| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691 |
- using Edge.Core.Processor;
- using Microsoft.EntityFrameworkCore;
- using Microsoft.Extensions.DependencyInjection;
- using Microsoft.Extensions.Logging;
- using Microsoft.Extensions.Logging.Abstractions;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading.Tasks;
- using Gateway.POS.Models;
- using Edge.Core.UniversalApi;
- using AutoMapper;
- using Edge.Core.Processor.Dispatcher.Attributes;
- using Gateway.Payment.Shared;
- namespace Gateway.POS
- {
- [MetaPartsDescriptor(
- "lang-zh-cn:轻简POSlang-en-us:Lite POS",
- "lang-zh-cn:轻简POSlang-en-us:Lite POS",
- new[] { "lang-zh-cn:轻简POSlang-en-us:LitePOS" })]
- public partial class App : IAppProcessor
- {
- private bool enableTestingMode = false;
- private Gateway.Payment.App paymentApp;
- private ClassicCpuCardApp.App classicCpuCardApp;
- private ILogger logger = NullLogger.Instance;
- private IServiceProvider services;
- public string MetaConfigName { get; set; }
- /// <summary>
- /// must be 6 digits
- /// </summary>
- private string siteId = "abcdef";
- public void Init(IEnumerable<IProcessor> processors)
- {
- this.paymentApp =
- processors.WithHandlerOrApp<Gateway.Payment.App>().SelectHandlerOrAppThenCast<Gateway.Payment.App>().FirstOrDefault();
- if (this.paymentApp == null)
- this.logger.LogInformation("There's no Gateway.Payment.App defined, so only support cash payment.");
- this.classicCpuCardApp =
- processors.WithHandlerOrApp<ClassicCpuCardApp.App>().SelectHandlerOrAppThenCast<ClassicCpuCardApp.App>().FirstOrDefault();
- if (this.classicCpuCardApp == null)
- this.logger.LogInformation("There's no ClassicCpuCardApp.App defined, so no support for cpu card.");
- }
- public App(bool enableTestingMode, IServiceProvider services)
- {
- this.services = services;
- var loggerFactory = services.GetRequiredService<ILoggerFactory>();
- this.logger = loggerFactory.CreateLogger("DynamicPrivate_Gateway.POS");
- this.enableTestingMode = enableTestingMode;
- }
- public Task<bool> Start()
- {
- this.logger.LogInformation("Migrating database...");
- var migrateDbContext = new PosAppDbContext();
- try
- {
- migrateDbContext.Database.Migrate();
- }
- catch (Exception exx)
- {
- string migrationsStr = "";
- string pendingMigrationsStr = "";
- string appliedMigrationsStr = "";
- try
- {
- migrationsStr = migrateDbContext.Database?.GetMigrations()?.Aggregate("", (acc, n) => acc + ", " + n) ?? "";
- pendingMigrationsStr = migrateDbContext.Database?.GetPendingMigrations()?.Aggregate("", (acc, n) => acc + ", " + n) ?? "";
- appliedMigrationsStr = migrateDbContext.Database?.GetAppliedMigrations()?.Aggregate("", (acc, n) => acc + ", " + n) ?? "";
- }
- catch
- {
- }
- this.logger.LogError("Gateway.POS App Exceptioned when Migrating the database, detail: " +
- exx + System.Environment.NewLine +
- "migrations are: " + migrationsStr + System.Environment.NewLine +
- ", pendingMigrations are: " + pendingMigrationsStr + System.Environment.NewLine +
- ", appliedMigrations are: " + appliedMigrationsStr);
- throw new InvalidOperationException("failed for migrating the database");
- }
- this.logger.LogInformation(" Migrate database finished.");
- return Task.FromResult(true);
- }
- //Task<bool> Stop() { return Task.FromResult(true); }
- [UniversalApi]
- public async Task<TransactionOutputDto> Commit(TransactionInputDto input)
- {
- var mapper = this.services.GetRequiredService<IMapper>();
- var trx = mapper.Map<Transaction>(input);
- trx.ServerSideTimestamp = DateTime.Now;
- try
- {
- var dbContext = new PosAppDbContext();
- var foundOp = await dbContext.Operators.FindAsync(new object[] { input.OperatorId });
- if (foundOp == null)
- {
- var output = mapper.Map<TransactionOutputDto>(trx);
- output.CommitState = new TransactionCommitState()
- {
- StateCode = 400,
- Reason = "Input OperatorId does not map to existed operator.",
- };
- return output;
- }
- trx.Operator = foundOp;
- if (trx.TransactionType == TransactionTypeEnum.Sale
- && (trx.Payments == null || !trx.Payments.Any()))
- {
- var output = mapper.Map<TransactionOutputDto>(trx);
- output.CommitState = new TransactionCommitState()
- {
- StateCode = 400,
- Reason = "Must provide at least one Payment.",
- };
- return output;
- }
- if (trx.TransactionType == TransactionTypeEnum.Sale && input.RefundTrxId != null)
- {
- var output = mapper.Map<TransactionOutputDto>(trx);
- output.CommitState = new TransactionCommitState()
- {
- StateCode = 400,
- Reason = "Trx with type Sale should not providing RefundTrxId.",
- };
- return output;
- }
- if (trx.TransactionType == TransactionTypeEnum.Sale
- && trx.Payments.Select(p => p.Method).Except(new[] { PaymentMethodEnum.Cash, PaymentMethodEnum.ClassicCpuCard, PaymentMethodEnum.DirectMembershipProfitAccountFundRedeem }).Any()
- && this.paymentApp == null)
- {
- var output = mapper.Map<TransactionOutputDto>(trx);
- output.CommitState = new TransactionCommitState()
- {
- StateCode = 400,
- Reason = "Only support Cash due to no other Mop enabled.",
- };
- return output;
- }
- if (trx.TransactionType == TransactionTypeEnum.Sale && trx.Payments.Count >= 2)
- {
- var output = mapper.Map<TransactionOutputDto>(trx);
- output.CommitState = new TransactionCommitState()
- {
- StateCode = 400,
- Reason = "Only support single payment for a trx.",
- };
- return output;
- }
- if (trx.TransactionType == TransactionTypeEnum.Sale && trx.Payments.Sum(p => p.ExpectAmount) != trx.NetAmount)
- {
- var output = mapper.Map<TransactionOutputDto>(trx);
- output.CommitState = new TransactionCommitState()
- {
- StateCode = 400,
- Reason = "Payment(s) expect amount(s) must exactly equals Trx.NetAmount since split payment is not support yet.",
- };
- return output;
- }
- if (trx.TransactionType == TransactionTypeEnum.Sale)
- {
- trx.ReceiptId = DateTime.Now.ToString("yyMMddHHmmssfff" + (trx.Operator?.Id.ToString() ?? "a"));
- if (trx.Payments.First().Method == PaymentMethodEnum.Cash)
- {
- trx.Payments.First().PaidAmount = trx.Payments.First().ExpectAmount;
- trx.Payments.First().TradeStatus = TradeStatusEnum.SUCCESS;
- }
- else
- {
- if (this.enableTestingMode)
- trx.NetAmount = new decimal(0.02);
- this.logger.LogDebug($"Committing with TrxType.Sale with MOP: {trx.Payments.First().Method }, netAmount: { trx.NetAmount.Value}, authCode: {trx.Payments.First().AuthCode}");
- if (trx.Payments.First().Method == PaymentMethodEnum.ClassicCpuCard)
- {
- var unitOfWorkDb = dbContext;
- var redeemInput = new Gateway.POS.Models.MembershipProfitAccountRedeemRequest();
- redeemInput.SourceTrx = trx;
- redeemInput.CreateByOperatorId = trx.OperatorId;
- redeemInput.Description = trx.Comment;
- redeemInput.ProfitAccountType = Gateway.POS.Models.MembershipProfitAccountProfitTypeEnum.Fund;
- redeemInput.Purpose = trx.Comment;
- redeemInput.RedeemAuthCode = trx.Payments.First().AuthCode;
- redeemInput.RedeemProfitAmount = trx.NetAmount;
- var redeemResult = await this.InternalRedeemMembershipProfitByOpenClassicCpuCardReaderAndReadCard(trx.Payments.First().CardReaderName, redeemInput, dbContext);
- if (redeemResult.OverallResultCode == 200)
- {
- this.logger.LogDebug(" Succeed for Commit with TrxType.Sale with MOP: " + trx.Payments.First().Method + ", netAmount: " + trx.NetAmount.Value);
- trx.Payments.First().PaidAmount = trx.NetAmount.Value;// trx.Payments.First().ExpectAmount;
- trx.Payments.First().TradeStatus = TradeStatusEnum.SUCCESS;
- trx.MembershipProfitAccountRedeem = redeemResult.Data as MembershipProfitAccountRedeem;
- }
- else
- {
- this.logger.LogDebug($" Failed for Commit with TrxType.Sale with MOP: {trx.Payments.First().Method}, netAmount: {trx.NetAmount.Value }: {redeemResult.Message.ToString()}");
- var output = mapper.Map<TransactionOutputDto>(trx);
- output.CommitState = new TransactionCommitState()
- {
- StateCode = 500,
- Reason = $"CPU卡支付失败: {redeemResult.Message}"
- };
- return output;
- }
- }
- else if (trx.Payments.First().Method == PaymentMethodEnum.DirectMembershipProfitAccountFundRedeem)
- {
- if (!trx.Payments.First().TargetMembershipSubAccountId.HasValue)
- {
- var output = mapper.Map<TransactionOutputDto>(trx);
- output.CommitState = new TransactionCommitState()
- {
- StateCode = 400,
- Reason = $"DirectMembershipProfitAccountFundRedeem must specify entry TargetMembershipSubAccountId in Payment"
- };
- return output;
- }
- var unitOfWorkDb = dbContext;
- var redeemInput = new Gateway.POS.Models.MembershipProfitAccountRedeemRequest();
- redeemInput.SourceTrx = trx;
- redeemInput.CreateByOperatorId = trx.OperatorId;
- redeemInput.Description = trx.Comment;
- redeemInput.ProfitAccountType = Gateway.POS.Models.MembershipProfitAccountProfitTypeEnum.Fund;
- redeemInput.Purpose = trx.Comment;
- redeemInput.RedeemAuthCode = trx.Payments.First().AuthCode;
- redeemInput.RedeemProfitAmount = trx.NetAmount;
- var redeemResult = await this.InternalRedeemMembershipProfit(trx.Payments.First().TargetMembershipSubAccountId.Value, redeemInput, dbContext);
- if (redeemResult.OverallResultCode == 200)
- {
- this.logger.LogDebug(" Succeed for Commit with TrxType.Sale with MOP: " + trx.Payments.First().Method + ", netAmount: " + trx.NetAmount.Value);
- trx.Payments.First().PaidAmount = trx.NetAmount.Value;// trx.Payments.First().ExpectAmount;
- trx.Payments.First().TradeStatus = TradeStatusEnum.SUCCESS;
- trx.MembershipProfitAccountRedeem = redeemResult.Data as MembershipProfitAccountRedeem;
- }
- else
- {
- this.logger.LogDebug($" Failed for Commit with TrxType.Sale with MOP: {trx.Payments.First().Method}, netAmount: {trx.NetAmount.Value }: {redeemResult.Message.ToString()}");
- var output = mapper.Map<TransactionOutputDto>(trx);
- output.CommitState = new TransactionCommitState()
- {
- StateCode = 500,
- Reason = $"DirectMembershipProfitAccountFundRedeem Payment failed with: {redeemResult.Message}"
- };
- return output;
- }
- }
- else
- {
- var po = await this.paymentApp.StartPayment(new PaymentOrderDto()
- {
- AuthCode = trx.Payments.First().AuthCode,
- PaymentMethod = trx.Payments.First().Method.ToString(),
- NetAmount = trx.NetAmount.Value,
- TotalAmount = trx.TotalAmount ?? trx.NetAmount.Value,
- OperatorId = trx.OperatorId.ToString(),
- SiteId = trx.SiteId,
- TerminalId = trx.TerminalId,
- Title = "sale from local fusion at " + DateTime.Now.ToLongTimeString(),
- IsForRefund = false
- });
- if (po.TradeStatus == TradeStatusEnum.SUCCESS)
- {
- this.logger.LogDebug(" Succeed for Commit with TrxType.Sale with MOP: " + trx.Payments.First().Method + ", netAmount: " + trx.NetAmount.Value + ", billNumber: " + po.BillNumber);
- trx.Payments.First().PaidAmount = trx.Payments.First().ExpectAmount;
- trx.Payments.First().BillNumber = po.BillNumber;
- trx.Payments.First().TradeStatus = TradeStatusEnum.SUCCESS;
- }
- else
- {
- this.logger.LogDebug($" Failed for Commit with TrxType.Sale with MOP: {trx.Payments.First().Method}, netAmount: {trx.NetAmount.Value }, Payment failed with PaymentResultMessage: {po.PayResults.FirstOrDefault()?.PaymentResultMessage ?? ""}, PaymentResultCode: { po.PayResults.FirstOrDefault()?.PaymentResultCode ?? ""}, PaymentResultErrorDetail: { po.PayResults.FirstOrDefault()?.PaymentResultErrorDetail ?? ""}, PaymentResultRawResult: { po.PayResults.FirstOrDefault()?.PaymentResultRawResult ?? ""}");
- var output = mapper.Map<TransactionOutputDto>(trx);
- output.CommitState = new TransactionCommitState()
- {
- StateCode = 500,
- Reason = $"Payment failed with PaymentResultMessage: {po.PayResults.FirstOrDefault()?.PaymentResultMessage ?? ""}, PaymentResultCode: {po.PayResults.FirstOrDefault()?.PaymentResultCode ?? ""}, PaymentResultErrorDetail: {po.PayResults.FirstOrDefault()?.PaymentResultErrorDetail ?? ""}, PaymentResultRawResult: {po.PayResults.FirstOrDefault()?.PaymentResultRawResult ?? ""}"
- };
- return output;
- }
- }
- }
- if (trx.TransactionSubType == TransactionSubTypeEnum.MembershipProfitAccount_Recharge_Fund_ToAccount_ById)
- {
- if (trx.Payments.First().TradeStatus != TradeStatusEnum.SUCCESS)
- {
- var output = mapper.Map<TransactionOutputDto>(trx);
- output.CommitState = new TransactionCommitState()
- {
- StateCode = 500,
- Reason = $"Recharge_Fund_ToAccount failed at Payment stage"
- };
- return output;
- }
- if ((trx.Payments.First().TargetMembershipAccountId ?? 0) == 0)
- {
- var output = mapper.Map<TransactionOutputDto>(trx);
- output.CommitState = new TransactionCommitState()
- {
- StateCode = 500,
- Reason = $"Recharge_Fund_ToAccount failed at Recharge stage, must specify the Target Membership Account Id, and a refund may requried since the real payment has done."
- };
- return output;
- }
- var unitOfWorkDb = dbContext;
- var recharge = new Gateway.POS.Models.MembershipProfitAccountRechargeRequest();
- recharge.SourceTrx = trx;
- recharge.CreateByOperatorId = trx.OperatorId;
- recharge.Description = trx.Comment;
- recharge.RechargeSource = ProfitAccountRechargeSourceEnum.BySystemTrx;
- recharge.RechargeAmount = trx.Payments.First().PaidAmount;
- var rechargeResult = await this.InternalRechargeMembershipAccount(
- trx.Payments.First().TargetMembershipAccountId.Value,
- MembershipProfitAccountProfitTypeEnum.Fund, recharge, unitOfWorkDb);
- if (rechargeResult.OverallResultCode == 200)
- {
- this.logger.LogDebug(" Succeed for Recharge with TrxType.Sale with MOP: " + trx.Payments.First().Method + ", netAmount: " + trx.NetAmount.Value);
- trx.MembershipProfitAccountRecharge = rechargeResult.Data as MembershipProfitAccountRecharge;
- }
- else
- {
- var output = mapper.Map<TransactionOutputDto>(trx);
- output.CommitState = new TransactionCommitState()
- {
- StateCode = 500,
- Reason = $"Recharge_Fund_ToAccount failed at Recharge stage, and a refund may requried since the real payment has done: {rechargeResult.Message ?? ""}"
- };
- return output;
- }
- }
- else if (trx.TransactionSubType == TransactionSubTypeEnum.MembershipProfitAccount_Recharge_Fund_ToSubAccount_ById)
- {
- if (trx.Payments.First().TradeStatus != TradeStatusEnum.SUCCESS)
- {
- var output = mapper.Map<TransactionOutputDto>(trx);
- output.CommitState = new TransactionCommitState()
- {
- StateCode = 500,
- Reason = $"Recharge_Fund_ToSubAccount failed at Payment stage"
- };
- return output;
- }
- if ((trx.Payments.First().TargetMembershipSubAccountId ?? 0) == 0)
- {
- var output = mapper.Map<TransactionOutputDto>(trx);
- output.CommitState = new TransactionCommitState()
- {
- StateCode = 500,
- Reason = $"Recharge_Fund_ToSubAccount failed at Recharge stage, must specify the Target Membership SubAccount Id, and a refund may requried since the real payment has done."
- };
- return output;
- }
- var unitOfWorkDb = dbContext;
- var recharge = new Gateway.POS.Models.MembershipProfitAccountRechargeRequest();
- recharge.SourceTrx = trx;
- recharge.CreateByOperatorId = trx.OperatorId;
- recharge.Description = trx.Comment;
- recharge.RechargeSource = ProfitAccountRechargeSourceEnum.BySystemTrx;
- recharge.RechargeAmount = trx.Payments.First().PaidAmount;
- var rechargeResult = await this.InternalRechargeMembershipSubAccount(
- trx.Payments.First().TargetMembershipSubAccountId.Value,
- MembershipProfitAccountProfitTypeEnum.Fund, recharge, unitOfWorkDb);
- if (rechargeResult.OverallResultCode == 200)
- {
- this.logger.LogDebug(" Succeed for Recharge with TrxType.Sale with MOP: " + trx.Payments.First().Method + ", netAmount: " + trx.NetAmount.Value);
- trx.MembershipProfitAccountRecharge = rechargeResult.Data as MembershipProfitAccountRecharge;
- }
- else
- {
- var output = mapper.Map<TransactionOutputDto>(trx);
- output.CommitState = new TransactionCommitState()
- {
- StateCode = 500,
- Reason = $"Recharge_Fund_ToSubAccount failed at Recharge stage, and a refund may requried since the real payment has done: {rechargeResult.Message ?? ""}"
- };
- return output;
- }
- }
- else if (trx.TransactionSubType == TransactionSubTypeEnum.MembershipProfitAccount_Recharge_Fund_ToSubAccount_ByCard)
- {
- if (trx.Payments.First().TradeStatus != TradeStatusEnum.SUCCESS)
- {
- var output = mapper.Map<TransactionOutputDto>(trx);
- output.CommitState = new TransactionCommitState()
- {
- StateCode = 500,
- Reason = $"Recharge_Fund_ToSubAccount failed at Payment stage"
- };
- return output;
- }
- var unitOfWorkDb = dbContext;
- var recharge = new Gateway.POS.Models.MembershipProfitAccountRechargeRequest();
- recharge.SourceTrx = trx;
- recharge.CreateByOperatorId = trx.OperatorId;
- recharge.Description = trx.Comment;
- recharge.RechargeSource = ProfitAccountRechargeSourceEnum.BySystemTrx;
- recharge.RechargeAmount = trx.Payments.First().PaidAmount;
- var rechargeResult = await this.InternalRechargeMembershipSubAccountByOpenClassicCpuCardReaderAndReadCard(
- trx.Payments.First().CardReaderName,
- MembershipProfitAccountProfitTypeEnum.Fund, recharge, unitOfWorkDb);
- if (rechargeResult.OverallResultCode == 200)
- {
- this.logger.LogDebug(" Succeed for Recharge with TrxType.Sale with MOP: " + trx.Payments.First().Method + ", netAmount: " + trx.NetAmount.Value);
- trx.MembershipProfitAccountRecharge = rechargeResult.Data as MembershipProfitAccountRecharge;
- }
- else
- {
- var output = mapper.Map<TransactionOutputDto>(trx);
- output.CommitState = new TransactionCommitState()
- {
- StateCode = 500,
- Reason = $"Recharge_Fund_ToSubAccount failed at Recharge stage, and a refund may requried since the real payment has done: {rechargeResult.Message ?? ""}"
- };
- return output;
- }
- }
- }
- else if (trx.TransactionType == TransactionTypeEnum.Refund)
- {
- if (input.RefundTrxId == null)
- {
- var output = mapper.Map<TransactionOutputDto>(trx);
- output.CommitState = new TransactionCommitState()
- {
- StateCode = 400,
- Reason = "Must provide original trx id for refund.",
- };
- return output;
- }
- var db = new PosAppDbContext();
- var originalTrx = await db.Transactions.Include(t => t.Payments).FirstOrDefaultAsync(t => t.Id == input.RefundTrxId);
- if (originalTrx == null)
- {
- var output = mapper.Map<TransactionOutputDto>(trx);
- output.CommitState = new TransactionCommitState()
- {
- StateCode = 400,
- Reason = $"Could not find original trx with id: {input.RefundTrxId.Value} for refund.",
- };
- return output;
- }
- if (originalTrx.TransactionType != TransactionTypeEnum.Sale)
- {
- var output = mapper.Map<TransactionOutputDto>(trx);
- output.CommitState = new TransactionCommitState()
- {
- StateCode = 400,
- Reason = $"Only can refund a previous exists Sale type trx.",
- };
- return output;
- }
- trx.ReceiptId = "R" + (originalTrx.ReceiptId ?? "");
- PaymentOrder paymentOrder = null;
- if (originalTrx.Payments.First().Method != PaymentMethodEnum.Cash)
- {
- if (string.IsNullOrEmpty(originalTrx.Payments.First().BillNumber))
- {
- var output = mapper.Map<TransactionOutputDto>(trx);
- output.CommitState = new TransactionCommitState()
- {
- StateCode = 400,
- Reason = $"Original trx does not contains the BillNumber in payment info which is the critical info for refund operation, contact administrator.",
- };
- return output;
- }
- this.logger.LogDebug("Committing with TrxType.Refund with MOP: " + trx.Payments.First().Method + ", netAmount: " + trx.NetAmount.Value + ", billNumber: " + originalTrx.Payments.First().BillNumber);
- paymentOrder = await this.paymentApp.StartPayment(new PaymentOrderDto()
- {
- AuthCode = originalTrx.Payments.First().AuthCode,
- PaymentMethod = originalTrx.Payments.First().Method.ToString(),
- BillNumber = originalTrx.Payments.First().BillNumber,
- NetAmount = originalTrx.Payments.First().PaidAmount,
- TotalAmount = originalTrx.TotalAmount ?? originalTrx.NetAmount.Value,
- OperatorId = originalTrx.OperatorId.ToString(),
- SiteId = originalTrx.SiteId,
- TerminalId = originalTrx.TerminalId,
- Title = "refund from local fusion at " + DateTime.Now.ToLongTimeString(),
- IsForRefund = true
- });
- }
- else
- {
- //cash always let it succeed.
- paymentOrder = new PaymentOrder();
- paymentOrder.TradeStatus = TradeStatusEnum.SUCCESS;
- }
- if (paymentOrder.TradeStatus == TradeStatusEnum.SUCCESS)
- {
- this.logger.LogDebug(" Succeed Committing with TrxType.Refund with MOP: " + trx.Payments.First().Method + ", netAmount: " + trx.NetAmount.Value + ", billNumber: " + originalTrx.Payments.First().BillNumber);
- trx.TotalAmount = -originalTrx.TotalAmount;
- trx.NetAmount = -originalTrx.NetAmount;
- trx.Payments.First().TradeStatus = TradeStatusEnum.SUCCESS;
- trx.Payments.First().ExpectAmount = -originalTrx.Payments.First().ExpectAmount;
- trx.Payments.First().PaidAmount = -originalTrx.Payments.First().PaidAmount;
- }
- else
- {
- this.logger.LogDebug($" Failed for Commit with TrxType.Refund with MOP: {trx.Payments.First().Method}, netAmount: {trx.NetAmount.Value }, billNumber: {originalTrx.Payments.First().BillNumber}, Payment failed with PaymentResultMessage: {paymentOrder.PayResults.FirstOrDefault()?.PaymentResultMessage ?? ""}, PaymentResultCode: { paymentOrder.PayResults.FirstOrDefault()?.PaymentResultCode ?? ""}, PaymentResultErrorDetail: { paymentOrder.PayResults.FirstOrDefault()?.PaymentResultErrorDetail ?? ""}, PaymentResultRawResult: { paymentOrder.PayResults.FirstOrDefault()?.PaymentResultRawResult ?? ""}");
- var output = mapper.Map<TransactionOutputDto>(trx);
- output.CommitState = new TransactionCommitState()
- {
- StateCode = 500,
- Reason = $"Payment(refund) failed with PaymentResultMessage: {paymentOrder.PayResults.FirstOrDefault()?.PaymentResultMessage ?? ""}, PaymentResultCode: {paymentOrder.PayResults.FirstOrDefault()?.PaymentResultCode ?? ""}, PaymentResultErrorDetail: {paymentOrder.PayResults.FirstOrDefault()?.PaymentResultErrorDetail ?? ""}, PaymentResultRawResult: {paymentOrder.PayResults.FirstOrDefault()?.PaymentResultRawResult ?? ""}"
- };
- return output;
- }
- }
- dbContext.Transactions.Add(trx);
- dbContext.Entry(trx.Operator).State = EntityState.Unchanged;
- await dbContext.SaveChangesAsync();
- var finalOutput = mapper.Map<TransactionOutputDto>(trx);
- finalOutput.CommitState = new TransactionCommitState()
- {
- StateCode = 200,
- Reason = "",
- };
- return finalOutput;
- }
- catch (Exception eeee)
- {
- this.logger.LogInformation($"Commit(trx) exceptioned: {eeee}");
- var output = mapper.Map<TransactionOutputDto>(trx);
- output.CommitState = new TransactionCommitState()
- {
- StateCode = 500,
- Reason = $"Generic exception in Commit(trx), detail: {eeee}",
- };
- return output;
- }
- }
- [UniversalApi]
- public async Task<List<TransactionOutputDto>> GetTransactionsByTimeRange(DateTime start, DateTime end, int pageRowCount, int pageIndex)
- {
- using (var db = new PosAppDbContext())
- {
- var results = await db.Transactions.Include(t => t.Payments).Include(t => t.Operator).Include(t => t.FuelItems).Include(t => t.AppliedDiscounts)
- .Include(t => t.MembershipProfitAccountRecharge)
- .Include(t => t.MembershipProfitAccountRedeem)
- .Where(t => t.ServerSideTimestamp >= start && t.ServerSideTimestamp <= end)
- .OrderByDescending(t => t.ServerSideTimestamp)
- .Skip(pageRowCount * pageIndex).Take(pageRowCount).ToListAsync();
- var mapper = this.services.GetRequiredService<IMapper>();
- var dtos = mapper.Map<List<TransactionOutputDto>>(results);
- return dtos;
- }
- }
- [UniversalApi]
- public async Task<OperatorOutputDto> ValidateOperatorLogon(string operatorName, string password)
- {
- using (var db = new PosAppDbContext())
- {
- var result = await db.Operators.FirstOrDefaultAsync(o => o.Name == operatorName && o.Password == password);
- if (result == null) return null;
- var mapper = this.services.GetRequiredService<IMapper>();
- var op = mapper.Map<OperatorOutputDto>(result);
- return op;
- }
- }
- [UniversalApi]
- public async Task<List<OperatorOutputDto>> GetOperators()
- {
- using (var db = new PosAppDbContext())
- {
- var results = await db.Operators.ToListAsync();
- if (results == null) return null;
- var mapper = this.services.GetRequiredService<IMapper>();
- var ops = mapper.Map<List<OperatorOutputDto>>(results);
- return ops;
- }
- }
- [UniversalApi]
- public async Task<OperatorOutputDto> CreateOperatorByAuthorizeCode(string authorizeCode, string newOpName, string newOpPassword, string newOpDescription)
- {
- if (authorizeCode != "666888")
- return null;
- if (string.IsNullOrEmpty(newOpName) || string.IsNullOrEmpty(newOpPassword))
- return null;
- using (var db = new PosAppDbContext())
- {
- var newOp = new Operator()
- {
- Name = newOpName,
- Password = newOpPassword,
- Description = newOpDescription,
- CreatedTimestamp = DateTime.Now
- };
- db.Operators.Add(newOp);
- var c = await db.SaveChangesAsync();
- if (c != 1)
- {
- this.logger.LogInformation($"Create operator with name: {newOpName ?? ""}, pwd: {newOpPassword ?? ""} failed due to effected db row count is not 1.");
- return null;
- }
- var mapper = this.services.GetRequiredService<IMapper>();
- var op = mapper.Map<OperatorOutputDto>(newOp);
- return op;
- }
- }
- [UniversalApi]
- public async Task<OperatorOutputDto> ResetOperatorPasswordByAuthorizeCode(string authorizeCode, string opName, string newOpPassword)
- {
- if (authorizeCode != "666888")
- return null;
- if (string.IsNullOrEmpty(opName) || string.IsNullOrEmpty(newOpPassword))
- return null;
- using (var db = new PosAppDbContext())
- {
- var updatedOp = await db.Operators.FirstOrDefaultAsync(op => op.Name == opName);
- if (updatedOp == null) return null;
- updatedOp.Password = newOpPassword;
- var c = await db.SaveChangesAsync();
- if (c != 1)
- {
- this.logger.LogInformation($"Reset operator pwd with name: {opName ?? ""}, newPwd: {newOpPassword ?? ""} failed due to effected db row count is not 1.");
- return null;
- }
- var mapper = this.services.GetRequiredService<IMapper>();
- var op = mapper.Map<OperatorOutputDto>(updatedOp);
- return op;
- }
- }
- [UniversalApi(Description = "Update or insert a discount, providing the non-zero Id property for update, otherwise for insert.")]
- public async Task<DiscountDto> UpsertDiscount(DiscountDto input)
- {
- var dbContext = new PosAppDbContext();
- var mapper = this.services.GetRequiredService<IMapper>();
- var discount = mapper.Map<Discount>(input);
- if (input.Id == null || input.Id == 0)
- {
- /*create one in db*/
- discount.CreatedTime = DateTime.Now;
- dbContext.Discounts.Add(discount);
- await dbContext.SaveChangesAsync();
- }
- else
- {
- /*udpate one in db*/
- discount.ModifiedTime = DateTime.Now;
- dbContext.Entry(discount).State = Microsoft.EntityFrameworkCore.EntityState.Modified;
- dbContext.Entry(discount).Property(c => c.CreatedTime).IsModified = false;
- //dbContext.Entry(inputTankOverallConfig).Property(c => c.ModifiedTimeStamp).IsModified = true;
- await dbContext.SaveChangesAsync();
- }
- return mapper.Map<DiscountDto>(discount);
- }
- [UniversalApi(Description = "Get all discounts")]
- public async Task<List<DiscountDto>> GetDiscounts()
- {
- var dbContext = new PosAppDbContext();
- var results = await dbContext.Discounts.ToListAsync();
- var mapper = this.services.GetRequiredService<IMapper>();
- return mapper.Map<List<DiscountDto>>(results);
- }
- }
- }
|