|
|
|
@ -163,6 +163,7 @@ namespace DS.WMS.Core.Invoice.Method
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#pragma warning disable CS4014
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 提交发票开票
|
|
|
|
|
/// </summary>
|
|
|
|
@ -215,7 +216,8 @@ namespace DS.WMS.Core.Invoice.Method
|
|
|
|
|
x.OriginalProcessedAmount,
|
|
|
|
|
y.CustomerId
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
invoice.Details = new List<ApplicationDetail>(details.Count);
|
|
|
|
|
|
|
|
|
|
invoice.Details ??= new List<ApplicationDetail>(details.Count);
|
|
|
|
|
|
|
|
|
|
foreach (var item in details)
|
|
|
|
|
{
|
|
|
|
@ -271,7 +273,8 @@ namespace DS.WMS.Core.Invoice.Method
|
|
|
|
|
//将请求明细转换为数据库的费用明细
|
|
|
|
|
invoice.Details = request.Details.Select(x => new ApplicationDetail
|
|
|
|
|
{
|
|
|
|
|
ApplicationId = x.ApplicationId,
|
|
|
|
|
Id = x.Id,
|
|
|
|
|
ApplicationId = x.ApplicationId == 0 ? x.ApplicationId : invoice.Id,
|
|
|
|
|
RefId = x.RefId,
|
|
|
|
|
DetailId = x.Id == 0 ? null : x.Id,
|
|
|
|
|
RecordId = x.RecordId,
|
|
|
|
@ -280,17 +283,19 @@ namespace DS.WMS.Core.Invoice.Method
|
|
|
|
|
FeeId = x.FeeId,
|
|
|
|
|
FeeName = x.FeeName,
|
|
|
|
|
FeeType = x.FeeType,
|
|
|
|
|
ApplyAmount = x.Amount,
|
|
|
|
|
Currency = x.Currency,
|
|
|
|
|
ApplyAmount = x.ApplyAmount,
|
|
|
|
|
ExchangeRate = x.ExchangeRate,
|
|
|
|
|
OriginalAmount = x.OriginalAmount,
|
|
|
|
|
OriginalCurrency = x.OriginalCurrency ?? (invoice.Currency.IsNullOrEmpty() ? x.Currency : invoice.Currency),
|
|
|
|
|
}).ToList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (invoice.Details?.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
//筛选出新增的费用明细
|
|
|
|
|
invoice.Details = invoice.Details.FindAll(x => x.Id == 0);
|
|
|
|
|
|
|
|
|
|
//金额禁止为0
|
|
|
|
|
if (invoice.Details.Any(x => x.ApplyAmount == 0 || x.OriginalAmount == 0))
|
|
|
|
|
return DataResult<TEntity>.FailedWithDesc(nameof(MultiLanguageConst.AmountCannotBeZero));
|
|
|
|
@ -304,18 +309,15 @@ namespace DS.WMS.Core.Invoice.Method
|
|
|
|
|
result = await PreSaveAsync(invoice);
|
|
|
|
|
if (!result.Succeeded)
|
|
|
|
|
return DataResult<TEntity>.Failed(result.Message, result.MultiCode);
|
|
|
|
|
|
|
|
|
|
invoice.ApplyAmount = invoice.Details.Sum(x => x.ApplyAmount);
|
|
|
|
|
invoice.AmountUppercase = new Money(invoice.ApplyAmount).ToString();
|
|
|
|
|
invoice.OriginalAmount = invoice.Details.Sum(x => x.OriginalAmount);
|
|
|
|
|
invoice.OtherInvoiceAmount = invoice.Details.Where(x => x.Currency != RMB_CODE).Sum(x => x.OriginalAmount);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await TenantDb.Ado.BeginTranAsync();
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
BuildOption buildOption;
|
|
|
|
|
if (invoice.Id == 0)//新增
|
|
|
|
|
{
|
|
|
|
|
buildOption = BuildOption.Create;
|
|
|
|
|
//创建时需要生成申请单编号
|
|
|
|
|
var sequence = CommonService.Value.GetSequenceNext<TEntity>();
|
|
|
|
|
if (!sequence.Succeeded)
|
|
|
|
@ -328,30 +330,33 @@ namespace DS.WMS.Core.Invoice.Method
|
|
|
|
|
}
|
|
|
|
|
else//编辑
|
|
|
|
|
{
|
|
|
|
|
if (invoice.Details?.Count > 0)
|
|
|
|
|
buildOption = BuildOption.Update;
|
|
|
|
|
await TenantDb.Updateable(invoice).UpdateColumns(x => new
|
|
|
|
|
{
|
|
|
|
|
x.InvoiceNO,
|
|
|
|
|
x.InvoiceDate,
|
|
|
|
|
//x.Currency,
|
|
|
|
|
x.ReceiptCurrency,
|
|
|
|
|
x.CustomerId,
|
|
|
|
|
x.CustomerName,
|
|
|
|
|
x.AutualCustomerName,
|
|
|
|
|
x.InvoiceHeader,
|
|
|
|
|
x.Account,
|
|
|
|
|
x.CustomerAddTel,
|
|
|
|
|
x.CustomerBank,
|
|
|
|
|
x.OperatorId,
|
|
|
|
|
x.TaxID,
|
|
|
|
|
x.TaxRate,
|
|
|
|
|
x.OrgId,
|
|
|
|
|
x.SaleDeptId
|
|
|
|
|
}).ExecuteCommandAsync();
|
|
|
|
|
|
|
|
|
|
if (invoice.Details?.Count > 0)
|
|
|
|
|
await TenantDb.Insertable(invoice.Details).ExecuteCommandAsync();
|
|
|
|
|
////因需要重新生成明细,所以要先清空现有发票明细
|
|
|
|
|
//await TenantDb.Deleteable<InvoiceDetail>().Where(x => x.ApplicationId == invoice.Id).ExecuteCommandAsync();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else if (invoice.InvoiceDetails?.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
//更新发票明细
|
|
|
|
|
if (invoice.InvoiceDetails?.Count > 0)
|
|
|
|
|
//发票明细只有更新
|
|
|
|
|
await TenantDb.Updateable(invoice.InvoiceDetails).IgnoreColumns(x => new { x.Category }).ExecuteCommandAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await TenantDb.Updateable(invoice).IgnoreColumns(x => new
|
|
|
|
|
{
|
|
|
|
|
x.BillNO,
|
|
|
|
|
x.IsLocked,
|
|
|
|
|
|
|
|
|
|
x.CreateBy,
|
|
|
|
|
x.CreateTime,
|
|
|
|
|
x.Deleted,
|
|
|
|
|
x.DeleteBy,
|
|
|
|
|
x.DeleteTime
|
|
|
|
|
}).ExecuteCommandAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (invoice.Details?.Count > 0)
|
|
|
|
@ -360,21 +365,26 @@ namespace DS.WMS.Core.Invoice.Method
|
|
|
|
|
var fees = invoice.Details.Select(x => new FeeRecord
|
|
|
|
|
{
|
|
|
|
|
Id = x.RecordId,
|
|
|
|
|
InvoiceAmount = x.OriginalAmount
|
|
|
|
|
InvoiceAmount = x.OriginalAmount,
|
|
|
|
|
OrderInvSettlementAmount = x.OriginalAmount,
|
|
|
|
|
}).ToList();
|
|
|
|
|
await TenantDb.Updateable(fees)
|
|
|
|
|
.PublicSetColumns(x => x.InvoiceAmount, "+")
|
|
|
|
|
.UpdateColumns(x => new { x.InvoiceAmount })
|
|
|
|
|
.ExecuteCommandAsync();
|
|
|
|
|
|
|
|
|
|
await BuildInvoiceDetailAsync([invoice]);
|
|
|
|
|
if (invoice.InvoiceDetails?.Count > 0)
|
|
|
|
|
await TenantDb.Insertable(invoice.InvoiceDetails).ExecuteCommandAsync();
|
|
|
|
|
var updateable = TenantDb.Updateable(fees).PublicSetColumns(x => x.InvoiceAmount, "+");
|
|
|
|
|
if (invoice.Type == InvoiceType.Applcation)
|
|
|
|
|
updateable = updateable.PublicSetColumns(x => x.OrderInvSettlementAmount, "+")
|
|
|
|
|
.UpdateColumns(x => new { x.OrderInvSettlementAmount });
|
|
|
|
|
|
|
|
|
|
await updateable.UpdateColumns(x => new { x.InvoiceAmount }).ExecuteCommandAsync();
|
|
|
|
|
|
|
|
|
|
//生成发票明细
|
|
|
|
|
await BuildInvoiceDetailAsync(invoice, buildOption);
|
|
|
|
|
|
|
|
|
|
//重新计算发票总金额
|
|
|
|
|
await RefreshInvoiceAsync([invoice]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await OnSaveAsync(invoice);
|
|
|
|
|
await TenantDb.Ado.CommitTranAsync();
|
|
|
|
|
|
|
|
|
|
PostSaveAsync(invoice);
|
|
|
|
|
|
|
|
|
|
return DataResult<TEntity>.Success(invoice);
|
|
|
|
@ -387,6 +397,199 @@ namespace DS.WMS.Core.Invoice.Method
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 生成发票明细
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="invoice">发票</param>
|
|
|
|
|
/// <param name="option">生成类型</param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
protected async Task BuildInvoiceDetailAsync(TEntity invoice, BuildOption option)
|
|
|
|
|
{
|
|
|
|
|
if (invoice.Details == null || invoice.Details.Count == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
var ids = invoice.Details.Select(x => x.Id);
|
|
|
|
|
if (option == BuildOption.Create)
|
|
|
|
|
{
|
|
|
|
|
var feesCodes = await TenantDb.Queryable<ApplicationDetail>().InnerJoin<FeeCode>((d, fc) => d.FeeId == fc.Id && ids.Contains(d.Id))
|
|
|
|
|
.Select((d, fc) => new
|
|
|
|
|
{
|
|
|
|
|
DetailId = d.Id,
|
|
|
|
|
FeeId = fc.Id,
|
|
|
|
|
fc.GoodName
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
var feeCodeGroups = feesCodes.GroupBy(x => x.GoodName).ToList();
|
|
|
|
|
|
|
|
|
|
invoice.InvoiceDetails = new List<InvoiceDetail>(feeCodeGroups.Count);
|
|
|
|
|
List<ApplicationDetailRelation> relations = [];
|
|
|
|
|
foreach (var g in feeCodeGroups)
|
|
|
|
|
{
|
|
|
|
|
var invDetail = new InvoiceDetail
|
|
|
|
|
{
|
|
|
|
|
Id = SnowFlakeSingle.Instance.NextId(),
|
|
|
|
|
ApplicationId = invoice.Id,
|
|
|
|
|
Name = g.Key,
|
|
|
|
|
TaxRate = invoice.TaxRate,
|
|
|
|
|
TaxUnitPrice = invoice.Details.FindAll(x => g.Select(x => x.DetailId).Contains(x.Id)).Sum(x => x.ApplyAmount),
|
|
|
|
|
Category = DetailCategory.InvoiceIssuance
|
|
|
|
|
};
|
|
|
|
|
invDetail.TaxAmount = invDetail.TaxUnitPrice * invoice.TaxRate;
|
|
|
|
|
invDetail.UnitPrice = invDetail.TaxUnitPrice - invDetail.TaxAmount;
|
|
|
|
|
|
|
|
|
|
invoice.InvoiceDetails.Add(invDetail);
|
|
|
|
|
|
|
|
|
|
foreach (var item in g)
|
|
|
|
|
{
|
|
|
|
|
relations.Add(new ApplicationDetailRelation
|
|
|
|
|
{
|
|
|
|
|
DetailId = item.DetailId,
|
|
|
|
|
InvoiceDetailId = invDetail.Id,
|
|
|
|
|
OriginalName = g.Key,
|
|
|
|
|
InvoiceId = invoice.Id
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await TenantDb.Insertable(invoice.InvoiceDetails).ExecuteCommandAsync();
|
|
|
|
|
await TenantDb.Insertable(relations).ExecuteCommandAsync();
|
|
|
|
|
}
|
|
|
|
|
//更新时只处理增加的明细
|
|
|
|
|
else if (option == BuildOption.Update)
|
|
|
|
|
{
|
|
|
|
|
//获取现有发票明细对应关系
|
|
|
|
|
var relations = await TenantDb.Queryable<ApplicationDetailRelation>().Where(x => x.InvoiceId == invoice.Id)
|
|
|
|
|
.Select(x => new
|
|
|
|
|
{
|
|
|
|
|
x.DetailId,
|
|
|
|
|
x.InvoiceDetailId,
|
|
|
|
|
x.OriginalName,
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
var feeIds = invoice.Details.Select(x => x.FeeId);
|
|
|
|
|
var feesCodes = await TenantDb.Queryable<FeeCode>().Where(x => feeIds.Contains(x.Id))
|
|
|
|
|
.Select(x => new
|
|
|
|
|
{
|
|
|
|
|
FeeId = x.Id,
|
|
|
|
|
x.GoodName
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
|
|
|
|
|
invoice.InvoiceDetails = []; //新增的发票明细
|
|
|
|
|
List<InvoiceDetail> invoiceDetailList = []; //更新的发票明细
|
|
|
|
|
List<ApplicationDetailRelation> relationList = []; //新增的明细关系
|
|
|
|
|
|
|
|
|
|
foreach (var detail in invoice.Details)
|
|
|
|
|
{
|
|
|
|
|
var goodsName = feesCodes.Find(x => x.FeeId == detail.FeeId)?.GoodName; //转换为发票明细名称
|
|
|
|
|
var relation = relations.Find(x => string.Equals(x.OriginalName, goodsName, StringComparison.Ordinal));
|
|
|
|
|
if (relation == null) //需要新增发票明细
|
|
|
|
|
{
|
|
|
|
|
var invDetail = new InvoiceDetail
|
|
|
|
|
{
|
|
|
|
|
Id = SnowFlakeSingle.Instance.NextId(),
|
|
|
|
|
ApplicationId = invoice.Id,
|
|
|
|
|
Name = goodsName,
|
|
|
|
|
TaxRate = invoice.TaxRate,
|
|
|
|
|
TaxUnitPrice = detail.ApplyAmount,
|
|
|
|
|
Category = DetailCategory.InvoiceIssuance
|
|
|
|
|
};
|
|
|
|
|
invDetail.TaxAmount = invDetail.TaxUnitPrice * invoice.TaxRate;
|
|
|
|
|
invDetail.UnitPrice = invDetail.TaxUnitPrice - invDetail.TaxAmount;
|
|
|
|
|
|
|
|
|
|
invoice.InvoiceDetails.Add(invDetail);
|
|
|
|
|
|
|
|
|
|
relationList.Add(new ApplicationDetailRelation
|
|
|
|
|
{
|
|
|
|
|
DetailId = detail.Id,
|
|
|
|
|
InvoiceDetailId = invDetail.Id,
|
|
|
|
|
InvoiceId = invoice.Id,
|
|
|
|
|
OriginalName = goodsName
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
else //发票明细已存在,追加金额
|
|
|
|
|
{
|
|
|
|
|
//添加到更新列表
|
|
|
|
|
invoiceDetailList.Add(new InvoiceDetail
|
|
|
|
|
{
|
|
|
|
|
Id = relation.InvoiceDetailId,
|
|
|
|
|
TaxUnitPrice = detail.ApplyAmount
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (invoice.InvoiceDetails.Count > 0)
|
|
|
|
|
await TenantDb.Insertable(invoice.InvoiceDetails).ExecuteCommandAsync();
|
|
|
|
|
|
|
|
|
|
//执行发票明细金额更新
|
|
|
|
|
if (invoiceDetailList.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
var ids2 = invoiceDetailList.Select(x => x.Id);
|
|
|
|
|
var updateList = await TenantDb.Queryable<InvoiceDetail>().Where(x => ids2.Contains(x.Id)).Select(x => new InvoiceDetail
|
|
|
|
|
{
|
|
|
|
|
Id = x.Id,
|
|
|
|
|
TaxUnitPrice = x.TaxUnitPrice,
|
|
|
|
|
TaxRate = x.TaxRate,
|
|
|
|
|
TaxAmount = x.TaxAmount,
|
|
|
|
|
UnitPrice = x.UnitPrice
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
foreach (var item in updateList)
|
|
|
|
|
{
|
|
|
|
|
var invDetail = invoiceDetailList.Find(x => x.Id == item.Id);
|
|
|
|
|
item.TaxUnitPrice += (invDetail?.TaxUnitPrice).GetValueOrDefault();
|
|
|
|
|
item.TaxAmount = item.TaxUnitPrice * invoice.TaxRate;
|
|
|
|
|
item.UnitPrice = item.TaxUnitPrice - item.TaxAmount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await TenantDb.Updateable(updateList).UpdateColumns(x => new
|
|
|
|
|
{
|
|
|
|
|
x.TaxUnitPrice,
|
|
|
|
|
x.TaxAmount,
|
|
|
|
|
x.UnitPrice
|
|
|
|
|
}).ExecuteCommandAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (relationList.Count > 0)
|
|
|
|
|
await TenantDb.Insertable(relationList).ExecuteCommandAsync();
|
|
|
|
|
}
|
|
|
|
|
else if (option == BuildOption.Delete)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 重新计算发票的各项金额数据
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="invoices">发票</param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
protected async Task<int> RefreshInvoiceAsync(List<TEntity> invoices)
|
|
|
|
|
{
|
|
|
|
|
var ids = invoices.Select(x => x.Id);
|
|
|
|
|
var details = await TenantDb.Queryable<ApplicationDetail>().Where(x => ids.Contains(x.ApplicationId))
|
|
|
|
|
.Select(x => new { x.ApplicationId, x.Currency, x.ApplyAmount, x.OriginalAmount }).ToListAsync();
|
|
|
|
|
var invDetails = await TenantDb.Queryable<InvoiceDetail>().Where(x => ids.Contains(x.ApplicationId))
|
|
|
|
|
.Select(x => new { x.ApplicationId, x.TaxUnitPrice }).ToListAsync();
|
|
|
|
|
|
|
|
|
|
foreach (var invoice in invoices)
|
|
|
|
|
{
|
|
|
|
|
var currDetails = details.FindAll(x => x.ApplicationId == invoice.Id);
|
|
|
|
|
|
|
|
|
|
invoice.ApplyAmount = currDetails.Sum(x => x.ApplyAmount);
|
|
|
|
|
invoice.AmountUppercase = new Money(invoice.ApplyAmount).ToString();
|
|
|
|
|
invoice.OriginalAmount = currDetails.Sum(x => x.OriginalAmount);
|
|
|
|
|
invoice.OtherInvoiceAmount = currDetails.FindAll(x => x.Currency != RMB_CODE).Sum(x => x.OriginalAmount);
|
|
|
|
|
|
|
|
|
|
invoice.InvoiceAmount = invDetails.FindAll(x => x.ApplicationId == invoice.Id).Sum(x => x.TaxUnitPrice);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return await TenantDb.Updateable(invoices).UpdateColumns(x => new
|
|
|
|
|
{
|
|
|
|
|
x.ApplyAmount,
|
|
|
|
|
x.AmountUppercase,
|
|
|
|
|
x.OriginalAmount,
|
|
|
|
|
x.OtherInvoiceAmount,
|
|
|
|
|
x.InvoiceAmount
|
|
|
|
|
}).ExecuteCommandAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 用于发票的状态检查
|
|
|
|
|
/// </summary>
|
|
|
|
@ -429,32 +632,38 @@ namespace DS.WMS.Core.Invoice.Method
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<DataResult> DeleteAsync(params long[] ids)
|
|
|
|
|
{
|
|
|
|
|
var apps = await TenantDb.Queryable<TEntity>().Where(x => ids.Contains(x.Id)).Select(x => new TEntity
|
|
|
|
|
await TenantDb.Ado.BeginTranAsync();
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
Id = x.Id,
|
|
|
|
|
IsLocked = x.IsLocked
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
var details = await TenantDb.Queryable<ApplicationDetail>().Where(x => ids.Contains(x.ApplicationId)).Select(
|
|
|
|
|
x => new ApplicationDetail
|
|
|
|
|
var apps = await TenantDb.Queryable<TEntity>().Where(x => ids.Contains(x.Id)).Select(x => new TEntity
|
|
|
|
|
{
|
|
|
|
|
Id = x.Id,
|
|
|
|
|
ApplicationId = x.ApplicationId,
|
|
|
|
|
DetailId = x.DetailId,
|
|
|
|
|
RefId = x.RefId,
|
|
|
|
|
RecordId = x.RecordId,
|
|
|
|
|
ApplyAmount = x.ApplyAmount,
|
|
|
|
|
OriginalAmount = x.OriginalAmount
|
|
|
|
|
Type = x.Type,
|
|
|
|
|
IsLocked = x.IsLocked
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
|
|
|
|
|
foreach (var app in apps)
|
|
|
|
|
app.Details = details.FindAll(x => x.ApplicationId == app.Id); await TenantDb.Ado.BeginTranAsync();
|
|
|
|
|
if (apps.Count == 0)
|
|
|
|
|
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.EmptyData));
|
|
|
|
|
|
|
|
|
|
var result = PreDelete(apps);
|
|
|
|
|
if (!result.Succeeded)
|
|
|
|
|
return result;
|
|
|
|
|
var details = await TenantDb.Queryable<ApplicationDetail>().Where(x => ids.Contains(x.ApplicationId)).Select(
|
|
|
|
|
x => new ApplicationDetail
|
|
|
|
|
{
|
|
|
|
|
Id = x.Id,
|
|
|
|
|
ApplicationId = x.ApplicationId,
|
|
|
|
|
DetailId = x.DetailId,
|
|
|
|
|
RefId = x.RefId,
|
|
|
|
|
RecordId = x.RecordId,
|
|
|
|
|
ApplyAmount = x.ApplyAmount,
|
|
|
|
|
OriginalAmount = x.OriginalAmount
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
|
|
|
|
|
foreach (var app in apps)
|
|
|
|
|
app.Details = details.FindAll(x => x.ApplicationId == app.Id);
|
|
|
|
|
|
|
|
|
|
var result = PreDelete(apps);
|
|
|
|
|
if (!result.Succeeded)
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
await OnDeleteDetailAsync(apps, DeleteOption.Entire);
|
|
|
|
|
await TenantDb.DeleteNav<TEntity>(x => ids.Contains(x.Id)).Include(x => x.Details).ExecuteCommandAsync();
|
|
|
|
|
await TenantDb.Ado.CommitTranAsync();
|
|
|
|
@ -478,7 +687,10 @@ namespace DS.WMS.Core.Invoice.Method
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<DataResult> DeleteDetailAsync(params long[] ids)
|
|
|
|
|
{
|
|
|
|
|
var details = await TenantDb.Queryable<ApplicationDetail>().Where(x => ids.Contains(x.Id)).Select(
|
|
|
|
|
await TenantDb.Ado.BeginTranAsync();
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var details = await TenantDb.Queryable<ApplicationDetail>().Where(x => ids.Contains(x.Id)).Select(
|
|
|
|
|
x => new ApplicationDetail
|
|
|
|
|
{
|
|
|
|
|
Id = x.Id,
|
|
|
|
@ -489,28 +701,32 @@ namespace DS.WMS.Core.Invoice.Method
|
|
|
|
|
ApplyAmount = x.ApplyAmount,
|
|
|
|
|
OriginalAmount = x.OriginalAmount
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
var appIds = details.Select(x => x.ApplicationId).Distinct().ToList();
|
|
|
|
|
var apps = await TenantDb.Queryable<TEntity>().Where(x => appIds.Contains(x.Id)).Select(x => new TEntity
|
|
|
|
|
{
|
|
|
|
|
Id = x.Id,
|
|
|
|
|
IsLocked = x.IsLocked
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
|
|
|
|
|
foreach (var app in apps)
|
|
|
|
|
app.Details = details.FindAll(x => x.ApplicationId == app.Id);
|
|
|
|
|
if (details.Count == 0)
|
|
|
|
|
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.EmptyData));
|
|
|
|
|
|
|
|
|
|
var result = PreDelete(apps);
|
|
|
|
|
if (!result.Succeeded)
|
|
|
|
|
return result;
|
|
|
|
|
var invIds = details.Select(x => x.ApplicationId).Distinct().ToList();
|
|
|
|
|
var invoices = await TenantDb.Queryable<TEntity>().Where(x => invIds.Contains(x.Id)).Select(x => new TEntity
|
|
|
|
|
{
|
|
|
|
|
Id = x.Id,
|
|
|
|
|
Type = x.Type,
|
|
|
|
|
IsLocked = x.IsLocked
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
|
|
|
|
|
await TenantDb.Ado.BeginTranAsync();
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
await OnDeleteDetailAsync(apps, DeleteOption.DetailOnly);
|
|
|
|
|
foreach (var app in invoices)
|
|
|
|
|
app.Details = details.FindAll(x => x.ApplicationId == app.Id);
|
|
|
|
|
|
|
|
|
|
var result = PreDelete(invoices);
|
|
|
|
|
if (!result.Succeeded)
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
|
|
await OnDeleteDetailAsync(invoices, DeleteOption.DetailOnly);
|
|
|
|
|
await TenantDb.Deleteable(details).ExecuteCommandAsync();
|
|
|
|
|
//重新计算发票总金额
|
|
|
|
|
await RefreshInvoiceAsync(invoices);
|
|
|
|
|
await TenantDb.Ado.CommitTranAsync();
|
|
|
|
|
|
|
|
|
|
PostDeleteAsync(apps, DeleteOption.Entire);
|
|
|
|
|
PostDeleteAsync(invoices, DeleteOption.Entire);
|
|
|
|
|
|
|
|
|
|
return DataResult.Success;
|
|
|
|
|
}
|
|
|
|
@ -529,8 +745,33 @@ namespace DS.WMS.Core.Invoice.Method
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<DataResult> DeleteInvoiceDetailAsync(params long[] ids)
|
|
|
|
|
{
|
|
|
|
|
int rows = await TenantDb.Deleteable<InvoiceDetail>().Where(x => ids.Contains(x.Id)).ExecuteCommandAsync();
|
|
|
|
|
return rows > 0 ? DataResult.Success : DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed));
|
|
|
|
|
await TenantDb.Ado.BeginTranAsync();
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var invDetails = await TenantDb.Queryable<InvoiceDetail>().Where(x => ids.Contains(x.Id))
|
|
|
|
|
.Select(x => new { x.ApplicationId, x.TaxUnitPrice }).ToListAsync();
|
|
|
|
|
var groups = invDetails.GroupBy(x => x.ApplicationId);
|
|
|
|
|
foreach (var g in groups)
|
|
|
|
|
{
|
|
|
|
|
var list = g.Select(x => new TEntity { Id = g.Key, InvoiceAmount = g.Sum(x => x.TaxUnitPrice) }).ToList();
|
|
|
|
|
//更新发票主表的开票金额
|
|
|
|
|
await TenantDb.Updateable(list).PublicSetColumns(x => x.InvoiceAmount, "-")
|
|
|
|
|
.UpdateColumns(x => new { x.InvoiceAmount }).ExecuteCommandAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await TenantDb.Deleteable<InvoiceDetail>().Where(x => ids.Contains(x.Id)).ExecuteCommandAsync();
|
|
|
|
|
//删除对应关系
|
|
|
|
|
await TenantDb.Deleteable<ApplicationDetailRelation>().Where(x => ids.Contains(x.InvoiceDetailId)).ExecuteCommandAsync();
|
|
|
|
|
|
|
|
|
|
await TenantDb.Ado.CommitTranAsync();
|
|
|
|
|
return DataResult.Success;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
await TenantDb.Ado.RollbackTranAsync();
|
|
|
|
|
await ex.LogAsync(Db);
|
|
|
|
|
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
@ -554,12 +795,15 @@ namespace DS.WMS.Core.Invoice.Method
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
protected virtual async Task OnDeleteDetailAsync(List<TEntity> invoices, DeleteOption deleteOption)
|
|
|
|
|
{
|
|
|
|
|
var excludeIds = invoices.SelectMany(x => x.Details).Select(x => x.Id).ToList();
|
|
|
|
|
//await TenantDb.Deleteable<InvoiceDetail>().Where(x => excludeIds.Contains(x.Id)).ExecuteCommandAsync();
|
|
|
|
|
var appIds = invoices.Select(x => x.Id);
|
|
|
|
|
|
|
|
|
|
if (deleteOption == DeleteOption.DetailOnly)
|
|
|
|
|
{
|
|
|
|
|
var appIds = invoices.Select(x => x.Id).ToList();
|
|
|
|
|
//删除明细需要同时变更发票明细
|
|
|
|
|
foreach (var item in invoices)
|
|
|
|
|
BuildInvoiceDetailAsync(item, BuildOption.Delete);
|
|
|
|
|
|
|
|
|
|
var excludeIds = invoices.SelectMany(x => x.Details).Select(x => x.Id);
|
|
|
|
|
var details = await TenantDb.Queryable<ApplicationDetail>().Where(x => appIds.Contains(x.ApplicationId) && !excludeIds.Contains(x.Id))
|
|
|
|
|
.Select(x => new ApplicationDetail
|
|
|
|
|
{
|
|
|
|
@ -577,24 +821,39 @@ namespace DS.WMS.Core.Invoice.Method
|
|
|
|
|
item.AmountUppercase = new Money(item.ApplyAmount).ToString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////删除明细需要同时变更发票明细
|
|
|
|
|
//await CreateInvoiceDetailsAsync(invoices);
|
|
|
|
|
//var invDetails = invoices.SelectMany(x => x.InvoiceDetails).ToList();
|
|
|
|
|
//if (invDetails.Count > 0)
|
|
|
|
|
// await TenantDb.Insertable(invDetails).ExecuteCommandAsync();
|
|
|
|
|
|
|
|
|
|
await TenantDb.Updateable(invoices).UpdateColumns(x => new
|
|
|
|
|
{
|
|
|
|
|
x.ApplyAmount,
|
|
|
|
|
x.AmountUppercase
|
|
|
|
|
}).ExecuteCommandAsync();
|
|
|
|
|
|
|
|
|
|
//删除明细之间的关系
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else if (deleteOption == DeleteOption.Entire)
|
|
|
|
|
{
|
|
|
|
|
//删除发票主表则同时删除对应发票明细
|
|
|
|
|
await TenantDb.Deleteable<InvoiceDetail>().Where(x => appIds.Contains(x.ApplicationId)).ExecuteCommandAsync();
|
|
|
|
|
|
|
|
|
|
//删除明细之间的关系
|
|
|
|
|
await TenantDb.Deleteable<ApplicationDetailRelation>().Where(x => appIds.Contains(x.InvoiceId)).ExecuteCommandAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var item in invoices)
|
|
|
|
|
{
|
|
|
|
|
//还原费用表的已开票金额
|
|
|
|
|
var fees = item.Details?.Select(x => new FeeRecord { Id = x.RecordId, InvoiceAmount = x.OriginalAmount }).ToList();
|
|
|
|
|
|
|
|
|
|
var updateable = TenantDb.Updateable(fees).PublicSetColumns(x => x.InvoiceAmount, "-");
|
|
|
|
|
|
|
|
|
|
if (item.Type == InvoiceType.Applcation)
|
|
|
|
|
updateable = updateable.PublicSetColumns(x => x.OrderInvSettlementAmount, "-")
|
|
|
|
|
.UpdateColumns(x => new { x.OrderInvSettlementAmount });
|
|
|
|
|
|
|
|
|
|
await updateable.UpdateColumns(x => new { x.InvoiceAmount }).ExecuteCommandAsync();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//还原费用表的已开票金额
|
|
|
|
|
var fees = invoices.SelectMany(x => x.Details).Select(x => new FeeRecord { Id = x.RecordId, InvoiceAmount = x.OriginalAmount }).ToList();
|
|
|
|
|
await TenantDb.Updateable(fees)
|
|
|
|
|
.PublicSetColumns(it => it.InvoiceAmount, "-").UpdateColumns(x => new { x.InvoiceAmount })
|
|
|
|
|
.ExecuteCommandAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
@ -604,51 +863,6 @@ namespace DS.WMS.Core.Invoice.Method
|
|
|
|
|
/// <param name="deleteOption">发票删除选项</param>
|
|
|
|
|
protected virtual Task PostDeleteAsync(List<TEntity> invoices, DeleteOption deleteOption) => Task.CompletedTask;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 生成发票明细
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="invoices"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
protected async Task BuildInvoiceDetailAsync(IEnumerable<TEntity> invoices)
|
|
|
|
|
{
|
|
|
|
|
foreach (var invoice in invoices)
|
|
|
|
|
{
|
|
|
|
|
if (invoice.Details?.Count > 0 && (invoice.InvoiceDetails == null || invoice.InvoiceDetails.Count == 0))
|
|
|
|
|
{
|
|
|
|
|
var ids = invoice.Details.Select(x => x.RecordId).ToList();
|
|
|
|
|
var feesCodes = await TenantDb.Queryable<FeeRecord>().InnerJoin<FeeCode>((f, c) => f.FeeId == c.Id && ids.Contains(f.Id))
|
|
|
|
|
.Select((f, c) => new
|
|
|
|
|
{
|
|
|
|
|
FeeId = c.Id,
|
|
|
|
|
c.GoodName
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
|
|
|
|
|
var list = feesCodes.GroupBy(x => x.GoodName).Select(x => new
|
|
|
|
|
{
|
|
|
|
|
Name = x.Key,
|
|
|
|
|
FeeIds = x.Select(y => y.FeeId)
|
|
|
|
|
}).ToList();
|
|
|
|
|
invoice.InvoiceDetails = new List<InvoiceDetail>(list.Count);
|
|
|
|
|
foreach (var item in list)
|
|
|
|
|
{
|
|
|
|
|
var invDetail = new InvoiceDetail
|
|
|
|
|
{
|
|
|
|
|
ApplicationId = invoice.Id,
|
|
|
|
|
Name = item.Name,
|
|
|
|
|
TaxRate = invoice.TaxRate,
|
|
|
|
|
TaxUnitPrice = invoice.Details.FindAll(x => item.FeeIds.Contains(x.FeeId)).Sum(x => x.ApplyAmount),
|
|
|
|
|
Category = DetailCategory.InvoiceIssuance
|
|
|
|
|
};
|
|
|
|
|
invDetail.TaxAmount = invDetail.TaxUnitPrice * invoice.TaxRate;
|
|
|
|
|
invDetail.UnitPrice = invDetail.TaxUnitPrice - invDetail.TaxAmount;
|
|
|
|
|
|
|
|
|
|
invoice.InvoiceDetails.Add(invDetail);
|
|
|
|
|
invoice.InvoiceAmount = invoice.InvoiceDetails.Sum(x => x.TaxUnitPrice);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 设置发票的锁定状态
|
|
|
|
|