Commit 249172c7 by 陶然

新增导入发票功能

parent 65f88acb
...@@ -253,5 +253,7 @@ namespace Kivii.Finances.Entities ...@@ -253,5 +253,7 @@ namespace Kivii.Finances.Entities
#endregion #endregion
[Ignore]
public List<InvoiceDetail> Details { get; set; }
} }
} }
...@@ -91,4 +91,164 @@ namespace Kivii.Finances.Transforms ...@@ -91,4 +91,164 @@ namespace Kivii.Finances.Transforms
[RequiresAnyRole(SystemRoles.Everyone)] [RequiresAnyRole(SystemRoles.Everyone)]
public class InvoiceRead : RestfulRead<Invoice> public class InvoiceRead : RestfulRead<Invoice>
{ } { }
[Api(Description = "插入发票")]
[RequiresAnyRole(SystemRoles.Everyone)]
public class InvoiceAccept : RestfulExecution<Invoice>
{
public List<Invoice> Items { get; set; }
public List<Payment> Payments { get; set; }
public override object OnExecution(IRequest req, IResponse res)
{
Items.ThrowIfNullOrEmpty("开票结果内容不能为空!");
foreach (var item in Items)
{
(item.OperateTime == DateTime.MinValue || item.OperateTime == DateTime.MaxValue).ThrowIfTrue("缺少开票日期信息!");
item.SerialCode.ThrowIfNullOrEmpty("缺少发票代码信息!");
item.SerialNumber.ThrowIfNullOrEmpty("缺少发票号码信息!");
item.Type.ThrowIfNullOrEmpty("缺少发票类型信息!");
(item.TaxRate < 0 || item.TaxRate > 1).ThrowIfTrue("缺少发票税率信息!");
(item.Amount == 0).ThrowIfTrue("缺少发票金额信息!");
item.Details.ThrowIfNullOrEmpty("缺少发票明细信息!");
(item.Amount != item.Details.Sum(o => o.Amount)).ThrowIfTrue("明细金额和传入发票金额不一致!");
}
if (!Payments.IsNullOrEmpty())
{
(Payments.Exists(o => o.Kvid == Guid.Empty)).ThrowIfTrue("不存在的到账信息!");
(Payments.Exists(o => o.Amount <= 0)).ThrowIfTrue("未指定到账开票金额!");
(Payments.Sum(o => o.Amount) != Items.Sum(o => o.Amount)).ThrowIfTrue("到账开票金额和发票金额不一致!");
}
var conn = KiviiContext.GetOpenedDbConnection<Invoice>();
(conn.Exists<Invoice>(o => Sql.In(o.SerialNumber, Items.ConvertAll(p => p.SerialNumber)))).ThrowIfTrue("存在重复录入的发票信息");
List<Payment> preCorrelatingPayments = new List<Payment>();
List<Payment> parentPayments = new List<Payment>();//也要更新父级的AmountInvoice
var insertInvoices = new List<Invoice>();
var insertInvoiceDetails = new List<InvoiceDetail>();
if (!Payments.IsNullOrEmpty())
{
var existPayments = conn.SelectByIds<Payment>(Payments.ConvertAll(o => o.Kvid));
existPayments.ThrowIfNullOrEmpty("未找到指定的到账信息!");
(existPayments.Count != Payments.Count).ThrowIfTrue("指定的到账信息与查询到的到账信息不匹配!");
existPayments.Exists(o => o.Type != PaymentType.Bank && o.Type != PaymentType.AliPay && o.Type != PaymentType.Cash && o.Type != PaymentType.Pos && o.Type != PaymentType.Split && o.Type != PaymentType.WeChat).ThrowIfTrue("存在不正确的到账类型");
foreach (var item in existPayments)
{
var payment = Payments.FirstOrDefault(o => o.Kvid == item.Kvid);
if (payment == null) continue;
if (item.Amount - item.AmountInvoice < payment.Amount) throw new Exception($"所选到账{item.SerialNumber},不足以继续开票指定金额{payment.Amount}元,当前到账剩余开票金额为:{item.Amount - item.AmountInvoice}元");
if (item.Amount - item.AmountInvoice >= payment.Amount)//说明选中的到账足以开票指定的金额
{
item.Amount = payment.Amount;
item.AmountInvoice = 0;
item.RemoveAllOnlyProperties();
preCorrelatingPayments.Add(item);
}
}
(preCorrelatingPayments.Sum(o => o.Amount) != Items.Sum(o => o.Amount)).ThrowIfTrue("指定的到账开票金额和发票金额不一致!");
}
foreach (var info in Items)
{
#region 开票成功的情况处理
var category = preCorrelatingPayments.IsNullOrEmpty() ? InvoiceApplyType.Debit : InvoiceApplyType.Payment;
var invoiceKvid = Guid.NewGuid();
var invoice = new Invoice();
invoice.RootKvid = invoiceKvid;
invoice.Kvid = invoiceKvid;
//invoice.ApplyKvid = ApplyKvid;
invoice.OwnerKvid = info.OwnerKvid;
invoice.OwnerName = info.OwnerName;
invoice.Currency = CurrencyUnit.CNY;
invoice.Type = info.Type;
invoice.Category = category.ToString();
invoice.OperateTime = info.OperateTime;
invoice.SerialCode = info.SerialCode ;
invoice.SerialNumber = info.SerialNumber;
//invoice.Status = 1;
invoice.TaxRate = info.TaxRate;
invoice.Amount = info.Amount;
invoice.AmountUntaxed = Math.Round(invoice.Amount / (1 + invoice.TaxRate), 2);
invoice.AmountTax = invoice.Amount - invoice.AmountUntaxed;
invoice.PayeeKvid = info.PayeeKvid;
invoice.PayeeName = info.PayeeName;
invoice.PayeeTaxNumber = info.PayeeTaxNumber;
invoice.PayeeCompanyAddress = info.PayeeCompanyAddress;
invoice.PayeePhone = info.PayeePhone;
invoice.PayeeRegisteredBank = info.PayeeRegisteredBank;
invoice.PayeeBankAccount = info.PayeeBankAccount;
invoice.PayerKvid = info.PayerKvid;
invoice.PayerName = info.PayerName;
invoice.PayerTaxNumber = info.PayerTaxNumber;
invoice.PayerCompanyAddress = info.PayerCompanyAddress;
invoice.PayerPhone = info.PayerPhone;
invoice.PayerRegisteredBank = info.PayerRegisteredBank;
invoice.PayerBankAccount = info.PayerBankAccount;
invoice.OperatorName = info.OperatorName;
invoice.Remark = info.Remark;
invoice.Metadata = new Dictionary<string, string>();
invoice.Metadata["PayeeOperatorName"] = info.Metadata.ContainsKey("PayeeOperatorName") ? info.Metadata["PayeeOperatorName"] : "";
invoice.Metadata["ReviewerName"] = info.Metadata.ContainsKey("ReviewerName") ? info.Metadata["ReviewerName"] : "";
insertInvoices.Add(invoice);
foreach (var infoDetail in info.Details)
{
var detail = new InvoiceDetail();
detail.PopulateInstance(infoDetail);
detail.InvoiceKvid = invoiceKvid;
detail.TaxRate = invoice.TaxRate;
detail.AmountUntaxed = invoice.AmountUntaxed;
detail.Amount = invoice.Amount;
detail.AmountTax = invoice.AmountTax;
detail.QuantityUnitPriceUntaxed = Math.Round(detail.AmountUntaxed / detail.Quantity, 2);
insertInvoiceDetails.Add(detail);
}
#endregion
}
if (!preCorrelatingPayments.IsNullOrEmpty())
{
var correlatedInvoices = insertInvoices.Correlating(preCorrelatingPayments);
insertInvoices.AddRange(correlatedInvoices);
var currentRootKvids = preCorrelatingPayments.Where(o => o.Type == PaymentType.Split).ToList().ConvertAll(p => p.RootKvid);
if (!currentRootKvids.IsNullOrEmpty()) parentPayments = conn.Select<Payment>(o => o.OffsetKvid == Guid.Empty && Sql.In(o.Kvid, currentRootKvids));
}
var rtns = new RestfulUpdateResponse<Invoice>();
rtns.Results = new List<Invoice>();
var trans = conn.OpenTransaction();
try
{
if (!insertInvoices.IsNullOrEmpty())
{
foreach (var item in insertInvoices)
{
if (item.Type == "Relation") item.SerialNumber = item.GetSubSerialNumber(conn);
conn.Insert(item);
if (item.Type != "Relation") rtns.Results.Add(item);
}
}
if (!insertInvoiceDetails.IsNullOrEmpty()) insertInvoiceDetails.ForEach(o => conn.Insert(o));
if (!preCorrelatingPayments.IsNullOrEmpty())
{
preCorrelatingPayments.ForEach(o => conn.UpdateOnly(o));
}
if (!parentPayments.IsNullOrEmpty())
{
parentPayments.ForEach(o => o.RecalculateAmountInvoice(conn));
}
trans.Commit();
return rtns;
}
catch (Exception ex)
{
trans.Rollback();
throw ex;
}
}
}
} }
...@@ -533,18 +533,13 @@ namespace Kivii.Finances.Transforms ...@@ -533,18 +533,13 @@ namespace Kivii.Finances.Transforms
if (OperatorKvid != Guid.Empty) query.And(o => o.OperatorKvid == OperatorKvid); if (OperatorKvid != Guid.Empty) query.And(o => o.OperatorKvid == OperatorKvid);
else if (OwnerKvid != Guid.Empty) query.And(o => o.OwnerKvid == OwnerKvid); else if (OwnerKvid != Guid.Empty) query.And(o => o.OwnerKvid == OwnerKvid);
else if (OrganizationKvid != Guid.Empty) query.And(o => o.OrganizationKvid == OrganizationKvid); else if (OrganizationKvid != Guid.Empty) query.And(o => o.OrganizationKvid == OrganizationKvid);
var apply = conn.Single(query); var applys = conn.Select(query);
var rtns = new RestfulQueryResponse<InvoiceApply>(); var rtns = new RestfulQueryResponse<InvoiceApply>();
rtns.Results = new List<InvoiceApply>(); rtns.Results = new List<InvoiceApply>();
if (apply == null) return rtns; if (applys == null) return rtns;
rtns.Results.AddRange(applys);
apply.Status = (int)InvoiceApplyStatus.AutoExecuting;
apply.AddOnlyProperties(o => o.Status);
conn.UpdateOnly(apply);
apply.RemoveAllOnlyProperties();
rtns.Results.Add(apply);
rtns.Total = rtns.Results.Count; rtns.Total = rtns.Results.Count;
return rtns; return rtns;
...@@ -664,7 +659,7 @@ namespace Kivii.Finances.Transforms ...@@ -664,7 +659,7 @@ namespace Kivii.Finances.Transforms
invoice.OperateTime = time; invoice.OperateTime = time;
invoice.SerialCode = code; invoice.SerialCode = code;
invoice.SerialNumber = number; invoice.SerialNumber = number;
invoice.Status = 1; //invoice.Status = 1;
invoice.Amount = currentDetails.Sum(o => o.Amount); invoice.Amount = currentDetails.Sum(o => o.Amount);
invoice.AmountTax = currentDetails.Sum(o => o.AmountTax); invoice.AmountTax = currentDetails.Sum(o => o.AmountTax);
invoice.AmountUntaxed = currentDetails.Sum(o => o.AmountUntaxed); invoice.AmountUntaxed = currentDetails.Sum(o => o.AmountUntaxed);
...@@ -855,7 +850,7 @@ namespace Kivii.Finances.Transforms ...@@ -855,7 +850,7 @@ namespace Kivii.Finances.Transforms
invoice.OperateTime = time; invoice.OperateTime = time;
invoice.SerialCode = code; invoice.SerialCode = code;
invoice.SerialNumber = number; invoice.SerialNumber = number;
invoice.Status = 1; //invoice.Status = 1;
invoice.Amount = currentAmount; invoice.Amount = currentAmount;
invoice.AmountUntaxed = Math.Round(currentAmount / (1 + taxRate), 2); invoice.AmountUntaxed = Math.Round(currentAmount / (1 + taxRate), 2);
invoice.AmountTax = currentAmount - invoice.AmountUntaxed; invoice.AmountTax = currentAmount - invoice.AmountUntaxed;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment