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; }
///
/// must be 6 digits
///
private string siteId = "abcdef";
public void Init(IEnumerable processors)
{
this.paymentApp =
processors.WithHandlerOrApp().SelectHandlerOrAppThenCast().FirstOrDefault();
if (this.paymentApp == null)
this.logger.LogInformation("There's no Gateway.Payment.App defined, so only support cash payment.");
this.classicCpuCardApp =
processors.WithHandlerOrApp().SelectHandlerOrAppThenCast().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();
this.logger = loggerFactory.CreateLogger("DynamicPrivate_Gateway.POS");
this.enableTestingMode = enableTestingMode;
}
public Task 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 Stop() { return Task.FromResult(true); }
[UniversalApi]
public async Task Commit(TransactionInputDto input)
{
var mapper = this.services.GetRequiredService();
var trx = mapper.Map(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(trx);
finalOutput.CommitState = new TransactionCommitState()
{
StateCode = 200,
Reason = "",
};
return finalOutput;
}
catch (Exception eeee)
{
this.logger.LogInformation($"Commit(trx) exceptioned: {eeee}");
var output = mapper.Map(trx);
output.CommitState = new TransactionCommitState()
{
StateCode = 500,
Reason = $"Generic exception in Commit(trx), detail: {eeee}",
};
return output;
}
}
[UniversalApi]
public async Task> 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();
var dtos = mapper.Map>(results);
return dtos;
}
}
[UniversalApi]
public async Task 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();
var op = mapper.Map(result);
return op;
}
}
[UniversalApi]
public async Task> GetOperators()
{
using (var db = new PosAppDbContext())
{
var results = await db.Operators.ToListAsync();
if (results == null) return null;
var mapper = this.services.GetRequiredService();
var ops = mapper.Map>(results);
return ops;
}
}
[UniversalApi]
public async Task 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();
var op = mapper.Map(newOp);
return op;
}
}
[UniversalApi]
public async Task 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();
var op = mapper.Map(updatedOp);
return op;
}
}
[UniversalApi(Description = "Update or insert a discount, providing the non-zero Id property for update, otherwise for insert.")]
public async Task UpsertDiscount(DiscountDto input)
{
var dbContext = new PosAppDbContext();
var mapper = this.services.GetRequiredService();
var discount = mapper.Map(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(discount);
}
[UniversalApi(Description = "Get all discounts")]
public async Task> GetDiscounts()
{
var dbContext = new PosAppDbContext();
var results = await dbContext.Discounts.ToListAsync();
var mapper = this.services.GetRequiredService();
return mapper.Map>(results);
}
}
}