mahao 1 year ago
parent
commit
404ea90ecc
  1. 4
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/models/settle/commerce.js
  2. 137
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/models/settle/inventory-detail.js
  3. 12
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/models/settle/inventory.js
  4. 4
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/router/business.js
  5. 2
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/settle/finance.js
  6. 2
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/settle/inventory.js
  7. 197
      code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/BQ/VmiAppService.cs
  8. 106
      code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/BQ/VmiAsyncBalanceService.cs
  9. 116
      code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/BQ/VmiAsyncMessageService.cs

4
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/models/settle/commerce.js

@ -70,12 +70,14 @@ export default function (businessType, type) {
const receivedUrl = `settleaccount/${service}/received`; const receivedUrl = `settleaccount/${service}/received`;
const rejectUrl = `settleaccount/${service}/reject`; const rejectUrl = `settleaccount/${service}/reject`;
const reissueUrl = `settleaccount/${service}/reissue-invoice`; const reissueUrl = `settleaccount/${service}/reissue-invoice`;
const approvalUrl = `settleaccount/${service}/approval-passed`;
const queryMethod = "POST"; const queryMethod = "POST";
const exportMethod = "POST"; const exportMethod = "POST";
const invoiceMethod = "POST"; const invoiceMethod = "POST";
const receivedMethod = "POST"; const receivedMethod = "POST";
const rejectMethod = "POST"; const rejectMethod = "POST";
const reissueMethod = "POST"; const reissueMethod = "POST";
const approvalMethod = "POST";
return { return {
query: { query: {
url: queryUrl, url: queryUrl,
@ -143,11 +145,13 @@ export default function (businessType, type) {
receivedUrl, receivedUrl,
rejectUrl, rejectUrl,
reissueUrl, reissueUrl,
approvalUrl,
exportMethod, exportMethod,
invoiceMethod, invoiceMethod,
receivedMethod, receivedMethod,
rejectMethod, rejectMethod,
reissueMethod, reissueMethod,
approvalMethod,
schema: schema, schema: schema,
}, },
}; };

137
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/models/settle/inventory-detail.js

@ -0,0 +1,137 @@
//库存扣减
import { version, state3 } from "../_options.js";
const schema = {
title: "寄售库库存扣减审批",
type: "object",
properties: {
version,
state: state3,
billNum: {
title: "发票号",
type: "string",
link: true,
},
settleBillNum: {
title: "关联结算单号",
type: "string",
},
invGroupNum: {
title: "发票分组号",
type: "string",
link: true,
},
site: {
title: "地点",
type: "string",
},
},
};
export default function (businessType) {
let service;
if (businessType === "JisBBAC") {
service = "b-bAC_PD_SERVICE";
} else if (businessType === "JisHBPO") {
service = "h-bPO_PD_SERVICE";
} else {
service = "p-uB_PD_SERVICE";
}
const queryUrl = `settleaccount/${service}/detail-query`;
const queryMethod = "POST";
return {
query: {
url: queryUrl,
method: queryMethod,
hasFilter: true,
schema: {
title: "不可结算单",
type: "object",
properties: {
filters: {
title: "项目",
type: "array",
hidden: true,
items: {
type: "object",
properties: {
logic: {
type: "int",
},
column: {
type: "string",
},
action: {
type: "int",
},
value: {
type: "string",
},
},
},
default: [
{
logic: "and",
column: "version",
action: "equal",
value: null,
readOnly: true,
},
{
logic: "and",
column: "billNum",
action: "equal",
value: null,
readOnly: true,
},
{
logic: "and",
column: "settleBillNum",
action: "equal",
value: null,
readOnly: true,
},
{
logic: "and",
column: "invGroupNum",
action: "equal",
value: null,
readOnly: true,
},
{
logic: "and",
column: "state",
action: "equal",
value: null,
readOnly: true,
},
],
},
skipCount: {
hidden: true,
default: 0,
},
maxResultCount: {
hidden: true,
default: 10,
},
sorting: {
hidden: true,
},
businessType: {
hidden: true,
default: 0,
},
},
},
},
table: {
schema: schema,
},
edit: {
schema: schema,
},
};
}

12
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/models/settle/inventory.js

@ -10,7 +10,8 @@ const schema = {
billNum: { billNum: {
title: "发票号", title: "发票号",
type: "string", type: "string",
link: true, oneToMany: "/settle/inventory-detail",
config: "/models/settle/inventory-detail.js",
}, },
settleBillNum: { settleBillNum: {
title: "关联结算单号", title: "关联结算单号",
@ -96,7 +97,7 @@ export default function (businessType) {
}, },
{ {
logic: "and", logic: "and",
column: "invGroupNum", column: "settleBillNum",
action: "equal", action: "equal",
value: null, value: null,
readOnly: true, readOnly: true,
@ -108,6 +109,13 @@ export default function (businessType) {
value: null, value: null,
readOnly: true, readOnly: true,
}, },
{
logic: "and",
column: "state",
action: "equal",
value: null,
readOnly: true,
},
], ],
}, },
skipCount: { skipCount: {

4
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/router/business.js

@ -116,7 +116,7 @@ export default [
children: [createButton("query", "title=查询&isTop=true")], children: [createButton("query", "title=查询&isTop=true")],
}, },
{ {
...createPage("settle/vmi-detail", "title=寄售库库存扣减审批明细&isHidden=true"), ...createPage("settle/inventory-detail", "title=寄售库库存扣减审批明细&isHidden=true"),
children: [createButton("query", "title=查询&isTop=true")], children: [createButton("query", "title=查询&isTop=true")],
}, },
{ {
@ -339,7 +339,7 @@ export default [
children: [ children: [
createButton("query", "title=查询&isTop=true"), createButton("query", "title=查询&isTop=true"),
createButton("import", "title=导入开票文件&isTop=true"), createButton("import", "title=导入开票文件&isTop=true"),
createButton("compare", "title=财务审核通过&isTop=true"), createButton("approval", "title=财务审核通过&isTop=true"),
createButton("export-group", "title=导出发票分组&pattern=paged"), createButton("export-group", "title=导出发票分组&pattern=paged"),
createButton("reject", "title=退回&isTop=true"), createButton("reject", "title=退回&isTop=true"),
createButton("sync", "title=同步到QAD&isTop=true"), createButton("sync", "title=同步到QAD&isTop=true"),

2
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/settle/finance.js

@ -26,7 +26,7 @@ export default {
? `确认退回选中的${rows.length}行数据吗?` ? `确认退回选中的${rows.length}行数据吗?`
: `确认选中的${rows.length}行数据客户已收票吗?`; : `确认选中的${rows.length}行数据客户已收票吗?`;
const data = item.path === "approval" ? rows.map((o) => o.invbillNum) : item.path === "reject" ? rows[0]["invGroupNum"] : rows.map((o) => o.invbillNum); const data = item.path === "approval" ? rows.map((o) => o.invbillNum) : item.path === "reject" ? rows[0]["invGroupNum"] : rows.map((o) => o.invbillNum);
const url = item.path === "approval" ? config.edit.invoiceUrl : item.path === "reject" ? config.edit.rejectUrl : config.edit.receivedUrl; const url = item.path === "approval" ? config.edit.approvalUrl : item.path === "reject" ? config.edit.rejectUrl : config.edit.receivedUrl;
await appListRef.value.onClick(async () => await request(url, data, { method: "POST" }), message, true); await appListRef.value.onClick(async () => await request(url, data, { method: "POST" }), message, true);
} }
} else if (item.path === "export-group") { } else if (item.path === "export-group") {

2
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/settle/inventory.js

@ -27,7 +27,7 @@ export default {
? `确认退回选中的${rows.length}行数据吗?` ? `确认退回选中的${rows.length}行数据吗?`
: `确认选中的${rows.length}行数据客户已收票吗?`; : `确认选中的${rows.length}行数据客户已收票吗?`;
const data = item.path === "approval" ? rows.map((o) => o.invbillNum) : item.path === "reject" ? rows[0]["invGroupNum"] : rows.map((o) => o.invbillNum); const data = item.path === "approval" ? rows.map((o) => o.invbillNum) : item.path === "reject" ? rows[0]["invGroupNum"] : rows.map((o) => o.invbillNum);
const url = item.path === "approval" ? config.edit.invoiceUrl : item.path === "reject" ? config.edit.rejectUrl : config.edit.receivedUrl; const url = item.path === "approval" ? config.edit.approvalUrl : item.path === "reject" ? config.edit.rejectUrl : config.edit.receivedUrl;
await appListRef.value.onClick(async () => await request(url, data, { method: "POST" }), message, true); await appListRef.value.onClick(async () => await request(url, data, { method: "POST" }), message, true);
} }
} else if (item.path === "export-group") { } else if (item.path === "export-group") {

197
code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/BQ/VmiAppService.cs

@ -6,11 +6,9 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Linq.Dynamic.Core; using System.Linq.Dynamic.Core;
using System.Reflection; using System.Reflection;
using System.Text.Json;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using ClosedXML.Excel; using ClosedXML.Excel;
using EFCore.BulkExtensions;
using LinqToDB.Data; using LinqToDB.Data;
using LinqToDB.EntityFrameworkCore; using LinqToDB.EntityFrameworkCore;
using Magicodes.ExporterAndImporter.Core; using Magicodes.ExporterAndImporter.Core;
@ -692,198 +690,3 @@ public class LogRequestDto : RequestDto
{ {
public List<VmiLogType> LogTypes { get; set; } = new List<VmiLogType>(); public List<VmiLogType> LogTypes { get; set; } = new List<VmiLogType>();
} }
/// <summary>
/// 异步更新库存
/// </summary>
public class VmiAsyncBalanceService : ApplicationService, IJobService, ITransientDependency
{
private readonly IServiceProvider _serviceProvider;
public VmiAsyncBalanceService(IServiceProvider serviceProvider)
{
this._serviceProvider = serviceProvider;
}
public async Task Invoke(IServiceProvider serviceProvider)
{
using var scope = _serviceProvider.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<SettleAccountDbContext>();
using var transaction = db.Database.BeginTransaction();
try
{
var messages = db.Set<VmiMessage>().Where(o => !o.isConsumed).OrderBy(o => o.Number).ToList();
var repo = db.Set<VmiBalance>();
foreach (var message in messages)
{
var log = JsonSerializer.Deserialize<VmiLog>(message.Message);
var balance = db.Set<VmiBalance>().FirstOrDefault(
o => o.DeliverBillType == log.DeliverBillType &&
o.CodeType == log.CodeType &&
o.DeliverBillType == log.DeliverBillType &&
o.VinCode == log.VinCode &&
o.ErpToLoc == log.ErpToLoc &&
o.OrderNum == log.OrderNum &&
o.factory == log.factory &&
o.Configcode == log.Configcode);
if (balance == null)
{
balance = new VmiBalance(GuidGenerator.Create());
balance.InjectFrom(log);
await repo.AddAsync(balance).ConfigureAwait(false);
log.InjectFrom(balance);
}
else
{
var logType = log.LogType;
var qty = balance.Qty;// + log.ty
if (logType == VmiLogType.Type100)
{
//发运入库,负库存字段需要更新
if (balance.Qty < decimal.Zero)
{
balance.InjectFrom(log);
}
}
else if (logType == VmiLogType.Type300)
{
//反结入库,只更新库存
}
else if (logType == VmiLogType.Type500)
{
//调整入库,更新库存和其他字段
balance.InjectFrom(log);
}
// 更新库存
balance.Qty = qty;
if (balance.Qty == decimal.Zero)
{
//删除0库存
repo.Remove(balance);
}
if (logType == VmiLogType.Type100 && balance.Qty < decimal.Zero && log.Qty > 0)
{
//更新补货
var log2 = db.Set<VmiLog>().FirstOrDefault(o => o.Id == log.Id);
if (log2 != null)
{
log2.IsReplenished = true;
}
}
}
message.isConsumed = true;
}
transaction.Commit();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
transaction.Rollback();
throw;
}
}
}
/// <summary>
/// 消息表定时清理
/// </summary>
public class VmiAsyncMessageService : ApplicationService, IJobService, ITransientDependency
{
private readonly IServiceProvider _serviceProvider;
public VmiAsyncMessageService(IServiceProvider serviceProvider)
{
this._serviceProvider = serviceProvider;
}
public Task Invoke(IServiceProvider serviceProvider)
{
using var scope = _serviceProvider.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<SettleAccountDbContext>();
db.Set<VmiMessage>().Where(o => o.isConsumed).BatchDelete();
var count = db.Set<VmiMessage>().Where(o => !o.isConsumed).Count();
scope.ServiceProvider.GetService<IHubContext<PageHub>>().Clients.All.ServerToClient("VmiBalance", count.ToString(), "");
return Task.CompletedTask;
}
}
/// <summary>
/// 库存事务定时备份
/// </summary>
public class VmiLogbackupService : ApplicationService, IJobService, ITransientDependency
{
private readonly IServiceProvider _serviceProvider;
public VmiLogbackupService(IServiceProvider serviceProvider)
{
this._serviceProvider = serviceProvider;
}
public Task Invoke(IServiceProvider serviceProvider)
{
using var scope = _serviceProvider.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<SettleAccountDbContext>();
using var transaction = db.Database.BeginTransaction();
try
{
var task = db.Set<VmiSyncTask>().FirstOrDefault(o => o.Number == "Set_VmiLog");
if (task != null)
{
var now = DateTime.Now;
task.LastUpdate = now;
var query = db.Set<VmiLog>().Where(o => o.UpdatedTime >= task.LastUpdate && o.UpdatedTime < now);
foreach (var item in query)
{
//同步到questdb
}
}
}
catch
{
transaction.Rollback();
throw;
}
return Task.CompletedTask;
}
}
/// <summary>
/// 库存余额定时备份
/// </summary>
public class VmiLogBalanceService : ApplicationService, IJobService, ITransientDependency
{
private readonly IServiceProvider _serviceProvider;
public VmiLogBalanceService(IServiceProvider serviceProvider)
{
this._serviceProvider = serviceProvider;
}
public Task Invoke(IServiceProvider serviceProvider)
{
using var scope = _serviceProvider.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<SettleAccountDbContext>();
using var transaction = db.Database.BeginTransaction();
try
{
var task = db.Set<VmiSyncTask>().FirstOrDefault(o => o.Number == "Set_VmiBalance");
if (task != null)
{
var now = DateTime.Now;
task.LastUpdate = now;
var query = db.Set<VmiBalance>().Where(o => o.UpdatedTime >= task.LastUpdate && o.UpdatedTime < now);
foreach (var item in query)
{
//同步到questdb
}
}
}
catch
{
transaction.Rollback();
throw;
}
return Task.CompletedTask;
}
}

106
code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/BQ/VmiAsyncBalanceService.cs

@ -0,0 +1,106 @@
using System;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Text.Json;
using System.Threading.Tasks;
using Magicodes.ExporterAndImporter.Core.Extension;
using Microsoft.Extensions.DependencyInjection;
using Omu.ValueInjecter;
using Volo.Abp.Application.Services;
using Volo.Abp.DependencyInjection;
using Win.Sfs.SettleAccount.Entities.BQ.Vmi;
using Win.Sfs.Shared.RepositoryBase;
namespace Win.Sfs.SettleAccount.Entities.BQ;
/// <summary>
/// 异步更新库存
/// </summary>
public class VmiAsyncBalanceService : ApplicationService, IJobService, ITransientDependency
{
private readonly IServiceProvider _serviceProvider;
public VmiAsyncBalanceService(IServiceProvider serviceProvider)
{
this._serviceProvider = serviceProvider;
}
public async Task Invoke(IServiceProvider serviceProvider)
{
using var scope = _serviceProvider.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<SettleAccountDbContext>();
using var transaction = db.Database.BeginTransaction();
try
{
var messages = db.Set<VmiMessage>().Where(o => !o.isConsumed).OrderBy(o => o.Number).ToList();
var repo = db.Set<VmiBalance>();
foreach (var message in messages)
{
var log = JsonSerializer.Deserialize<VmiLog>(message.Message);
var balance = db.Set<VmiBalance>().FirstOrDefault(
o => o.DeliverBillType == log.DeliverBillType &&
o.CodeType == log.CodeType &&
o.DeliverBillType == log.DeliverBillType &&
o.VinCode == log.VinCode &&
o.ErpToLoc == log.ErpToLoc &&
o.OrderNum == log.OrderNum &&
o.factory == log.factory &&
o.Configcode == log.Configcode);
if (balance == null)
{
balance = new VmiBalance(GuidGenerator.Create());
balance.InjectFrom(log);
await repo.AddAsync(balance).ConfigureAwait(false);
log.InjectFrom(balance);
}
else
{
var logType = log.LogType;
var qty = balance.Qty;// + log.ty
if (logType == VmiLogType.Type100)
{
//发运入库,负库存字段需要更新
if (balance.Qty < decimal.Zero)
{
balance.InjectFrom(log);
}
}
else if (logType == VmiLogType.Type300)
{
//反结入库,只更新库存
}
else if (logType == VmiLogType.Type500)
{
//调整入库,更新库存和其他字段
balance.InjectFrom(log);
}
// 更新库存
balance.Qty = qty;
if (balance.Qty == decimal.Zero)
{
//删除0库存
repo.Remove(balance);
}
if (logType == VmiLogType.Type100 && balance.Qty < decimal.Zero && log.Qty > 0)
{
//更新补货
var log2 = db.Set<VmiLog>().FirstOrDefault(o => o.Id == log.Id);
if (log2 != null)
{
log2.IsReplenished = true;
}
}
}
message.isConsumed = true;
}
transaction.Commit();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
transaction.Rollback();
throw;
}
}
}

116
code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/BQ/VmiAsyncMessageService.cs

@ -0,0 +1,116 @@
using System;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;
using EFCore.BulkExtensions;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.DependencyInjection;
using SettleAccount.Job.SignalR;
using Volo.Abp.Application.Services;
using Volo.Abp.DependencyInjection;
using Win.Sfs.SettleAccount.Entities.BQ.Vmi;
namespace Win.Sfs.SettleAccount.Entities.BQ;
/// <summary>
/// 消息表定时清理
/// </summary>
public class VmiAsyncMessageService : ApplicationService, IJobService, ITransientDependency
{
private readonly IServiceProvider _serviceProvider;
public VmiAsyncMessageService(IServiceProvider serviceProvider)
{
this._serviceProvider = serviceProvider;
}
public Task Invoke(IServiceProvider serviceProvider)
{
using var scope = _serviceProvider.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<SettleAccountDbContext>();
db.Set<VmiMessage>().Where(o => o.isConsumed).BatchDelete();
var count = db.Set<VmiMessage>().Where(o => !o.isConsumed).Count();
scope.ServiceProvider.GetService<IHubContext<PageHub>>().Clients.All.ServerToClient("VmiBalance", count.ToString(), "");
return Task.CompletedTask;
}
}
/// <summary>
/// 库存事务定时备份
/// </summary>
public class VmiLogbackupService : ApplicationService, IJobService, ITransientDependency
{
private readonly IServiceProvider _serviceProvider;
public VmiLogbackupService(IServiceProvider serviceProvider)
{
this._serviceProvider = serviceProvider;
}
public Task Invoke(IServiceProvider serviceProvider)
{
using var scope = _serviceProvider.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<SettleAccountDbContext>();
using var transaction = db.Database.BeginTransaction();
try
{
var task = db.Set<VmiSyncTask>().FirstOrDefault(o => o.Number == "Set_VmiLog");
if (task != null)
{
var now = DateTime.Now;
task.LastUpdate = now;
var query = db.Set<VmiLog>().Where(o => o.UpdatedTime >= task.LastUpdate && o.UpdatedTime < now);
foreach (var item in query)
{
//同步到questdb
}
}
}
catch
{
transaction.Rollback();
throw;
}
return Task.CompletedTask;
}
}
/// <summary>
/// 库存余额定时备份
/// </summary>
public class VmiLogBalanceService : ApplicationService, IJobService, ITransientDependency
{
private readonly IServiceProvider _serviceProvider;
public VmiLogBalanceService(IServiceProvider serviceProvider)
{
this._serviceProvider = serviceProvider;
}
public Task Invoke(IServiceProvider serviceProvider)
{
using var scope = _serviceProvider.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<SettleAccountDbContext>();
using var transaction = db.Database.BeginTransaction();
try
{
var task = db.Set<VmiSyncTask>().FirstOrDefault(o => o.Number == "Set_VmiBalance");
if (task != null)
{
var now = DateTime.Now;
task.LastUpdate = now;
var query = db.Set<VmiBalance>().Where(o => o.UpdatedTime >= task.LastUpdate && o.UpdatedTime < now);
foreach (var item in query)
{
//同步到questdb
}
}
}
catch
{
transaction.Rollback();
throw;
}
return Task.CompletedTask;
}
}
Loading…
Cancel
Save