|
|
|
@ -10,6 +10,7 @@ using DS.WMS.Core.Invoice.Dtos;
|
|
|
|
|
using DS.WMS.Core.Invoice.Interface;
|
|
|
|
|
using DS.WMS.Core.Sys.Entity;
|
|
|
|
|
using DS.WMS.Core.Sys.Interface;
|
|
|
|
|
using Mapster;
|
|
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
|
using SqlSugar;
|
|
|
|
|
|
|
|
|
@ -157,6 +158,17 @@ namespace DS.WMS.Core.Invoice.Method
|
|
|
|
|
return DataResult<InvoiceDto>.Success(invoice);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 根据业务编号及类型获取费用记录
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="items">业务ID与业务类型</param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public virtual Task<DataResult<InvoiceApplicaitonBiz>> GetFeesAsync(params FeeClient[] items)
|
|
|
|
|
{
|
|
|
|
|
return Task.FromResult(DataResult<InvoiceApplicaitonBiz>.Success(
|
|
|
|
|
new InvoiceApplicaitonBiz(new List<FeeInvoiceDto>())));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#pragma warning disable CS4014
|
|
|
|
|
|
|
|
|
@ -191,176 +203,191 @@ namespace DS.WMS.Core.Invoice.Method
|
|
|
|
|
|
|
|
|
|
invoice.OperatorId ??= long.Parse(User.UserId);
|
|
|
|
|
|
|
|
|
|
//按发票申请
|
|
|
|
|
if (request.Applications != null && request.Applications.Count > 0)
|
|
|
|
|
if (request.Invoice.Mode == InvoiceMode.Applcation && request.Applications != null && request.Applications.Count > 0) //发票申请开出
|
|
|
|
|
{
|
|
|
|
|
var ids = request.Applications.Select(x => x.ApplicationId);
|
|
|
|
|
var details = await TenantDb.Queryable<ApplicationDetail>()
|
|
|
|
|
.InnerJoin<InvoiceApplication>((x, y) => x.ApplicationId == y.Id)
|
|
|
|
|
.LeftJoin<InfoClientBank>((x, y, z) => y.CustomerId == z.ClientId && z.Currency == invoice.Currency && z.IsInvoiceDefault == true)
|
|
|
|
|
.Where((x, y, z) => ids.Contains(x.ApplicationId) && x.Category == DetailCategory.InvoiceApplication)
|
|
|
|
|
.Select((x, y, z) => new
|
|
|
|
|
{
|
|
|
|
|
x.Id,
|
|
|
|
|
x.ApplicationId,
|
|
|
|
|
x.RecordId,
|
|
|
|
|
x.CustomerName,
|
|
|
|
|
x.FeeId,
|
|
|
|
|
x.FeeType,
|
|
|
|
|
x.FeeName,
|
|
|
|
|
x.ApplyAmount,
|
|
|
|
|
x.OriginalAmount,
|
|
|
|
|
x.Currency,
|
|
|
|
|
x.OriginalCurrency,
|
|
|
|
|
x.ProcessedAmount,
|
|
|
|
|
x.OriginalProcessedAmount,
|
|
|
|
|
|
|
|
|
|
y.CustomerId,
|
|
|
|
|
y.TaxRate,
|
|
|
|
|
y.TaxID,
|
|
|
|
|
y.InvoiceHeader,
|
|
|
|
|
y.CustomerAddTel,
|
|
|
|
|
y.SaleDeptId,
|
|
|
|
|
y.PushMode,
|
|
|
|
|
y.CellPhoneNO,
|
|
|
|
|
y.Email,
|
|
|
|
|
|
|
|
|
|
z.BankAccountNo,
|
|
|
|
|
z.BankName
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
|
|
|
|
|
//税率不一致
|
|
|
|
|
if (details.GroupBy(x => x.TaxRate).Select(x => x.Key).Count() > 1)
|
|
|
|
|
return DataResult<TEntity>.FailedWithDesc(nameof(MultiLanguageConst.InvoiceCustomerOnlyOne));
|
|
|
|
|
|
|
|
|
|
invoice.Details ??= new List<ApplicationDetail>(details.Count);
|
|
|
|
|
foreach (var item in details)
|
|
|
|
|
if (request.Invoice.Mode == InvoiceMode.Applcation) //按发票申请
|
|
|
|
|
{
|
|
|
|
|
if (invoice.CustomerId == 0)
|
|
|
|
|
{
|
|
|
|
|
invoice.CustomerId = item.CustomerId;
|
|
|
|
|
invoice.CustomerName = item.CustomerName;
|
|
|
|
|
invoice.TaxRate = item.TaxRate;
|
|
|
|
|
invoice.InvoiceHeader = item.InvoiceHeader;
|
|
|
|
|
invoice.CustomerTaxID = item.TaxID;
|
|
|
|
|
invoice.CustomerAddressTel = item.CustomerAddTel;
|
|
|
|
|
invoice.CustomerAccount = item.BankAccountNo;
|
|
|
|
|
invoice.CustomerBankName = item.BankName;
|
|
|
|
|
invoice.SaleDeptId = item.SaleDeptId;
|
|
|
|
|
invoice.PushMode = item.PushMode;
|
|
|
|
|
invoice.CellPhoneNO = item.CellPhoneNO;
|
|
|
|
|
invoice.Email = item.Email;
|
|
|
|
|
}
|
|
|
|
|
else if (invoice.CustomerId != item.CustomerId) //校验开票单位是否一致
|
|
|
|
|
{
|
|
|
|
|
return DataResult<TEntity>.FailedWithDesc(nameof(MultiLanguageConst.InvoiceCustomerOnlyOne));
|
|
|
|
|
}
|
|
|
|
|
else if (invoice.TaxRate != item.TaxRate) //校验税率是否一致
|
|
|
|
|
{
|
|
|
|
|
return DataResult<TEntity>.FailedWithDesc(nameof(MultiLanguageConst.InconsistentTaxRates));
|
|
|
|
|
}
|
|
|
|
|
var details = await TenantDb.Queryable<ApplicationDetail>()
|
|
|
|
|
.InnerJoin<InvoiceApplication>((x, y) => x.ApplicationId == y.Id)
|
|
|
|
|
.LeftJoin<InfoClientBank>((x, y, z) => y.CustomerId == z.ClientId && z.Currency == invoice.Currency && z.IsInvoiceDefault == true)
|
|
|
|
|
.Where((x, y, z) => ids.Contains(x.ApplicationId) && x.Category == DetailCategory.InvoiceApplication)
|
|
|
|
|
.Select((x, y, z) => new
|
|
|
|
|
{
|
|
|
|
|
x.Id,
|
|
|
|
|
x.ApplicationId,
|
|
|
|
|
x.RecordId,
|
|
|
|
|
x.CustomerName,
|
|
|
|
|
x.FeeId,
|
|
|
|
|
x.FeeType,
|
|
|
|
|
x.FeeName,
|
|
|
|
|
x.ApplyAmount,
|
|
|
|
|
x.OriginalAmount,
|
|
|
|
|
x.Currency,
|
|
|
|
|
x.OriginalCurrency,
|
|
|
|
|
x.ProcessedAmount,
|
|
|
|
|
x.OriginalProcessedAmount,
|
|
|
|
|
|
|
|
|
|
y.CustomerId,
|
|
|
|
|
y.TaxRate,
|
|
|
|
|
y.TaxID,
|
|
|
|
|
y.InvoiceHeader,
|
|
|
|
|
y.CustomerAddTel,
|
|
|
|
|
y.SaleDeptId,
|
|
|
|
|
y.PushMode,
|
|
|
|
|
y.CellPhoneNO,
|
|
|
|
|
y.Email,
|
|
|
|
|
|
|
|
|
|
z.BankAccountNo,
|
|
|
|
|
z.BankName
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
|
|
|
|
|
//需转换为费用明细
|
|
|
|
|
var detail = new ApplicationDetail
|
|
|
|
|
{
|
|
|
|
|
ApplicationId = invoice.Id,
|
|
|
|
|
RefId = item.ApplicationId,
|
|
|
|
|
DetailId = item.Id,
|
|
|
|
|
RecordId = item.RecordId,
|
|
|
|
|
Category = DetailCategory.InvoiceIssuance,
|
|
|
|
|
CustomerName = item.CustomerName,
|
|
|
|
|
FeeId = item.FeeId,
|
|
|
|
|
FeeName = item.FeeName,
|
|
|
|
|
FeeType = item.FeeType,
|
|
|
|
|
Currency = invoice.Currency,
|
|
|
|
|
OriginalCurrency = item.Currency,
|
|
|
|
|
ApplyAmount = item.ApplyAmount - item.ProcessedAmount,
|
|
|
|
|
OriginalAmount = item.OriginalAmount - item.OriginalProcessedAmount
|
|
|
|
|
};
|
|
|
|
|
//税率不一致
|
|
|
|
|
if (details.GroupBy(x => x.TaxRate).Select(x => x.Key).Count() > 1)
|
|
|
|
|
return DataResult<TEntity>.FailedWithDesc(nameof(MultiLanguageConst.InconsistentTaxRates));
|
|
|
|
|
|
|
|
|
|
var app = request.Applications.Find(x => x.ApplicationId == item.ApplicationId);
|
|
|
|
|
if (app != null)
|
|
|
|
|
invoice.Details ??= new List<ApplicationDetail>(details.Count);
|
|
|
|
|
foreach (var item in details)
|
|
|
|
|
{
|
|
|
|
|
if (app.Currency == invoice.Currency)
|
|
|
|
|
if (invoice.CustomerId == 0)
|
|
|
|
|
{
|
|
|
|
|
detail.ExchangeRate = 1m;
|
|
|
|
|
invoice.CustomerId = item.CustomerId;
|
|
|
|
|
invoice.CustomerName = item.CustomerName;
|
|
|
|
|
invoice.TaxRate = item.TaxRate;
|
|
|
|
|
invoice.InvoiceHeader = item.InvoiceHeader;
|
|
|
|
|
invoice.CustomerTaxID = item.TaxID;
|
|
|
|
|
invoice.CustomerAddressTel = item.CustomerAddTel;
|
|
|
|
|
invoice.CustomerAccount = item.BankAccountNo;
|
|
|
|
|
invoice.CustomerBankName = item.BankName;
|
|
|
|
|
invoice.SaleDeptId = item.SaleDeptId;
|
|
|
|
|
invoice.PushMode = item.PushMode;
|
|
|
|
|
invoice.CellPhoneNO = item.CellPhoneNO;
|
|
|
|
|
invoice.Email = item.Email;
|
|
|
|
|
}
|
|
|
|
|
else if (string.IsNullOrEmpty(app.Currency)) //原币申请
|
|
|
|
|
else if (invoice.CustomerId != item.CustomerId) //校验开票单位是否一致
|
|
|
|
|
{
|
|
|
|
|
detail.ExchangeRate = app.ExchangeRates.FirstOrDefault(
|
|
|
|
|
x => x.Currency == invoice.Currency)?.ExchangeRate;
|
|
|
|
|
return DataResult<TEntity>.FailedWithDesc(nameof(MultiLanguageConst.InvoiceCustomerOnlyOne));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
else if (invoice.TaxRate != item.TaxRate) //校验税率是否一致
|
|
|
|
|
{
|
|
|
|
|
detail.ExchangeRate = app.ExchangeRates.FirstOrDefault(
|
|
|
|
|
x => x.Currency == invoice.Currency)?.ExchangeRate;
|
|
|
|
|
return DataResult<TEntity>.FailedWithDesc(nameof(MultiLanguageConst.InconsistentTaxRates));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!detail.ExchangeRate.HasValue)
|
|
|
|
|
detail.ExchangeRate = 1m;
|
|
|
|
|
//需转换为费用明细
|
|
|
|
|
var detail = new ApplicationDetail
|
|
|
|
|
{
|
|
|
|
|
ApplicationId = invoice.Id,
|
|
|
|
|
RefId = item.ApplicationId,
|
|
|
|
|
DetailId = item.Id,
|
|
|
|
|
RecordId = item.RecordId,
|
|
|
|
|
Category = DetailCategory.InvoiceIssuance,
|
|
|
|
|
CustomerName = item.CustomerName,
|
|
|
|
|
FeeId = item.FeeId,
|
|
|
|
|
FeeName = item.FeeName,
|
|
|
|
|
FeeType = item.FeeType,
|
|
|
|
|
Currency = invoice.Currency,
|
|
|
|
|
OriginalCurrency = item.Currency,
|
|
|
|
|
ApplyAmount = item.ApplyAmount - item.ProcessedAmount,
|
|
|
|
|
OriginalAmount = item.OriginalAmount - item.OriginalProcessedAmount
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var app = request.Applications.Find(x => x.ApplicationId == item.ApplicationId);
|
|
|
|
|
if (app != null)
|
|
|
|
|
{
|
|
|
|
|
if (app.Currency == invoice.Currency)
|
|
|
|
|
{
|
|
|
|
|
detail.ExchangeRate = 1m;
|
|
|
|
|
}
|
|
|
|
|
else if (string.IsNullOrEmpty(app.Currency)) //原币申请
|
|
|
|
|
{
|
|
|
|
|
detail.ExchangeRate = app.ExchangeRates.FirstOrDefault(
|
|
|
|
|
x => x.Currency == invoice.Currency)?.ExchangeRate;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
detail.ExchangeRate = app.ExchangeRates.FirstOrDefault(
|
|
|
|
|
x => x.Currency == invoice.Currency)?.ExchangeRate;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!detail.ExchangeRate.HasValue)
|
|
|
|
|
detail.ExchangeRate = 1m;
|
|
|
|
|
|
|
|
|
|
if (detail.ExchangeRate.HasValue)
|
|
|
|
|
detail.ApplyAmount = detail.ApplyAmount * detail.ExchangeRate.Value;
|
|
|
|
|
if (detail.ExchangeRate.HasValue)
|
|
|
|
|
detail.ApplyAmount = detail.ApplyAmount * detail.ExchangeRate.Value;
|
|
|
|
|
|
|
|
|
|
invoice.Details.Add(detail);
|
|
|
|
|
invoice.Details.Add(detail);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//自由申请
|
|
|
|
|
if (request.Details?.Count > 0)
|
|
|
|
|
else if (request.Invoice.Mode == InvoiceMode.Free) //自由开票
|
|
|
|
|
{
|
|
|
|
|
if (invoice.Id == 0 && invoice.CustomerId == 0)
|
|
|
|
|
if (request.BizList?.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
var first = request.Details[0];
|
|
|
|
|
invoice.CustomerId = first.CustomerId;
|
|
|
|
|
invoice.CustomerName = first.CustomerName;
|
|
|
|
|
var result2 = await GetFeesAsync([.. request.BizList]);
|
|
|
|
|
if (result2.Data != null)
|
|
|
|
|
{
|
|
|
|
|
request.Details ??= [];
|
|
|
|
|
foreach (var item in result2.Data.Items)
|
|
|
|
|
request.Details.Add(item.Adapt<PaymentApplicationDetailDto>());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var ids = request.Details.Select(x => x.RecordId).Distinct();
|
|
|
|
|
var fees = await TenantDb.Queryable<FeeRecord>().Where(x => ids.Contains(x.Id)).Select(x => new { x.Id, x.TaxRate }).ToListAsync();
|
|
|
|
|
//税率不一致
|
|
|
|
|
if (fees.GroupBy(x => x.TaxRate).Select(x => x.Key).Count() > 1 || (invoice.Id > 0 && invoice.TaxRate != fees[0].TaxRate))
|
|
|
|
|
return DataResult<TEntity>.FailedWithDesc(nameof(MultiLanguageConst.InvoiceCustomerOnlyOne));
|
|
|
|
|
|
|
|
|
|
//将请求明细转换为数据库的费用明细
|
|
|
|
|
invoice.Details = request.Details.Select(x => new ApplicationDetail
|
|
|
|
|
if (request.Details?.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
Id = x.Id,
|
|
|
|
|
ApplicationId = x.ApplicationId == 0 ? x.ApplicationId : invoice.Id,
|
|
|
|
|
RefId = x.RefId,
|
|
|
|
|
DetailId = x.Id == 0 ? null : x.Id,
|
|
|
|
|
RecordId = x.RecordId,
|
|
|
|
|
Category = DetailCategory.InvoiceIssuance,
|
|
|
|
|
CustomerName = x.CustomerName ?? invoice.CustomerName,
|
|
|
|
|
FeeId = x.FeeId,
|
|
|
|
|
FeeName = x.FeeName,
|
|
|
|
|
FeeType = x.FeeType,
|
|
|
|
|
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.Id == 0 && invoice.CustomerId == 0)
|
|
|
|
|
{
|
|
|
|
|
var first = request.Details[0];
|
|
|
|
|
invoice.CustomerId = first.CustomerId;
|
|
|
|
|
invoice.CustomerName = first.CustomerName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//补充购方信息
|
|
|
|
|
invoice.CustomerTaxID = await TenantDb.Queryable<InfoClient>().Where(x => x.Id == invoice.CustomerId).Select(x => x.TaxNo).FirstAsync();
|
|
|
|
|
var header = await TenantDb.Queryable<InvoiceHeader>().Where(x => x.RelativeId == invoice.CustomerId)
|
|
|
|
|
.OrderByDescending(x => x.Id).FirstAsync();
|
|
|
|
|
if (header != null)
|
|
|
|
|
{
|
|
|
|
|
invoice.InvoiceHeader = header.Header;
|
|
|
|
|
invoice.CustomerAddressTel = header.AddressTel;
|
|
|
|
|
}
|
|
|
|
|
var clientBank = await TenantDb.Queryable<InfoClientBank>().Where(x => x.ClientId == invoice.CustomerId && x.Currency == invoice.Currency)
|
|
|
|
|
.OrderByDescending(x => x.IsInvoiceDefault).Select(x => new
|
|
|
|
|
var ids = request.Details.Select(x => x.RecordId).Distinct();
|
|
|
|
|
var fees = await TenantDb.Queryable<FeeRecord>().Where(x => ids.Contains(x.Id)).Select(x => new { x.Id, x.TaxRate }).ToListAsync();
|
|
|
|
|
//税率不一致
|
|
|
|
|
if (fees.GroupBy(x => x.TaxRate).Select(x => x.Key).Count() > 1 || (invoice.Id > 0 && invoice.TaxRate != fees[0].TaxRate))
|
|
|
|
|
return DataResult<TEntity>.FailedWithDesc(nameof(MultiLanguageConst.InconsistentTaxRates));
|
|
|
|
|
|
|
|
|
|
//将请求明细转换为数据库的费用明细
|
|
|
|
|
invoice.Details = request.Details.Select(x => new ApplicationDetail
|
|
|
|
|
{
|
|
|
|
|
x.Account,
|
|
|
|
|
x.BankName
|
|
|
|
|
}).FirstAsync();
|
|
|
|
|
if (clientBank != null)
|
|
|
|
|
{
|
|
|
|
|
invoice.CustomerAccount = clientBank.Account;
|
|
|
|
|
invoice.CustomerBankName = clientBank.BankName;
|
|
|
|
|
Id = x.Id,
|
|
|
|
|
ApplicationId = x.ApplicationId == 0 ? x.ApplicationId : invoice.Id,
|
|
|
|
|
RefId = x.RefId,
|
|
|
|
|
DetailId = x.Id == 0 ? null : x.Id,
|
|
|
|
|
RecordId = x.RecordId,
|
|
|
|
|
Category = DetailCategory.InvoiceIssuance,
|
|
|
|
|
CustomerName = x.CustomerName ?? invoice.CustomerName,
|
|
|
|
|
FeeId = x.FeeId,
|
|
|
|
|
FeeName = x.FeeName,
|
|
|
|
|
FeeType = x.FeeType,
|
|
|
|
|
Currency = x.Currency,
|
|
|
|
|
ApplyAmount = x.ApplyAmount,
|
|
|
|
|
ExchangeRate = x.ExchangeRate,
|
|
|
|
|
OriginalAmount = x.OriginalAmount,
|
|
|
|
|
OriginalCurrency = x.OriginalCurrency ?? (invoice.Currency.IsNullOrEmpty() ? x.Currency : invoice.Currency),
|
|
|
|
|
}).ToList();
|
|
|
|
|
|
|
|
|
|
//补充购方信息
|
|
|
|
|
invoice.CustomerTaxID = await TenantDb.Queryable<InfoClient>().Where(x => x.Id == invoice.CustomerId).Select(x => x.TaxNo).FirstAsync();
|
|
|
|
|
var header = await TenantDb.Queryable<InvoiceHeader>().Where(x => x.RelativeId == invoice.CustomerId)
|
|
|
|
|
.OrderByDescending(x => x.Id).FirstAsync();
|
|
|
|
|
if (header != null)
|
|
|
|
|
{
|
|
|
|
|
invoice.InvoiceHeader = header.Header;
|
|
|
|
|
invoice.CustomerAddressTel = header.AddressTel;
|
|
|
|
|
}
|
|
|
|
|
var clientBank = await TenantDb.Queryable<InfoClientBank>().Where(x => x.ClientId == invoice.CustomerId && x.Currency == invoice.Currency)
|
|
|
|
|
.OrderByDescending(x => x.IsInvoiceDefault).Select(x => new
|
|
|
|
|
{
|
|
|
|
|
x.Account,
|
|
|
|
|
x.BankName
|
|
|
|
|
}).FirstAsync();
|
|
|
|
|
if (clientBank != null)
|
|
|
|
|
{
|
|
|
|
|
invoice.CustomerAccount = clientBank.Account;
|
|
|
|
|
invoice.CustomerBankName = clientBank.BankName;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|