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.Invoice.Interface;
using DS.WMS.Core.Sys.Entity;
using SqlSugar;
namespace DS.WMS.Core.Invoice.Method
{
///
/// 标准(按申请)开票实现
///
public class GeneralInvoiceService : InvoiceService, IGeneralInvoiceService
{
///
/// 初始化
///
///
public GeneralInvoiceService(IServiceProvider provider) : base(provider)
{
}
///
/// 获取发票申请分页列表
///
///
///
public async Task>> GetApplicationListAsync(PageRequest request)
{
var query = TenantDb.Queryable()
.Where(a => (a.Status == InvoiceApplicationStatus.AuditPassed || a.Status == InvoiceApplicationStatus.PartialInvoiced) &&
SqlFunc.Subqueryable().Where(d => d.ApplicationId == a.Id && (d.OriginalAmount - d.OriginalProcessedAmount) != 0).Any())
.Select(a => new InvoiceApplicationDto
{
Id = a.Id,
ApplicationNO = a.ApplicationNO,
Status = a.Status,
CustomerId = a.CustomerId,
CustomerName = a.CustomerName, //结算单位
InvoiceHeader = a.InvoiceHeader,
ApplyAmount = a.ApplyAmount,
InvoiceAmount = a.InvoiceAmount,
Currency = a.Currency,
Category = a.Category,
OrgId = a.OrgId, //所属部门
SaleDeptId = a.SaleDeptId, //所属分部
CreateBy = a.CreateBy, //申请人
CreateTime = a.CreateTime, //申请日期
InvoiceRemark = a.InvoiceRemark, //开票要求
Note = a.Note,
//原币金额
OriginalAmountList = SqlFunc.Subqueryable().Where(y => a.Id == y.ApplicationId)
.GroupBy(y => y.OriginalCurrency).ToList(y => new CurrencyAmount { Currency = y.OriginalCurrency, Amount = y.OriginalAmount })
});
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().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().Where(x => orgIds.Contains(x.Id)).Select(x => new { x.Id, x.OrgName }).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;
}
}
return result;
}
///
/// 获取发票申请明细
///
/// 申请单ID
///
public async Task>> 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((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, //原始金额
SaleName = x.SaleName,
CustomerNo = x.CustomerNo,
MBLNO = x.MBLNO,
ClientName = x.ClientName,
ETD = x.ETD,
SourceName = x.SourceName,
AuditTime = y.AuditTime
}).ToListAsync();
return DataResult>.Success(details);
}
protected override Task 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 Task.Factory.StartNew(UpdateInvoiceApplications, new List { invoice });
}
protected override async Task OnDeleteDetailAsync(List 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();
await base.OnDeleteDetailAsync(invoices, deleteOption);
}
protected override Task PostDeleteAsync(List invoices, DeleteOption deleteOption)
{
return Task.Factory.StartNew(UpdateInvoiceApplications, invoices);
}
//更新发票申请的状态
void UpdateInvoiceApplications(object? state)
{
var list = state as IEnumerable;
if (list == null || !list.Any())
return;
var ids = list.SelectMany(x => x.Details).Where(x => x.RefId.HasValue).Select(x => x.RefId.GetValueOrDefault()).Distinct().ToList();
var appDetails = TenantDb.Queryable().Where(d => ids.Contains(d.ApplicationId))
.Select(d => new ApplicationDetail
{
Id = d.Id,
ApplicationId = d.ApplicationId,
OriginalAmount = d.OriginalAmount,
OriginalProcessedAmount = d.OriginalProcessedAmount
}).ToList();
List list2 = new(ids.Count);
foreach (var id in ids)
{
var entity = new InvoiceApplication { Id = id };
var inv = list.FirstOrDefault(x => x.Details.Any(y => y.RefId == id));
entity.AcutalInvoiceNO = inv?.InvoiceNO;
var details = appDetails.FindAll(x => x.ApplicationId == id);
if (details.All(x => x.OriginalAmount == x.OriginalAmount - x.OriginalProcessedAmount))
{
entity.Status = InvoiceApplicationStatus.Invoiced;
list2.Add(entity);
}
else if (details.All(x => x.OriginalAmount - x.OriginalProcessedAmount == 0))
{
entity.Status = InvoiceApplicationStatus.AuditPassed;
list2.Add(entity);
}
else if (details.Exists(x => x.OriginalAmount != x.OriginalAmount - x.OriginalProcessedAmount))
{
entity.Status = InvoiceApplicationStatus.PartialInvoiced;
list2.Add(entity);
}
}
TenantDb.Updateable(list2).UpdateColumns(x => new { x.Status, x.AcutalInvoiceNO }).ExecuteCommand();
}
}
}