Commit c5c35d0e by 陶然

优化

parent 84f2e5cb
......@@ -215,7 +215,6 @@ namespace Kivii.Finances.Entities
public DateTime OperateTime { get; set; }
[ApiMember(Description = "支付日期")]
[InternalSetter]
public DateTime? PayedTime { get; set; }
[IgnoreUpdate]
......
......@@ -217,6 +217,10 @@ namespace Kivii.Finances.Entities
[StringLength(2000), Default("")]
public string Remark { get; set; }
#endregion
[Ignore]
public List<InvoiceApplyDetail> Details { get; set; }
}
public enum InvoiceApplyType
......
......@@ -152,7 +152,6 @@ namespace Kivii.Finances.Entities
#region 文本 摘要 备注
[ApiMember(Description = "摘要,最大500字")]
[IgnoreUpdate]
[StringLength(500), Default("")]
public string Summary { get; set; }
......
......@@ -89,8 +89,32 @@ namespace Kivii.Finances.Transforms
{ }
[RequiresAnyRole(SystemRoles.Everyone)]
public class InvoiceUpdate : RestfulUpdate<Invoice>
{
}
[RequiresAnyRole(SystemRoles.Everyone)]
public class InvoiceRead : RestfulRead<Invoice>
{ }
{
public bool IncludeDetail { get; set; }
public override bool OnPostRestfulRead(IRequest req, IResponse res, System.Data.IDbConnection dbConnection, IRestfulReadResponse<Invoice> rtns)
{
if (IncludeDetail)
{
var details = dbConnection.Select<InvoiceDetail>(o => o.InvoiceKvid == Kvid);
rtns.Result.Details = new List<InvoiceDetail>();
foreach (var item in details)
{
var detail = new InvoiceDetail();
detail.PopulateWith(item);
rtns.Result.Details.Add(detail);
}
}
return base.OnPostRestfulRead(req, res, dbConnection, rtns);
}
}
[Api(Description = "插入发票")]
[RequiresAnyRole(SystemRoles.Everyone)]
......@@ -119,7 +143,6 @@ namespace Kivii.Finances.Transforms
(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("存在重复录入的发票信息");
......
......@@ -515,8 +515,8 @@ namespace Kivii.Finances.Transforms
#endregion
#region 开票客户端对接
[RequiresAnyRole(SystemRoles.Everyone)]
[Api(Description = "获取一条")]
[RequiresAnyRole(SystemRoles.Everyone)]
public class InvoiceApplyExecuting : RestfulExecution<InvoiceApply>
{
/// <summary>
......@@ -539,7 +539,16 @@ namespace Kivii.Finances.Transforms
rtns.Results = new List<InvoiceApply>();
if (applys == null) return rtns;
rtns.Results.AddRange(applys);
var queryDetails = conn.From<InvoiceApplyDetail>();
queryDetails.Where(o => Sql.In(o.ApplyKvid, applys.ConvertAll(p => p.Kvid)));
var details = conn.Select(queryDetails);
foreach (var item in applys)
{
item.Details = new List<InvoiceApplyDetail>();
var currents = details.Where(o => o.ApplyKvid == item.Kvid).ToList();
if (!currents.IsNullOrEmpty()) item.Details.AddRange(currents);
rtns.Results.Add(item);
}
rtns.Total = rtns.Results.Count;
return rtns;
......@@ -552,47 +561,30 @@ namespace Kivii.Finances.Transforms
{
public Guid ApplyKvid { get; set; }
public string FileContent { get; set; }
//发票开具最大额度限制 默认10万
public decimal Limit { get; set; } = 100000;
public List<Invoice> Items { get; set; }
public override object OnExecution(IRequest req, IResponse res)
{
ApplyKvid.ThrowIfEmpty("发票申请Kvid 不能为空!");
FileContent.ThrowIfNullOrEmpty("开票结果内容不能为空!");
var contents = FileContent.Replace("\r", "\n").Split('\n').ToList();
List<List<string>> infos = new List<List<string>>();
foreach (var content in contents)
Items.ThrowIfNullOrEmpty("开票结果内容不能为空!");
foreach (var item in Items)
{
if (content.IsNullOrEmpty()) continue;
var info = content.Replace(" ", "").Replace("[", "").Replace("]", ",").Replace("\n", "").Split(',').ToList();
(info.Count() < 3).ThrowIfTrue("文件内容格式不正确!");
infos.Add(info);
(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("明细金额和传入发票金额不一致!");
}
var conn = KiviiContext.GetOpenedDbConnection<InvoiceApply>();
conn.InitEntityType<Invoice>();
(conn.Exists<Invoice>(o => Sql.In(o.SerialNumber, Items.ConvertAll(p => p.SerialNumber)))).ThrowIfTrue("存在重复录入的发票信息");
var apply = conn.SingleById<InvoiceApply>(ApplyKvid);
apply.ThrowIfNull("未找到对应发票申请信息!");
(apply.AmountInvoice == apply.Amount).ThrowIfTrue("此发票申请已开具发票!");
var applyDetails = conn.Select<InvoiceApplyDetail>(o => o.ApplyKvid == ApplyKvid);
applyDetails.ThrowIfNullOrEmpty("未找到对应发票申请明细信息!");
//拆分applyDetail (超10万的)
var applyDetailSplited = new List<InvoiceApplyDetail>();
//只有一条明细的情况下 需要对明细进行拆分超过10万的部分
if (applyDetails.Count == 1) applyDetailSplited = applyDetails[0].SplitApplyDetail(Limit);
//多条明细的情况 不进行拆分了 但要判断下要是超过10万就要报错了
else
{
var group = applyDetails.GroupBy(o => o.GoodsId);
foreach (var kv in group)
{
var sum = kv.Sum(o => o.Amount);
if (sum > Limit) throw new Exception($"存在单张发票明细超过{Limit}元 无法创建!");
}
applyDetailSplited = applyDetails;
}
(applyDetailSplited.Sum(o => o.Amount) != apply.Amount).ThrowIfTrue("要生成的发票金额之和不等于申请金额!");
(apply.AmountInvoice >= apply.Amount).ThrowIfTrue("此发票申请已开具发票!");
(apply.Amount - apply.AmountInvoice < Items.Sum(o => o.Amount)).ThrowIfTrue("当前申请金额小于要录入的发票金额!");
var applyRelations = conn.Select<InvoiceApply>(o => o.ParentKvid == apply.Kvid && o.OperateType == InvoiceApplyType.Related && o.OffsetKvid == Guid.Empty);
var logs = new List<EntityLog<InvoiceApply>>();
......@@ -600,50 +592,15 @@ namespace Kivii.Finances.Transforms
var insertInvoices = new List<Invoice>();
var insertInvoiceDetails = new List<InvoiceDetail>();
foreach (var info in infos)
{
#region 开票失败的情况处理
if (info[2] != "开具结果:1")
{
apply.Status = (int)InvoiceApplyStatus.ErrorInsertInvoice;
apply.AddOnlyProperties(o => o.Status);
apply.Remark = $"开票失败! {info.Join(",")}";
apply.AddOnlyProperties(o => o.Remark);
//apply.AmountUsed = 0;
//apply.AddOnlyProperties(o => o.AmountUsed);
updateApplys.Add(apply);
//conn.UpdateOnly(apply);
if (!applyRelations.IsNullOrEmpty())
{
foreach (var item in applyRelations)
foreach (var info in Items)
{
item.Status = -1;
item.AddOnlyProperties(o => o.Status);
updateApplys.Add(item);
//conn.UpdateOnly(item);
}
}
var log = new EntityLog<InvoiceApply>();
log.OwnerKvid = apply.Kvid;
log.BizId = apply.SerialNumber;
log.BizKvid = apply.Kvid;
log.BizType = typeof(InvoiceApply).FullName;
log.Title = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
log.Remark = $"编号:{apply.SerialNumber} 申请失败,原因:{info.Join(",")}";
logs.Add(log);
continue;
}
#endregion
#region 开票成功的情况处理
var time = DateTime.ParseExact(info[0], "yyyy-MM-ddHH:mm:ss", CultureInfo.InvariantCulture);//开票时间
var code = info[4];//开票代码
var number = System.Text.RegularExpressions.Regex.Replace(info[5], @"[^0-9]+", "");//开票号码,唯一
var type = info[3].Split(':')[1];//开票类型
var group = info[1].Split(':')[1];
var currentDetails = group.IsNullOrEmpty() ? applyDetailSplited : applyDetailSplited.Where(o => o.GoodsId == group).ToList();
var time = info.OperateTime;//DateTime.ParseExact(info[0], "yyyy-MM-ddHH:mm:ss", CultureInfo.InvariantCulture);//开票时间
var code = info.SerialCode;//info[4];//开票代码
var number = info.SerialNumber;//System.Text.RegularExpressions.Regex.Replace(info[5], @"[^0-9]+", "");//开票号码,唯一
var type = info.Type;//info[3].Split(':')[1];//开票类型
var currentAmount = info.Amount;
var taxRate = info.TaxRate;
var invoiceKvid = Guid.NewGuid();
var invoice = new Invoice();
......@@ -660,10 +617,10 @@ namespace Kivii.Finances.Transforms
invoice.SerialCode = code;
invoice.SerialNumber = number;
//invoice.Status = 1;
invoice.Amount = currentDetails.Sum(o => o.Amount);
invoice.AmountTax = currentDetails.Sum(o => o.AmountTax);
invoice.AmountUntaxed = currentDetails.Sum(o => o.AmountUntaxed);
invoice.TaxRate = currentDetails[0].TaxRate;
invoice.Amount = currentAmount;
invoice.AmountUntaxed = Math.Round(currentAmount / (1 + taxRate), 2);
invoice.AmountTax = currentAmount - invoice.AmountUntaxed;
invoice.TaxRate = taxRate;
invoice.PayeeKvid = apply.PayeeKvid;
invoice.PayeeName = apply.PayeeName;
invoice.PayeeTaxNumber = apply.PayeeTaxNumber;
......@@ -687,20 +644,17 @@ namespace Kivii.Finances.Transforms
insertInvoices.Add(invoice);
//conn.Insert(invoice);
foreach (var item in currentDetails)
foreach (var infoDetail in info.Details)
{
var detail = new InvoiceDetail();
detail.PopulateInstance(infoDetail);
detail.InvoiceKvid = invoiceKvid;
detail.GoodsFullName = item.GoodsFullName;
detail.GoodsSpecifications = item.GoodsSpecifications;
detail.Quantity = item.Quantity;
detail.QuantityUnitPriceUntaxed = item.QuantityUnitPriceUntaxed;
detail.AmountUntaxed = item.AmountUntaxed;
detail.Amount = item.Amount;
detail.AmountTax = item.AmountTax;
detail.TaxRate = item.TaxRate;
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);
//conn.Insert(detail);
}
#endregion
......@@ -743,7 +697,7 @@ namespace Kivii.Finances.Transforms
{
var correlatedInvoices = insertInvoices.Correlating(payments);
insertInvoices.AddRange(correlatedInvoices);
var currentRootKvids = payments.Where(o => o.Type==PaymentType.Split).ToList().ConvertAll(p => p.RootKvid);
var currentRootKvids = payments.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));
}
#endregion
......@@ -791,13 +745,13 @@ namespace Kivii.Finances.Transforms
}
}
[RequiresAnyRole(SystemRoles.Everyone)]
[Api(Description = "开票结果回写2")]
[RequiresAnyRole(SystemRoles.Everyone)]
public class InvoiceApplyResult2 : RestfulExecution<InvoiceApply>
{
public Guid ApplyKvid { get; set; }
public List<Invoice> Items { get; set; }
public string FileContent { get; set; }
//发票开具最大额度限制 默认10万
public decimal Limit { get; set; } = 100000;
......@@ -805,20 +759,39 @@ namespace Kivii.Finances.Transforms
public override object OnExecution(IRequest req, IResponse res)
{
ApplyKvid.ThrowIfEmpty("发票申请Kvid 不能为空!");
Items.ThrowIfNullOrEmpty("开票结果内容不能为空!");
foreach (var item in Items)
FileContent.ThrowIfNullOrEmpty("开票结果内容不能为空!");
var contents = FileContent.Replace("\r", "\n").Split('\n').ToList();
List<List<string>> infos = new List<List<string>>();
foreach (var content in contents)
{
(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("缺少发票金额信息!");
if (content.IsNullOrEmpty()) continue;
var info = content.Replace(" ", "").Replace("[", "").Replace("]", ",").Replace("\n", "").Split(',').ToList();
(info.Count() < 3).ThrowIfTrue("文件内容格式不正确!");
infos.Add(info);
}
var conn = KiviiContext.GetOpenedDbConnection<InvoiceApply>();
var apply = conn.SingleById<InvoiceApply>(ApplyKvid);
apply.ThrowIfNull("未找到对应发票申请信息!");
(apply.AmountInvoice == apply.Amount).ThrowIfTrue("此发票申请已开具发票!");
var applyDetails = conn.Select<InvoiceApplyDetail>(o => o.ApplyKvid == ApplyKvid);
applyDetails.ThrowIfNullOrEmpty("未找到对应发票申请明细信息!");
//拆分applyDetail (超10万的)
var applyDetailSplited = new List<InvoiceApplyDetail>();
//只有一条明细的情况下 需要对明细进行拆分超过10万的部分
if (applyDetails.Count == 1) applyDetailSplited = applyDetails[0].SplitApplyDetail(Limit);
//多条明细的情况 不进行拆分了 但要判断下要是超过10万就要报错了
else
{
var group = applyDetails.GroupBy(o => o.GoodsId);
foreach (var kv in group)
{
var sum = kv.Sum(o => o.Amount);
if (sum > Limit) throw new Exception($"存在单张发票明细超过{Limit}元 无法创建!");
}
applyDetailSplited = applyDetails;
}
(applyDetailSplited.Sum(o => o.Amount) != apply.Amount).ThrowIfTrue("要生成的发票金额之和不等于申请金额!");
var applyRelations = conn.Select<InvoiceApply>(o => o.ParentKvid == apply.Kvid && o.OperateType == InvoiceApplyType.Related && o.OffsetKvid == Guid.Empty);
var logs = new List<EntityLog<InvoiceApply>>();
......@@ -826,15 +799,50 @@ namespace Kivii.Finances.Transforms
var insertInvoices = new List<Invoice>();
var insertInvoiceDetails = new List<InvoiceDetail>();
foreach (var info in Items)
foreach (var info in infos)
{
#region 开票失败的情况处理
if (info[2] != "开具结果:1")
{
apply.Status = (int)InvoiceApplyStatus.ErrorInsertInvoice;
apply.AddOnlyProperties(o => o.Status);
apply.Remark = $"开票失败! {info.Join(",")}";
apply.AddOnlyProperties(o => o.Remark);
//apply.AmountUsed = 0;
//apply.AddOnlyProperties(o => o.AmountUsed);
updateApplys.Add(apply);
//conn.UpdateOnly(apply);
if (!applyRelations.IsNullOrEmpty())
{
foreach (var item in applyRelations)
{
item.Status = -1;
item.AddOnlyProperties(o => o.Status);
updateApplys.Add(item);
//conn.UpdateOnly(item);
}
}
var log = new EntityLog<InvoiceApply>();
log.OwnerKvid = apply.Kvid;
log.BizId = apply.SerialNumber;
log.BizKvid = apply.Kvid;
log.BizType = typeof(InvoiceApply).FullName;
log.Title = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
log.Remark = $"编号:{apply.SerialNumber} 申请失败,原因:{info.Join(",")}";
logs.Add(log);
continue;
}
#endregion
#region 开票成功的情况处理
var time = info.OperateTime;//DateTime.ParseExact(info[0], "yyyy-MM-ddHH:mm:ss", CultureInfo.InvariantCulture);//开票时间
var code = info.SerialCode;//info[4];//开票代码
var number = info.SerialNumber;//System.Text.RegularExpressions.Regex.Replace(info[5], @"[^0-9]+", "");//开票号码,唯一
var type = info.Type;//info[3].Split(':')[1];//开票类型
var currentAmount = info.Amount;
var taxRate = info.TaxRate;
var time = DateTime.ParseExact(info[0], "yyyy-MM-ddHH:mm:ss", CultureInfo.InvariantCulture);//开票时间
var code = info[4];//开票代码
var number = System.Text.RegularExpressions.Regex.Replace(info[5], @"[^0-9]+", "");//开票号码,唯一
var type = info[3].Split(':')[1];//开票类型
var group = info[1].Split(':')[1];
var currentDetails = group.IsNullOrEmpty() ? applyDetailSplited : applyDetailSplited.Where(o => o.GoodsId == group).ToList();
var invoiceKvid = Guid.NewGuid();
var invoice = new Invoice();
......@@ -851,10 +859,10 @@ namespace Kivii.Finances.Transforms
invoice.SerialCode = code;
invoice.SerialNumber = number;
//invoice.Status = 1;
invoice.Amount = currentAmount;
invoice.AmountUntaxed = Math.Round(currentAmount / (1 + taxRate), 2);
invoice.AmountTax = currentAmount - invoice.AmountUntaxed;
invoice.TaxRate = taxRate;
invoice.Amount = currentDetails.Sum(o => o.Amount);
invoice.AmountTax = currentDetails.Sum(o => o.AmountTax);
invoice.AmountUntaxed = currentDetails.Sum(o => o.AmountUntaxed);
invoice.TaxRate = currentDetails[0].TaxRate;
invoice.PayeeKvid = apply.PayeeKvid;
invoice.PayeeName = apply.PayeeName;
invoice.PayeeTaxNumber = apply.PayeeTaxNumber;
......@@ -878,18 +886,21 @@ namespace Kivii.Finances.Transforms
insertInvoices.Add(invoice);
//conn.Insert(invoice);
foreach (var item in currentDetails)
{
var detail = new InvoiceDetail();
detail.InvoiceKvid = invoiceKvid;
detail.GoodsFullName = "录入明细";//item.GoodsFullName;
//detail.GoodsSpecifications = item.GoodsSpecifications;
detail.Quantity = 1;//item.Quantity;
detail.AmountUntaxed = invoice.AmountUntaxed;
detail.Amount = invoice.Amount;
detail.AmountTax = invoice.AmountTax;
detail.QuantityUnitPriceUntaxed = Math.Round(detail.AmountUntaxed / detail.Quantity, 2);
detail.TaxRate = invoice.TaxRate;
detail.GoodsFullName = item.GoodsFullName;
detail.GoodsSpecifications = item.GoodsSpecifications;
detail.Quantity = item.Quantity;
detail.QuantityUnitPriceUntaxed = item.QuantityUnitPriceUntaxed;
detail.AmountUntaxed = item.AmountUntaxed;
detail.Amount = item.Amount;
detail.AmountTax = item.AmountTax;
detail.TaxRate = item.TaxRate;
insertInvoiceDetails.Add(detail);
//conn.Insert(detail);
}
#endregion
#region 更新申请状态
......@@ -931,7 +942,7 @@ namespace Kivii.Finances.Transforms
{
var correlatedInvoices = insertInvoices.Correlating(payments);
insertInvoices.AddRange(correlatedInvoices);
var currentRootKvids = payments.Where(o => o.Type == PaymentType.Split).ToList().ConvertAll(p => p.RootKvid);
var currentRootKvids = payments.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));
}
#endregion
......@@ -978,5 +989,6 @@ namespace Kivii.Finances.Transforms
return rtns;
}
}
#endregion
}
......@@ -134,6 +134,70 @@ namespace Kivii.Finances.Transforms
}
}
[Api(Description = "泛型结算更新")]
[RequiresAnyRole(SystemRoles.Everyone)]
public class SettlementUpdate : RestfulExecutionGeneric<Settlement>
{
public Settlement Item { get; set; }
public List<Settlement> Items { get; set; }
public override object OnExecutionGeneric<G>(IRequest req, IResponse res)
{
(Item == null && Items.IsNullOrEmpty()).ThrowIfTrue("请传入要结算的内容!");
if (Items.IsNullOrEmpty()) Items = new List<Settlement>();
if (Item != null) Items.Add(Item);
var connF = KiviiContext.GetOpenedDbConnection<Settlement>();
var connE = KiviiContext.GetOpenedDbConnection<G>();
var rtns = new RestfulCreateResponse<Settlement>();
rtns.Results = new List<Settlement>();
#region 合并数据库连接,并启用事务
IDbTransaction tranE = null, tranF = null;
if (connE.ConnectionString == connF.ConnectionString)
{
connF.Close();
connF = connE;
tranE = connE.OpenTransaction();
}
else
{
tranE = connE.OpenTransaction();
tranF = connF.OpenTransaction();
}
#endregion
try
{
foreach (var item in Items)
{
if (item.OnlyProperties.IsNullOrEmpty()) continue;
item.OnlyProperties.RemoveAll(o => o != "Remark" && o != "Summary");
if (item.OnlyProperties.IsNullOrEmpty()) continue;
connF.UpdateOnly(item);
rtns.Results.Add(item);
if (typeof(G) != typeof(Settlement))
{
var entitySettlement = new EntitySettlement<G>();
entitySettlement.PopulateInstance(item);
connE.UpdateOnly(entitySettlement);
}
}
tranE?.Commit();
tranF?.Commit();
}
catch (Exception ex)
{
tranE?.Rollback();
tranF?.Rollback();
throw ex;
}
return rtns;
}
}
[Api(Description = "结算读取")]
[RequiresAnyRole(SystemRoles.Everyone)]
public class SettlementRead : RestfulExecutionGeneric<Settlement>
......
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