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.

235 lines
11 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System.Text;
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.Op.Entity;
using DS.WMS.Core.Settlement.Dtos;
using DS.WMS.Core.Settlement.Entity;
using DS.WMS.Core.Settlement.Interface;
using DS.WMS.Core.Sys.Entity;
using Masuit.Tools.Systems;
namespace DS.WMS.Core.Settlement.Method
{
/// <summary>
/// 发票结算
/// </summary>
public class InvoiceSettlementService : SettlementService<PaymentSettlement>, IInvoiceSettlementService
{
/// <summary>
/// 初始化
/// </summary>
/// <param name="provider"></param>
public InvoiceSettlementService(IServiceProvider provider) : base(provider)
{
}
/// <summary>
/// 获取待结算的发票申请列表
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public async Task<DataResult<List<InvoiceApplicationDto>>> GetInvoiceListAsync(PageRequest request)
{
var whereList = request.GetConditionalModels(Db);
var result = await TenantDb.Queryable<InvoiceApplication>()
.InnerJoin<ApplicationDetail>((a, d) => d.Category == DetailCategory.InvoiceApplication && a.Id == d.ApplicationId && d.OriginalAmount - d.OriginalSettlementAmount != 0)
.InnerJoin<FeeRecord>((a, d, f) => (f.FeeStatus == FeeStatus.AuditPassed || f.FeeStatus == FeeStatus.PartialSettlement) && d.RecordId == f.Id &&
((f.Amount > 0 && d.OriginalAmount - d.OriginalSettlementAmount <= f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount) ||
(f.Amount < 0 && d.OriginalAmount - d.OriginalSettlementAmount >= f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount))
)
.GroupBy((a, d, f) => a.Id)
.Select((a, d, f) => new InvoiceApplicationDto
{
}, true).MergeTable().Where(a => a.Status == InvoiceApplicationStatus.AuditPassed || a.Status == InvoiceApplicationStatus.PartialInvoiced).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.Select(x => x.SaleDeptId).Distinct().ToList();
var orgs = await Db.Queryable<SysOrg>().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;
}
}
return result;
}
/// <summary>
/// 获取发票申请费用明细
/// </summary>
/// <param name="ids"></param>
/// <returns></returns>
public async Task<DataResult<List<ApplicationDetailDto>>> GetInvoiceDetailsAsync(params long[] ids)
{
var query1 = TenantDb.Queryable<ApplicationDetail>()
.InnerJoin<FeeRecord>((d, f) => d.Category == DetailCategory.InvoiceApplication && d.RecordId == f.Id &&
(f.FeeStatus == FeeStatus.AuditPassed || f.FeeStatus == FeeStatus.PartialSettlement) && f.BusinessType == BusinessType.OceanShippingExport &&
((f.Amount > 0 && d.OriginalAmount - d.OriginalSettlementAmount <= f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount) ||
(f.Amount < 0 && d.OriginalAmount - d.OriginalSettlementAmount >= f.Amount - f.SettlementAmount - f.OrderAmount + f.OrderSettlementAmount))
)
.LeftJoin<SeaExport>((d, f, s) => f.BusinessId == s.Id)
.Where((d, f, s) => ids.Contains(d.ApplicationId))
.Select((d, f, s) => new ApplicationDetailDto
{
ClientName = s.CustomerName,
Voyage = s.Voyno,
SourceName = s.SourceName,
}, true);
var list = await TenantDb.UnionAll(query1).ToListAsync();
var result = DataResult<List<ApplicationDetailDto>>.Success(list);
result.Count = list.Count;
return result;
}
protected override async Task<List<SettlementDetailDto>> GetSettlementDetails(long id)
{
var list = await TenantDb.Queryable<ApplicationDetail>()
.InnerJoin<ApplicationDetail>((d, pd) => d.DetailId == pd.Id)
.InnerJoin<InvoiceApplication>((d, pd, pa) => pd.ApplicationId == pa.Id)
.Where(d => d.ApplicationId == id)
.Select((d, pd, pa) => new
{
d.Id,
d.ApplicationId,
d.ApplyAmount,
d.Currency,
d.OriginalCurrency,
d.OriginalAmount,
pa.ApplicationNO,
pa.Status,
pa.CreateTime,
pa.CreateBy,
pa.Note
}).ToListAsync();
var details = new List<SettlementDetailDto>();
if (list.Count == 0)
return details;
var gp = list.GroupBy(d => d.ApplicationId);
var uids = list.Select(x => x.CreateBy).Distinct();
var users = await Db.Queryable<SysUser>().Where(x => uids.Contains(x.Id)).Select(x => new
{
x.Id,
x.UserName
}).ToListAsync();
foreach (var g in gp)
{
var firstItem = g.FirstOrDefault();
var dto = new SettlementDetailDto
{
ApplicationId = g.Key,
//Ids = g.Select(x => x.Id),
RMBApplyAmount = g.Where(x => x.OriginalCurrency == FeeCurrency.RMB_CODE).Sum(x => x.ApplyAmount),
USDApplyAmount = g.Where(x => x.OriginalCurrency == FeeCurrency.USD_CODE).Sum(x => x.ApplyAmount),
ApplicationNO = firstItem.ApplicationNO,
Status = (int)firstItem.Status,
StatusText = firstItem.Status.GetDescription(),
CreateTime = firstItem?.CreateTime,
CreateBy = firstItem?.CreateBy,
CreateByName = users.Find(x => x.Id == firstItem?.CreateBy)?.UserName,
PaymentDate = firstItem?.CreateTime,
Note = firstItem?.Note
};
//包含多个币别
if (g.GroupBy(x => x.OriginalCurrency).Select(x => x.Key).Count() > 1)
{
//原始币别=不等于结算单币别的首个币别参考DS7
dto.OriginalCurrency = g.Select(x => x.OriginalCurrency).FirstOrDefault();
//原始金额=当前结算单的币别合计
dto.OriginalAmount = g.Sum(x => x.ApplyAmount);
}
else
{
dto.OriginalCurrency = firstItem?.OriginalCurrency;
dto.OriginalAmount = g.Where(x => x.OriginalCurrency == dto.OriginalCurrency).Sum(x => x.ApplyAmount);
}
//结算金额=原申请的原始币别合计
dto.SettlementAmount = g.Where(x => x.OriginalCurrency == dto.OriginalCurrency).Sum(x => x.ApplyAmount);
details.Add(dto);
}
return details;
}
protected override async Task<DataResult> PreSaveAsync(PaymentSettlement settlement)
{
//settlement.Mode = SettlementMode.InvoiceSettlement;
var appIds = settlement.Details.Select(x => x.ApplicationId).Distinct();
var appList = await TenantDb.Queryable<InvoiceApplication>().Where(x => appIds.Contains(x.Id))
.Select(x => new
{
x.Id,
x.Status,
x.CustomerId,
x.CustomerName,
}).ToListAsync();
if (appList.Count == 0)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.EmptyData));
if (appList.Exists(x => x.Status != InvoiceApplicationStatus.AuditPassed))
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.ApplicationSelectStatusError));
if (appList.GroupBy(x => x.CustomerId).Select(x => x.Key).Count() > 1)
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.DetailCustomerOnlyOne));
//获取剩余待结算金额
var ids2 = settlement.Details.Select(x => x.DetailId);
var appDetails = await TenantDb.Queryable<ApplicationDetail>().Where(x => ids2.Contains(x.Id) && x.Category == DetailCategory.InvoiceApplication)
.Select(x => new
{
x.Id,
OriginalRestAmount = x.OriginalAmount - x.OriginalSettlementAmount
}).ToListAsync();
StringBuilder sb = new();
foreach (var detail in settlement.Details)
{
var item = appDetails.Find(x => x.Id == detail.DetailId);
if (item == null)
{
sb.Append(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.EmptyData)));
break;
}
if (detail.OriginalAmount > 0 && detail.OriginalAmount > item.OriginalRestAmount)
{
sb.AppendFormat(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.DetailExceedingLimit)), detail.FeeName);
sb.Append("");
continue;
}
else if (detail.OriginalAmount < 0 && detail.OriginalAmount < item.OriginalRestAmount)
{
sb.AppendFormat(MultiLanguageConst.GetDescription(nameof(MultiLanguageConst.DetailExceedingLimit)), detail.FeeName);
sb.Append("");
continue;
}
detail.Category = DetailCategory.InvoiceSettlement;
}
return sb.Length > 0 ? DataResult.Failed(sb.ToString()) : DataResult.Success;
}
}
}