diff --git a/ds-wms-service/DS.WMS.Core/Application/Entity/InvoiceDetail.cs b/ds-wms-service/DS.WMS.Core/Application/Entity/InvoiceDetail.cs
index f465c4ad..4f8860b4 100644
--- a/ds-wms-service/DS.WMS.Core/Application/Entity/InvoiceDetail.cs
+++ b/ds-wms-service/DS.WMS.Core/Application/Entity/InvoiceDetail.cs
@@ -92,5 +92,11 @@ namespace DS.WMS.Core.Application.Entity
///
[SugarColumn(ColumnDescription = "类别", IsNullable = true)]
public DetailCategory Category { get; set; }
+
+ ///
+ /// 币别
+ ///
+ [SugarColumn(ColumnDescription = "币别", IsNullable = false, Length = 3)]
+ public string Currency { get; set; }
}
}
diff --git a/ds-wms-service/DS.WMS.Core/Application/Method/InvoiceApplicationService.cs b/ds-wms-service/DS.WMS.Core/Application/Method/InvoiceApplicationService.cs
index 0377ac7d..240ce73e 100644
--- a/ds-wms-service/DS.WMS.Core/Application/Method/InvoiceApplicationService.cs
+++ b/ds-wms-service/DS.WMS.Core/Application/Method/InvoiceApplicationService.cs
@@ -653,6 +653,7 @@ namespace DS.WMS.Core.Application.Method
ApplicationId = application.Id,
CodeId = code.Id,
Name = code.Name,
+ Currency = code.DefaultCurrency ?? string.Empty,
Quantity = 1,
TaxUnitPrice = detail.ApplyAmount,
TaxRate = code.TaxRate,
diff --git a/ds-wms-service/DS.WMS.Core/Invoice/Interface/IInvoiceIssuanceService.cs b/ds-wms-service/DS.WMS.Core/Invoice/Interface/IInvoiceIssuanceService.cs
index 26fe8383..309e6371 100644
--- a/ds-wms-service/DS.WMS.Core/Invoice/Interface/IInvoiceIssuanceService.cs
+++ b/ds-wms-service/DS.WMS.Core/Invoice/Interface/IInvoiceIssuanceService.cs
@@ -36,5 +36,12 @@ namespace DS.WMS.Core.Invoice.Interface
///
/// 当为null时引发。
Task AddTenantAsync(Tenant tenant);
+
+ ///
+ /// 发送邮件
+ ///
+ /// 发票ID
+ ///
+ Task SendMailAsync(long id);
}
}
diff --git a/ds-wms-service/DS.WMS.Core/Invoice/Method/GeneralInvoiceService.cs b/ds-wms-service/DS.WMS.Core/Invoice/Method/GeneralInvoiceService.cs
index 103c7db1..496ff7a2 100644
--- a/ds-wms-service/DS.WMS.Core/Invoice/Method/GeneralInvoiceService.cs
+++ b/ds-wms-service/DS.WMS.Core/Invoice/Method/GeneralInvoiceService.cs
@@ -132,7 +132,8 @@ namespace DS.WMS.Core.Invoice.Method
var list = invoice.Details?.Where(x => x.DetailId.HasValue).Select(x => new ApplicationDetail
{
Id = x.DetailId.GetValueOrDefault(),
- ProcessedAmount = x.ApplyAmount,
+ ProcessedAmount = x.Currency == x.OriginalCurrency ?
+ x.ApplyAmount : x.ApplyAmount / (x.ExchangeRate ?? 1),
OriginalProcessedAmount = x.OriginalAmount
}).ToList();
@@ -148,55 +149,33 @@ namespace DS.WMS.Core.Invoice.Method
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();
-
- //还原发票申请状态
- var ids = list.Where(x => x.DetailId.HasValue).Select(x => x.DetailId).Distinct();
- var details = TenantDb.Queryable().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 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)
+ var items = invoices.SelectMany(x => x.Details);
+ var ids = items.Select(x => x.DetailId);
+ //获取发票申请明细
+ var details = await TenantDb.Queryable().Where(x => ids.Contains(x.Id))
+ .Select(x => new ApplicationDetail
{
- entity.Status = InvoiceApplicationStatus.AuditPassed;
- }
- else if (itemCount > processedCount)
- {
- entity.Status = InvoiceApplicationStatus.PartialInvoiced;
- }
+ Id = x.Id,
+ Currency = x.Currency,
+ ApplicationId = x.ApplicationId,
+ ProcessedAmount = x.ProcessedAmount,
+ OriginalAmount = x.OriginalAmount,
+ OriginalProcessedAmount = x.OriginalProcessedAmount
+ }).ToListAsync();
- applications.Add(entity);
+ foreach (var detail in details)
+ {
+ var item = items.FirstOrDefault(x => x.DetailId == detail.Id);
+ detail.ProcessedAmount -= detail.Currency == item.Currency ? item.ApplyAmount : item.OriginalAmount;
+ detail.OriginalProcessedAmount -= item.OriginalAmount;
}
- if (applications.Count > 0)
- await TenantDb.Updateable(applications).UpdateColumns(x => new { x.Status }).ExecuteCommandAsync();
+ //恢复发票申请费用明细的已处理金额
+ await TenantDb.Updateable(details)
+ .UpdateColumns(x => new { x.ProcessedAmount, x.OriginalProcessedAmount })
+ .ExecuteCommandAsync();
+
await base.OnDeleteDetailAsync(invoices, deleteOption);
}
diff --git a/ds-wms-service/DS.WMS.Core/Invoice/Method/InvoiceIssuanceService.cs b/ds-wms-service/DS.WMS.Core/Invoice/Method/InvoiceIssuanceService.cs
index bc25da9f..be469346 100644
--- a/ds-wms-service/DS.WMS.Core/Invoice/Method/InvoiceIssuanceService.cs
+++ b/ds-wms-service/DS.WMS.Core/Invoice/Method/InvoiceIssuanceService.cs
@@ -15,7 +15,7 @@ using SqlSugar;
namespace DS.WMS.Core.Invoice.Method
{
///
- /// 发票开具服务
+ /// 发票开出接口服务
///
public sealed class InvoiceIssuanceService : ApplicationServiceBase, IInvoiceIssuanceService
{
@@ -167,21 +167,22 @@ namespace DS.WMS.Core.Invoice.Method
///
public async Task UpdateInvoiceNumberAsync(string sn)
{
- var result2 = DataResult.Success;
+ var invResult = DataResult.Success;
var invoices = await TenantDb.Queryable()
- .Where(x => x.SN == sn && !SqlFunc.IsNullOrEmpty(x.PDFUrl))
+ .Where(x => x.SN == sn && !SqlFunc.IsNullOrEmpty(x.InvoiceNO))
.Select(x => new Entity.Invoice
{
SN = x.SN,
BillNO = x.BillNO,
InvoiceNO = x.InvoiceNO,
+ Type = x.Type,
ApiCode = x.ApiCode,
ApiStatus = x.ApiStatus,
PDFUrl = x.PDFUrl
}).ToListAsync();
- result2.Data = invoices;
+ invResult.Data = invoices;
if (invoices.Count > 0)
- return result2;
+ return invResult;
var order = await TenantDb.Queryable().Where(x => x.SN == sn).FirstAsync();
//如果开票中所属机构为空,则取用户的orgId
@@ -212,6 +213,18 @@ namespace DS.WMS.Core.Invoice.Method
if (queryResult.data.Order?.Count > 0)
{
+ var billNumbers = queryResult.data.Order.Select(x => x.orderNo);
+ //获取发票ID及类型
+ var list = await TenantDb.Queryable().Where(x => billNumbers.Contains(x.BillNO))
+ .Select(x => new
+ {
+ x.Id,
+ x.BillNO,
+ x.Type,
+ x.Mode
+ }).ToListAsync();
+ DateTime dtNow = DateTime.Now;
+ long userId = long.Parse(User.UserId);
foreach (var item in queryResult.data.Order)
{
var inv = new Entity.Invoice
@@ -221,8 +234,18 @@ namespace DS.WMS.Core.Invoice.Method
InvoiceNO = item.fphm,
ApiCode = item.State.ToString(),
ApiStatus = item.UpMessage,
- PDFUrl = item.FileUrl
+ PDFUrl = item.FileUrl,
+ IsLocked = true,
+ LockTime = dtNow,
+ LockUserId = userId
};
+ var storedItem = list.Find(x => x.BillNO == inv.BillNO);
+ if (storedItem == null)
+ return DataResult.FailedWithDesc(nameof(MultiLanguageConst.EmptyData));
+
+ inv.Id = storedItem.Id;
+ inv.Type = storedItem.Type;
+ inv.Mode = storedItem.Mode;
invoices.Add(inv);
switch (item.State)
@@ -242,28 +265,33 @@ namespace DS.WMS.Core.Invoice.Method
await TenantDb.Ado.BeginTranAsync();
try
{
- var billNumbers = invoices.Select(x => x.BillNO);
- //获取发票费用明细ID
- var ids = await TenantDb.Queryable()
- .InnerJoin((i, d) => i.Id == d.ApplicationId)
- .Where((i, d) => billNumbers.Contains(i.BillNO) && i.Type == InvoiceType.Blue)
- .Select((i, d) => d.Id).ToArrayAsync();
- if (ids.Length > 0)
+ var redIds = invoices.Where(x => x.Type == InvoiceType.Red).Select(x => x.Id).ToList();
+ //开出红票时,需要删除蓝票的费用明细
+ if (redIds.Count > 0)
{
+ //获取蓝票费用明细ID
+ var ids = await TenantDb.Queryable()
+ .InnerJoin((d, i) => d.ApplicationId == i.Id)
+ .Where((d, i) => redIds.Contains(i.RedId.Value))
+ .Select((d, i) => d.Id).ToArrayAsync();
//删除蓝票费用明细
await InvoiceService.Value.DeleteDetailAsync(ids);
}
- await TenantDb.Updateable(invoices).WhereColumns(x => x.BillNO)
- .UpdateColumns(x => new
- {
- x.InvoiceNO,
- x.ApiCode,
- x.ApiStatus,
- x.PDFUrl
- }).ExecuteCommandAsync();
-
- await InvoiceService.Value.RefreshApplicationStatus(invoices.Select(x => x.InvoiceNO)!);
+ await TenantDb.Updateable(invoices).UpdateColumns(x => new
+ {
+ x.InvoiceNO,
+ x.ApiCode,
+ x.ApiStatus,
+ x.PDFUrl,
+ x.IsLocked,
+ x.LockUserId,
+ x.LockTime
+ }).ExecuteCommandAsync();
+
+ //回写发票申请的状态
+ if (invoices.Exists(x => x.Mode == InvoiceMode.Applcation && x.Type == InvoiceType.Blue))
+ await InvoiceService.Value.RefreshApplicationStatus(invoices.Select(x => x.InvoiceNO)!);
await TenantDb.Ado.CommitTranAsync();
}
@@ -275,8 +303,8 @@ namespace DS.WMS.Core.Invoice.Method
}
}
- result2.Data = invoices;
- return result2;
+ invResult.Data = invoices;
+ return invResult;
}
///
@@ -350,6 +378,7 @@ namespace DS.WMS.Core.Invoice.Method
try
{
await TenantDb.InsertNav(redInvoice).Include(x => x.Details).Include(x => x.InvoiceDetails).ExecuteCommandAsync();
+
blueInvoice.RedId = redInvoice.Id;
blueInvoice.IsSetRed = true;
blueInvoice.RedCode = request.chyyDm;
@@ -407,6 +436,40 @@ namespace DS.WMS.Core.Invoice.Method
}
}
+ ///
+ /// 发送邮件
+ ///
+ /// 发票ID
+ ///
+ public async Task SendMailAsync(long id)
+ {
+ var inv = await TenantDb.Queryable().Where(x => x.Id == id)
+ .Select(x => new
+ {
+ orderNo = x.BillNO,
+ x.SaleDeptId,
+ x.InvoiceNO
+ }).FirstAsync();
+ if (inv == null)
+ return DataResult.FailedWithDesc(nameof(MultiLanguageConst.EmptyData));
+
+ if (!string.IsNullOrEmpty(inv.InvoiceNO))
+ return DataResult.Failed("发票尚未开出");
+
+ //如果开票中所属机构为空,则取用户的orgId
+ var userOrgId = (inv.SaleDeptId != null && inv.SaleDeptId > 0) ? inv.SaleDeptId : User.OrgId;
+ //接口请求key密钥
+ var orgauthinfo = Db.Queryable().Where(t => t.OrgId == userOrgId).First();
+ api.DefaultHeaders.Clear();
+ api.DefaultHeaders.Add("USER_KEY", orgauthinfo.Key);
+ api.DefaultHeaders.Add("USER_SECRET", orgauthinfo.Secret);
+ var result = await api.PostAsync>(AppSetting.app(["InvoiceApi", "BaseUrl"]) + "/api/Invoice/InvoiceToEmil", inv);
+ if (result.Data == null || !result.Data.success)
+ return DataResult.Failed(result.Data == null ? "请求失败" : result.Data.msg);
+
+ return DataResult.Success;
+ }
+
///
/// 添加租户信息
///
diff --git a/ds-wms-service/DS.WMS.Core/Invoice/Method/InvoiceService`1.cs b/ds-wms-service/DS.WMS.Core/Invoice/Method/InvoiceService`1.cs
index c217714d..a31654c6 100644
--- a/ds-wms-service/DS.WMS.Core/Invoice/Method/InvoiceService`1.cs
+++ b/ds-wms-service/DS.WMS.Core/Invoice/Method/InvoiceService`1.cs
@@ -9,6 +9,7 @@ using DS.WMS.Core.Code.Entity;
using DS.WMS.Core.Fee.Entity;
using DS.WMS.Core.Info.Entity;
using DS.WMS.Core.Invoice.Dtos;
+using DS.WMS.Core.Invoice.Entity;
using DS.WMS.Core.Invoice.Interface;
using DS.WMS.Core.Op.Entity;
using DS.WMS.Core.Sys.Entity;
@@ -222,7 +223,9 @@ namespace DS.WMS.Core.Invoice.Method
dbValue = await TenantDb.Queryable().Select(x => new TEntity
{
Id = x.Id,
+ InvoiceNO = x.InvoiceNO,
IsLocked = x.IsLocked,
+ IsSettled = x.IsSettled,
Mode = x.Mode,
}).FirstAsync(x => x.Id == request.Invoice.Id);
}
@@ -362,7 +365,7 @@ namespace DS.WMS.Core.Invoice.Method
if (app.AmountOther.HasValue)
{
- result2 = AssignAmount(details2.FindAll(x => x.Currency != FeeCurrency.RMB_CODE && x.OriginalCurrency != FeeCurrency.USD_CODE), app.AmountOther.Value);
+ result2 = AssignAmount(details2.FindAll(x => x.Currency != FeeCurrency.RMB_CODE && x.Currency != FeeCurrency.USD_CODE), app.AmountOther.Value);
if (!result2.Succeeded)
return DataResult.Failed(result2.Message, result2.MultiCode);
}
@@ -458,8 +461,7 @@ namespace DS.WMS.Core.Invoice.Method
}
//补充销方信息
- //var org = await Db.Queryable().Where(x => x.Id == User.OrgId).Select(x => new { x.OrgFullName, x.LicenseCode }).FirstAsync();
- var orgId = invoice.SaleDeptId ?? User.OrgId;
+ var orgId = invoice.SaleDeptId.GetValueOrDefault() == 0 ? User.OrgId : invoice.SaleDeptId;
var org = await Db.Queryable().LeftJoin((t, a) => t.Id == a.OrgId).Where((t, a) => t.Id == orgId).Select((t, a) => new { t.OrgFullName, t.LicenseCode }).FirstAsync();
if (org != null)
{
@@ -477,9 +479,6 @@ namespace DS.WMS.Core.Invoice.Method
invoice.Account = orgBank.BankAccountNo;
}
- //生成默认备注
- //invoice.InvoiceRemark = $"购买方地址电话:" + Environment.NewLine + invoice.CustomerAddressTel + Environment.NewLine
- // + "购买方开户行/账号:" + invoice.CustomerBankName + " " + invoice.CustomerAccount;
if (!string.IsNullOrEmpty(invRemark))
{
invoice.Note += Environment.NewLine + invRemark;
@@ -696,6 +695,7 @@ namespace DS.WMS.Core.Invoice.Method
ApplicationId = invoice.Id,
CodeId = code.Id,
Name = code.Name,
+ Currency = FeeCurrency.RMB_CODE,
Quantity = 1,
TaxUnitPrice = detail.ApplyAmount,
TaxRate = code.TaxRate,
@@ -765,8 +765,17 @@ namespace DS.WMS.Core.Invoice.Method
///
protected virtual DataResult EnsureSettlement(TEntity invoice, TEntity? dbValue)
{
- if (dbValue != null && dbValue.IsLocked)
- return DataResult.FailedWithDesc(nameof(MultiLanguageConst.InvoiceIsLocked));
+ if (dbValue != null)
+ {
+ if (dbValue.IsLocked)
+ return DataResult.FailedWithDesc(nameof(MultiLanguageConst.InvoiceIsLocked));
+
+ if (!string.IsNullOrEmpty(dbValue.InvoiceNO))
+ return DataResult.FailedWithDesc(nameof(MultiLanguageConst.InvoiceIsIssued));
+
+ if (dbValue.IsSettled)
+ return DataResult.FailedWithDesc(nameof(MultiLanguageConst.InvoiceIsSettled));
+ }
return DataResult.Success;
}
@@ -947,11 +956,14 @@ namespace DS.WMS.Core.Invoice.Method
if (invoices.Any(x => x.IsLocked))
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.InvoiceIsLocked));
- if (invoices.Any(x => !string.IsNullOrEmpty(x.ApiCode)))
+ if (invoices.Any(x => !string.IsNullOrEmpty(x.InvoiceNO)))
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.InvoiceIsIssued));
- var ids = invoices.Select(x => x.Id);
- if (TenantDb.Queryable().Any(x => ids.Contains(x.RefId.Value) && x.Category == DetailCategory.InvoiceSettlement))
+ //var ids = invoices.Select(x => x.Id);
+ //if (TenantDb.Queryable().Any(x => ids.Contains(x.RefId.Value) && x.Category == DetailCategory.InvoiceSettlement))
+ // return DataResult.FailedWithDesc(nameof(MultiLanguageConst.InvoiceIsSettled));
+
+ if (invoices.Any(x => x.IsSettled))
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.InvoiceIsSettled));
return DataResult.Success;
@@ -1038,8 +1050,7 @@ namespace DS.WMS.Core.Invoice.Method
LockTime = isLocked ? dt : null,
LockUserId = isLocked ? userId : null
}).ToList();
- int rows = await TenantDb.Updateable(list)
- .UpdateColumns(x => new { x.IsLocked, x.LockTime, x.LockUserId }).ExecuteCommandAsync();
+ int rows = await TenantDb.Updateable(list).UpdateColumns(x => new { x.IsLocked, x.LockTime, x.LockUserId }).ExecuteCommandAsync();
return rows > 0 ? DataResult.Success : DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed));
}
diff --git a/ds-wms-service/DS.WMS.Core/Settlement/Method/ApplicationSettlementService.cs b/ds-wms-service/DS.WMS.Core/Settlement/Method/ApplicationSettlementService.cs
index d54cb1c2..ba873c5b 100644
--- a/ds-wms-service/DS.WMS.Core/Settlement/Method/ApplicationSettlementService.cs
+++ b/ds-wms-service/DS.WMS.Core/Settlement/Method/ApplicationSettlementService.cs
@@ -646,17 +646,16 @@ namespace DS.WMS.Core.Settlement.Method
var items = list.SelectMany(x => x.Details);
var ids = items.Select(x => x.DetailId);
//获取申请明细
- var details = TenantDb.Queryable().Where(x => ids.Contains(x.Id))
+ var details = await TenantDb.Queryable().Where(x => ids.Contains(x.Id))
.Select(x => new ApplicationDetail
{
Id = x.Id,
Currency = x.Currency,
- OriginalCurrency = x.OriginalCurrency,
ApplicationId = x.ApplicationId,
ProcessedAmount = x.ProcessedAmount,
OriginalAmount = x.OriginalAmount,
OriginalProcessedAmount = x.OriginalProcessedAmount
- }).ToList();
+ }).ToListAsync();
foreach (var detail in details)
{
diff --git a/ds-wms-service/DS.WMS.FeeApi/Controllers/GeneralInvoiceController.cs b/ds-wms-service/DS.WMS.FeeApi/Controllers/GeneralInvoiceController.cs
index c1c74926..65de506e 100644
--- a/ds-wms-service/DS.WMS.FeeApi/Controllers/GeneralInvoiceController.cs
+++ b/ds-wms-service/DS.WMS.FeeApi/Controllers/GeneralInvoiceController.cs
@@ -137,13 +137,12 @@ namespace DS.WMS.FeeApi.Controllers
/// 发票ID
///
[HttpPost, Route("SetLock")]
- public async Task SetLockAsync([FromBody] IdModel model)
+ public async Task SetLockAsync([FromBody] IdModel model)
{
if (!ModelState.IsValid)
return DataResult.Failed(ModelState.GetErrorMessage(), MultiLanguageConst.IllegalRequest);
- bool isLocked = Convert.ToBoolean(model.Value);
- return await _service.SetLockAsync(isLocked, model.Ids);
+ return await _service.SetLockAsync(model.Value, model.Ids);
}
///
@@ -187,6 +186,18 @@ namespace DS.WMS.FeeApi.Controllers
return await issuanceService.ReverseAsync(request);
}
+ ///
+ /// 发送开票邮件
+ ///
+ ///
+ /// 发票ID
+ ///
+ [HttpPost, Route("SendMail")]
+ public async Task SendMailAsync([FromServices] IInvoiceIssuanceService issuanceService, long id)
+ {
+ return await issuanceService.SendMailAsync(id);
+ }
+
///
/// 添加租户信息
///