You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
275 lines
13 KiB
C#
275 lines
13 KiB
C#
using DS.Module.Core;
|
|
using DS.Module.Core.Enums;
|
|
using DS.Module.Core.Extensions;
|
|
using DS.WMS.Core.Application.Dtos;
|
|
using DS.WMS.Core.Application.Entity;
|
|
using DS.WMS.Core.Fee.Entity;
|
|
using DS.WMS.Core.Invoice.Interface;
|
|
using DS.WMS.Core.Sys.Entity;
|
|
using SqlSugar;
|
|
|
|
namespace DS.WMS.Core.Invoice.Method
|
|
{
|
|
/// <summary>
|
|
/// 标准(按申请)开票实现
|
|
/// </summary>
|
|
public class GeneralInvoiceService : InvoiceService<Entity.Invoice>, IGeneralInvoiceService
|
|
{
|
|
/// <summary>
|
|
/// 初始化
|
|
/// </summary>
|
|
/// <param name="provider"></param>
|
|
public GeneralInvoiceService(IServiceProvider provider) : base(provider)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取发票申请分页列表
|
|
/// </summary>
|
|
/// <param name="request"></param>
|
|
/// <returns></returns>
|
|
public async Task<DataResult<List<InvoiceApplicationDto>>> GetApplicationListAsync(PageRequest request)
|
|
{
|
|
var query = TenantDb.Queryable<InvoiceApplication>()
|
|
.Where(a => (a.Status == InvoiceApplicationStatus.AuditPassed || a.Status == InvoiceApplicationStatus.PartialInvoiced) &&
|
|
SqlFunc.Subqueryable<ApplicationDetail>().Where(d => d.ApplicationId == a.Id && d.Category == DetailCategory.InvoiceApplication && (d.OriginalAmount - d.OriginalProcessedAmount) != 0).Any())
|
|
.Select(a => new InvoiceApplicationDto
|
|
{
|
|
AmountRMB = SqlFunc.Subqueryable<ApplicationDetail>().Where(y => a.Id == y.ApplicationId && y.Currency == FeeCurrency.RMB_CODE).Sum(y => y.ApplyAmount),
|
|
AmountUSD = SqlFunc.Subqueryable<ApplicationDetail>().Where(y => a.Id == y.ApplicationId && y.Currency == FeeCurrency.USD_CODE).Sum(y => y.ApplyAmount),
|
|
AmountOther = SqlFunc.Subqueryable<ApplicationDetail>().Where(y => a.Id == y.ApplicationId && y.Currency != FeeCurrency.RMB_CODE && y.Currency != FeeCurrency.USD_CODE).Sum(y => y.ApplyAmount),
|
|
//原币金额
|
|
OriginalAmountList = SqlFunc.Subqueryable<ApplicationDetail>().Where(y => a.Id == y.ApplicationId)
|
|
.GroupBy(y => y.OriginalCurrency).ToList(y => new CurrencyAmount { Currency = y.OriginalCurrency, Amount = SqlFunc.AggregateSum(y.OriginalAmount) })
|
|
}, true);
|
|
|
|
var whereList = request.GetConditionalModels(Db);
|
|
var result = await query.Where(whereList).ToQueryPageAsync(request.PageCondition);
|
|
|
|
if (result.Data?.Count > 0)
|
|
{
|
|
var userIds = result.Data.Select(x => x.CreateBy).Distinct();
|
|
var users = await Db.Queryable<SysUser>().Where(x => userIds.Contains(x.Id)).Select(x => new { x.Id, x.UserName }).ToListAsync();
|
|
|
|
var orgIds = result.Data.Where(x => x.SaleDeptId.HasValue).Select(x => x.SaleDeptId)
|
|
.Union(result.Data.Where(x => x.OrgId.HasValue).Select(x => x.OrgId))
|
|
.Distinct();
|
|
var orgs = await Db.Queryable<SysOrg>().Where(x => orgIds.Contains(x.Id)).Select(x => new { x.Id, x.OrgName }).ToListAsync();
|
|
|
|
var ids = result.Data.Where(x => string.IsNullOrEmpty(x.Currency)).Select(x => x.Id);
|
|
var appList = await TenantDb.Queryable<ApplicationDetail>().Where(
|
|
x => ids.Contains(x.ApplicationId)).Select(x => new { x.ApplicationId, x.Currency }).ToListAsync();
|
|
|
|
foreach (var item in result.Data)
|
|
{
|
|
item.CreateByName = users.Find(x => x.Id == item.CreateBy)?.UserName;
|
|
|
|
item.SaleDeptName = orgs.Find(x => x.Id == item.SaleDeptId)?.OrgName;
|
|
item.OrgName = orgs.Find(x => x.Id == item.OrgId)?.OrgName;
|
|
|
|
if (string.IsNullOrEmpty(item.Currency))
|
|
{
|
|
var list = appList.FindAll(x => x.ApplicationId == item.Id);
|
|
item.Currency = string.Join(" ", list.Select(x => x.Currency).Distinct());
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取发票申请明细
|
|
/// </summary>
|
|
/// <param name="ids">申请单ID</param>
|
|
/// <returns></returns>
|
|
public async Task<DataResult<List<InvoiceApplicationDetailDto>>> GetApplicationDetailsAsync(params long[] ids)
|
|
{
|
|
var query = CreateApplicationDetailQuery((d, f, s) => ids.Contains(d.ApplicationId) && d.Category == DetailCategory.InvoiceApplication && (d.OriginalAmount - d.OriginalProcessedAmount) != 0);
|
|
|
|
var details = await TenantDb.Queryable(query).LeftJoin<InvoiceApplication>((x, y) => x.ApplicationId == y.Id)
|
|
.Select((x, y) => new InvoiceApplicationDetailDto
|
|
{
|
|
Id = x.Id,
|
|
ApplicationId = x.ApplicationId,
|
|
BusinessId = x.BusinessId,
|
|
BusinessType = x.BusinessType,
|
|
RecordId = x.RecordId,
|
|
FeeName = x.FeeName,
|
|
FeeType = x.FeeType,
|
|
ApplyAmount = x.ApplyAmount,
|
|
RestAmount = x.ApplyAmount - x.ProcessedAmount,
|
|
OriginalCurrency = x.OriginalCurrency, //原始币别
|
|
ExchangeRate = x.ExchangeRate, //折算汇率
|
|
OriginalAmount = x.OriginalAmount, //原始金额
|
|
|
|
CustomerNo = x.CustomerNo,
|
|
MBLNO = x.MBLNO,
|
|
HBLNO = x.HBLNO,
|
|
SaleName = x.SaleName,
|
|
ClientName = x.ClientName,
|
|
ETD = x.ETD,
|
|
SourceName = x.SourceName,
|
|
|
|
AuditTime = y.AuditTime
|
|
}).ToListAsync();
|
|
|
|
return DataResult<List<InvoiceApplicationDetailDto>>.Success(details);
|
|
}
|
|
|
|
|
|
protected override Task<DataResult> PreSaveAsync(Entity.Invoice invoice)
|
|
{
|
|
invoice.Mode = InvoiceMode.Applcation;
|
|
|
|
return Task.FromResult(DataResult.Success);
|
|
}
|
|
|
|
protected override async Task OnSaveAsync(Entity.Invoice invoice)
|
|
{
|
|
var list = invoice.Details?.Where(x => x.DetailId.HasValue).Select(x => new ApplicationDetail
|
|
{
|
|
Id = x.DetailId.GetValueOrDefault(),
|
|
ProcessedAmount = x.ApplyAmount,
|
|
OriginalProcessedAmount = x.OriginalAmount
|
|
}).ToList();
|
|
|
|
if (list != null && list.Count > 0)
|
|
{
|
|
//增加发票申请明细的已处理金额
|
|
await TenantDb.Updateable(list)
|
|
.PublicSetColumns(x => x.ProcessedAmount, "+").PublicSetColumns(x => x.OriginalProcessedAmount, "+")
|
|
.UpdateColumns(x => new { x.ProcessedAmount, x.OriginalProcessedAmount })
|
|
.ExecuteCommandAsync();
|
|
}
|
|
}
|
|
|
|
protected override Task PostSaveAsync(Entity.Invoice invoice)
|
|
{
|
|
return RefreshApplicationStatus([invoice], null);
|
|
}
|
|
|
|
protected override async Task OnDeleteDetailAsync(List<Entity.Invoice> invoices, DeleteOption deleteOption)
|
|
{
|
|
var list = invoices.SelectMany(x => x.Details).Where(x => x.DetailId.HasValue).Select(x => new ApplicationDetail
|
|
{
|
|
Id = x.DetailId.GetValueOrDefault(),
|
|
ProcessedAmount = x.ApplyAmount,
|
|
OriginalProcessedAmount = x.OriginalAmount
|
|
}).ToList();
|
|
//恢复发票申请费用明细的已处理金额
|
|
await TenantDb.Updateable(list)
|
|
.PublicSetColumns(x => x.ProcessedAmount, "-").PublicSetColumns(x => x.OriginalProcessedAmount, "-")
|
|
.UpdateColumns(x => new { x.ProcessedAmount, x.OriginalProcessedAmount })
|
|
.ExecuteCommandAsync();
|
|
|
|
//还原发票申请状态
|
|
var ids = list.Where(x => x.DetailId.HasValue).Select(x => x.DetailId).Distinct();
|
|
var details = TenantDb.Queryable<ApplicationDetail>().Where(x => ids.Contains(x.Id))
|
|
.Select(x => new ApplicationDetail
|
|
{
|
|
Id = x.Id,
|
|
ApplicationId = x.ApplicationId,
|
|
ProcessedAmount = x.ProcessedAmount,
|
|
OriginalAmount = x.OriginalAmount,
|
|
OriginalProcessedAmount = x.OriginalProcessedAmount
|
|
}).ToList();
|
|
|
|
var gpList = details.GroupBy(x => x.ApplicationId);
|
|
List<InvoiceApplication> applications = [];
|
|
foreach (var gp in gpList)
|
|
{
|
|
var processedCount = gp.Count(x => x.OriginalAmount - x.OriginalProcessedAmount == 0);
|
|
var itemCount = gp.Count();
|
|
if (itemCount == processedCount)
|
|
continue;
|
|
|
|
var entity = new InvoiceApplication { Id = gp.Key };
|
|
if (processedCount == 0)
|
|
{
|
|
entity.Status = InvoiceApplicationStatus.AuditPassed;
|
|
}
|
|
else if (itemCount > processedCount)
|
|
{
|
|
entity.Status = InvoiceApplicationStatus.PartialInvoiced;
|
|
}
|
|
|
|
applications.Add(entity);
|
|
}
|
|
|
|
if (applications.Count > 0)
|
|
await TenantDb.Updateable(applications).UpdateColumns(x => new { x.Status }).ExecuteCommandAsync();
|
|
|
|
await base.OnDeleteDetailAsync(invoices, deleteOption);
|
|
}
|
|
|
|
protected override Task PostDeleteAsync(List<Entity.Invoice> invoices, DeleteOption deleteOption)
|
|
{
|
|
////获取关联的发票申请的ID
|
|
//var ids = invoices.SelectMany(x => x.Details).Where(x => x.RefId.HasValue).Select(x => x.RefId.GetValueOrDefault()).Distinct();
|
|
//if (deleteOption == DeleteOption.Entire)
|
|
//{
|
|
// return TenantDb.Updateable<InvoiceApplication>()
|
|
// .SetColumns(x => x.Status == InvoiceApplicationStatus.AuditPassed)
|
|
// .Where(x => ids.Contains(x.Id))
|
|
// .ExecuteCommandAsync();
|
|
//}
|
|
//else if (deleteOption == DeleteOption.DetailOnly)
|
|
//{
|
|
// //获取关联的发票申请的明细ID
|
|
// var ids2 = invoices.SelectMany(x => x.Details).Where(x => x.DetailId.HasValue).Select(x => x.DetailId.GetValueOrDefault()).Distinct();
|
|
|
|
//}
|
|
|
|
//return Task.CompletedTask;
|
|
|
|
return RefreshApplicationStatus(invoices, deleteOption);
|
|
}
|
|
|
|
//更新发票申请的状态
|
|
private async Task RefreshApplicationStatus(List<Entity.Invoice> invoices, DeleteOption? deleteOption)
|
|
{
|
|
if (invoices == null || !invoices.Any())
|
|
return;
|
|
|
|
//获取关联的发票申请的ID
|
|
var ids = invoices.SelectMany(x => x.Details).Where(x => x.RefId.HasValue).Select(x => x.RefId.GetValueOrDefault()).Distinct().ToList();
|
|
var appDetails = await TenantDb.Queryable<ApplicationDetail>().Where(d => ids.Contains(d.ApplicationId))
|
|
.Select(d => new ApplicationDetail
|
|
{
|
|
Id = d.Id,
|
|
Category = d.Category,
|
|
ApplicationId = d.ApplicationId,
|
|
OriginalAmount = d.OriginalAmount,
|
|
OriginalProcessedAmount = d.OriginalProcessedAmount
|
|
}).ToListAsync();
|
|
|
|
List<InvoiceApplication> list2 = new(ids.Count);
|
|
foreach (var id in ids)
|
|
{
|
|
var entity = new InvoiceApplication { Id = id };
|
|
var details = appDetails.FindAll(x => x.ApplicationId == id);
|
|
|
|
if (details.All(x => x.OriginalAmount == x.OriginalAmount - x.OriginalProcessedAmount))
|
|
{
|
|
entity.Status = deleteOption.HasValue ? InvoiceApplicationStatus.AuditPassed : InvoiceApplicationStatus.Invoiced;
|
|
list2.Add(entity);
|
|
}
|
|
else if (details.All(x => x.OriginalAmount - x.OriginalProcessedAmount == 0))
|
|
{
|
|
entity.Status = deleteOption == null ? InvoiceApplicationStatus.Invoiced : InvoiceApplicationStatus.AuditPassed;
|
|
list2.Add(entity);
|
|
}
|
|
else if (details.Exists(x => x.OriginalAmount != x.OriginalAmount - x.OriginalProcessedAmount))
|
|
{
|
|
entity.Status = InvoiceApplicationStatus.PartialInvoiced;
|
|
list2.Add(entity);
|
|
}
|
|
}
|
|
|
|
await TenantDb.Updateable(list2).UpdateColumns(x => new { x.Status }).ExecuteCommandAsync();
|
|
}
|
|
|
|
}
|
|
}
|