zhouhongjun 6 months ago
parent
commit
4ae5673ee1
  1. 39
      code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/BQ/INVOICE_SERVICE.cs
  2. 75
      code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/BQ/JobHostdService.cs
  3. 1
      code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/BQ/Syncs/SeSyncExtendManager.cs
  4. 14
      code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/BQ/VmiAppService.cs
  5. 2
      code/src/Modules/SettleAccount/src/SettleAccount.EntityFrameworkCore/EntityFrameworkCore/SettleAccountDbContext.cs

39
code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/BQ/INVOICE_SERVICE.cs

@ -222,6 +222,7 @@ namespace Win.Sfs.SettleAccount.Entities.BQ
inv.Amt = Math.Round(itm.Qty * first.PRICE, 2);
inv.Extend1 = itm.ContractDocID;
inv.BussiessType = EnumBusinessType.MaiDanJianBBAC;
if (invoiceGrp.Site == "1046")
{
inv.Extend2 = "CC16";
@ -252,6 +253,7 @@ namespace Win.Sfs.SettleAccount.Entities.BQ
InvoiceNetAmount = invoiceGrpDetail.Amt,
InvoiceTaxAmount = Math.Round(invoiceGrpDetail.Amt * 0.13m, 2),
TaxRate = 0.13m,
Remark = string.IsNullOrEmpty(invoiceGrp.FileName) ? string.Empty : invoiceGrp.FileName,
Location = invoiceGrpDetail.Extend2,
begintime = invoiceGrpDetail.BeginDate,
endtime = invoiceGrpDetail.EndDate,
@ -268,19 +270,7 @@ namespace Win.Sfs.SettleAccount.Entities.BQ
var invdiff = invbefore - invafter;
//invoiceGrp.RealAmt + invoiceGrp.TaxDiff-invafter;
tedsaInvs1.FirstOrDefault().InvoiceTaxAmount += invdiff;
//var a = tedsaInvs1.Sum(p => p.InvoiceNetAmount);
//var b= tedsaInvs1.Sum(p => p.InvoiceTaxAmount);
//var invafter = a + b;
//var invdiff = invbefore - invafter;
//var line1 = tedsaInvs1.FirstOrDefault(p => p.LINE == "1");
//var line2 = tedsaInvs1.FirstOrDefault(p => p.LINE == "2");
//line2.InvoiceTaxAmount += invdiff;
//line1.InvoiceTaxAmount += invoiceGrp.TaxDiff;
//红冲发票提交QAD
if (!string.IsNullOrEmpty(invoiceGrp.ParentInvbillNum))
{
@ -292,17 +282,7 @@ namespace Win.Sfs.SettleAccount.Entities.BQ
await _repository.DbContext.BulkUpdateAsync(new List<INVOICE_GRP>() { invoiceGrp });
await BindInvoiceSyncQadAsync(teaTaskSub, invoiceGrp.RealnvBillNum, invoiceGrp.InvbillNum, invoiceGrp.ClientCode, invoiceGrp.CreationTime).ConfigureAwait(false);
//await _exChangeCenterDbContext.SaveChangesAsync().ConfigureAwait(false);
// var retryPolicyAsync = Policy.Handle<Exception>().WaitAndRetryAsync(new[] {
// TimeSpan.FromSeconds(1),
// TimeSpan.FromSeconds(5),
// TimeSpan.FromSeconds(5),
// TimeSpan.FromSeconds(5)
//}, (exception, timeSpan, retryCount, context) =>
//{
// _logger.LogError($"提交到QAD,修改发票状态执行失败,第 {retryCount} 次重试");
//});
// await retryPolicyAsync.ExecuteAsync(async () => await _settleAccountDbContext.SaveChangesAsync().ConfigureAwait(false)).ConfigureAwait(false);
}
}
else
@ -311,6 +291,16 @@ namespace Win.Sfs.SettleAccount.Entities.BQ
var invoiceGrpDetails = _settleAccountDbContext.Set<INVOICE_WAIT_DETAIL>()
.Where(t => t.InvbillNum == invbillNum)
.ToList();
if (invoiceGrpDetails.Any())
{
var tedSaInvs = new List<TED_SAS_INVOICE>();
@ -387,8 +377,10 @@ namespace Win.Sfs.SettleAccount.Entities.BQ
var invafter = tedSaInvs.Sum(p => p.InvoiceTaxAmount);
var invdiff = invbefore - invafter;
tedSaInvs.FirstOrDefault().InvoiceTaxAmount += invdiff;
//tedSaInvs.FirstOrDefault().InvoiceTaxAmount += invoiceGrp.TaxDiff;
//红冲发票提交QAD
if (!string.IsNullOrEmpty(invoiceGrp.ParentInvbillNum))
@ -499,6 +491,7 @@ namespace Win.Sfs.SettleAccount.Entities.BQ
Location = invoiceGrpDetail.GetProperty("ErpToLoc", string.Empty),
begintime = invoiceGrpDetail.BeginDate,
endtime = invoiceGrpDetail.EndDate,
Remark = string.IsNullOrEmpty(invoiceGrp.FileName) ? string.Empty : invoiceGrp.FileName,
domain = "BJBMPT",
LINE = (i + 1).ToString()
});

75
code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/BQ/JobHostdService.cs

@ -68,13 +68,19 @@ namespace Win.Sfs.SettleAccount.Entities.BQ
}
public static List<Type> ServiceTypes { get; private set; }
// Jobs字段使用ConcurrentDictionary来存储JobItem、Tuple<CancellationTokenSource, Thread>类型的数据
public ConcurrentDictionary<JobItem, Tuple<CancellationTokenSource, Thread>> Jobs { get; } = new();
// 用于添加服务到IServiceCollection中
public static void AddService(IServiceCollection services)
{
// 获取所有实现了IJobService接口的类,并将其添加到ServiceTypes列表中
ServiceTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(o => o.GetTypes())
.Where(o => o.IsClass && !o.IsAbstract && o.IsAssignableTo(typeof(IJobService)))
.ToList();
// 遍历ServiceTypes列表中的类型,并分别向services中注册IJobService接口和实现类
ServiceTypes.ForEach(o =>
{
services.AddTransient(typeof(IJobService), o);
@ -82,28 +88,37 @@ namespace Win.Sfs.SettleAccount.Entities.BQ
});
}
public void AddJob(JobItem job)
{
// 使用锁确保线程安全
lock (_lockObj)
{
// 检查是否存在相同Id的作业
if (!Jobs.Keys.Any(o => o.Id == job.Id))
{
// 尝试创建新作业的线程
try
{
// 创建取消标记和线程
var source = new CancellationTokenSource();
var token = source.Token;
var thread = new Thread(async () =>
{
try
{
// 解析Cron表达式
var expression = CronExpression.Parse(job.Cron, job.Cron.Split(' ').Length == 5 ? CronFormat.Standard : CronFormat.IncludeSeconds);
// 获取作业服务类型
var serviceType = ServiceTypes.FirstOrDefault(o => o.FullName == job.Service);
if (serviceType != null)
{
// 循环执行作业直到取消标记被设置
while (!_stoppingToken.IsCancellationRequested && !token.IsCancellationRequested)
{
try
{
// 计算下一次执行时间间隔
var now = DateTime.UtcNow;
var nextUtc = expression.GetNextOccurrence(now);
var span = nextUtc - now;
@ -117,6 +132,7 @@ namespace Win.Sfs.SettleAccount.Entities.BQ
await Task.Delay(currentDelay).ConfigureAwait(false);
}
Debug.WriteLine($"{job.Name} 定时任务开始执行");
// 创建作用域并获取作业服务实例
using var scope = this._serviceProvider.CreateScope();
if (scope.ServiceProvider.GetService(serviceType) is IJobService jobService)
{
@ -124,6 +140,7 @@ namespace Win.Sfs.SettleAccount.Entities.BQ
{
var jobItem = this.GetJobItem(job.Id);
Guid? jobLogId = null;
// 如果作业正在运行并且心跳超过20秒,则停止作业
if (jobItem.IsRunning && (DateTime.Now - jobItem.HeartBeat.Value).TotalSeconds > 20)
{
JobItemStop(jobItem.Id);
@ -131,13 +148,16 @@ namespace Win.Sfs.SettleAccount.Entities.BQ
if (!jobItem.IsRunning)
{
jobLogId = this.JobItemStart(job.Id);
// 创建定时器以发送心跳
using var timer = new System.Timers.Timer(10000);
if (jobLogId.HasValue)
{
try
{
// 执行作业服务方法
timer.Elapsed += (s, e) => JobItemHeartBeat(job.Id);
timer.Start();
// 通知客户端作业状态变化
scope.ServiceProvider.GetRequiredService<IHubContext<PageHub>>().Clients.All.ServerToClient("JobItem", "refresh", "");
await jobService.Invoke(scope.ServiceProvider).ConfigureAwait(false);
this.JobItemSuccess(job.Id, jobLogId.Value);
@ -152,6 +172,7 @@ namespace Win.Sfs.SettleAccount.Entities.BQ
finally
{
timer.Stop();
// 通知客户端作业状态变化
scope.ServiceProvider.GetRequiredService<IHubContext<PageHub>>().Clients.All.ServerToClient("JobItem", "refresh", "");
}
}
@ -179,6 +200,7 @@ namespace Win.Sfs.SettleAccount.Entities.BQ
{
IsBackground = true
};
// 尝试将作业添加到字典中并启动线程
if (this.Jobs.TryAdd(job, new Tuple<CancellationTokenSource, Thread>(source, thread)))
{
thread.Start();
@ -193,17 +215,26 @@ namespace Win.Sfs.SettleAccount.Entities.BQ
}
}
private void JobItemFaild(Guid id, Guid jobLogId, Exception ex)
{
// 获取连接字符串
var connectionString = this._serviceProvider.GetRequiredService<IConfiguration>().GetConnectionString("SettleAccountService");
// 使用连接字符串创建数据库连接
using var connection = new SqlConnection(connectionString);
// 配置数据库上下文选项
var options = new DbContextOptionsBuilder<SettleAccountDbContext>().UseSqlServer(connection).Options;
// 使用数据库上下文实例化数据库上下文
using var db = new SettleAccountDbContext(options);
// 获取指定 id 对应的 JobItem 实体
var entity = db.Set<JobItem>().FirstOrDefault(o => o.Id == id);
if (entity != null)
{
// 更新实体的 IsRunning 属性,并保存到数据库
entity.IsRunning = false;
// 获取指定 jobLogId 对应的 JobLog 实体
var log = db.Set<JobLog>().FirstOrDefault(o => o.Id == jobLogId);
// 更新 JobLog 实体的 End、Success 和 Exception 属性,并保存到数据库
log.End = DateTime.Now;
log.Success = false;
log.Exception = ex.ToString();
@ -211,61 +242,103 @@ namespace Win.Sfs.SettleAccount.Entities.BQ
}
}
// 在指定的作业项成功时更新数据库
private void JobItemSuccess(Guid id, Guid jobLogId)
{
var connectionString = this._serviceProvider.GetRequiredService<IConfiguration>().GetConnectionString("SettleAccountService");
using var connection = new SqlConnection(connectionString);
var options = new DbContextOptionsBuilder<SettleAccountDbContext>().UseSqlServer(connection).Options;
using var db = new SettleAccountDbContext(options);
// 通过id查找作业项实体
var entity = db.Set<JobItem>().FirstOrDefault(o => o.Id == id);
if (entity != null)
{
// 设置作业项为非运行状态
entity.IsRunning = false;
// 通过jobLogId查找作业日志实体
var log = db.Set<JobLog>().FirstOrDefault(o => o.Id == jobLogId);
if (log != null)
{
// 更新作业日志的结束时间和成功状态
log.End = DateTime.Now;
log.Success = true;
}
// 保存更改到数据库
db.SaveChanges();
}
}
// 停止作业项的方法
private void JobItemStop(Guid id)
{
// 获取数据库连接字符串
var connectionString = this._serviceProvider.GetRequiredService<IConfiguration>().GetConnectionString("SettleAccountService");
// 使用数据库连接
using var connection = new SqlConnection(connectionString);
// 配置数据库上下文选项
var options = new DbContextOptionsBuilder<SettleAccountDbContext>().UseSqlServer(connection).Options;
// 使用结算账户数据库上下文
using var db = new SettleAccountDbContext(options);
// 从数据库中获取指定id的作业项实体
var entity = db.Set<JobItem>().FirstOrDefault(o => o.Id == id);
if (entity != null)
{
// 将作业项的运行状态设置为false
entity.IsRunning = false;
// 获取指定作业id且结束时间为空的作业日志,按开始时间降序排序
var log = db.Set<JobLog>().Where(o => o.JobId == id && o.End == null).OrderByDescending(o => o.Start).FirstOrDefault();
// 设置作业日志的执行状态为失败,并记录异常描述
log.Success = false;
log.Exception = "心跳超时,自动停止";
// 保存数据库更改
db.SaveChanges();
}
}
// 通过作业项的ID启动作业项
private Guid? JobItemStart(Guid id)
{
// 获取数据库连接字符串
var connectionString = this._serviceProvider.GetRequiredService<IConfiguration>().GetConnectionString("SettleAccountService");
// 使用连接字符串创建SqlConnection对象
using var connection = new SqlConnection(connectionString);
// 使用连接字符串创建SettleAccountDbContext的DbContextOptions
var options = new DbContextOptionsBuilder<SettleAccountDbContext>().UseSqlServer(connection).Options;
// 使用DbContextOptions创建SettleAccountDbContext
using var db = new SettleAccountDbContext(options);
// 从数据库中查询指定ID的作业项实体
var entity = db.Set<JobItem>().FirstOrDefault(o => o.Id == id);
// 如果作业项实体存在
if (entity != null)
{
// 设置作业项为运行状态,并更新心跳时间为当前时间
entity.IsRunning = true;
entity.HeartBeat = DateTime.Now;
// 添加作业日志
var log = db.Set<JobLog>().Add(new JobLog { Start = DateTime.Now, JobId = entity.Id, Host = Dns.GetHostName() });
// 保存作业日志到数据库
db.SaveChanges();
// 返回新增作业日志的ID
return log.Entity.Id;
}
// 作业项不存在时返回空
return null;
}
// 从数据库中获取指定id的JobItem对象
private JobItem GetJobItem(Guid id)
{
var connectionString = this._serviceProvider.GetRequiredService<IConfiguration>().GetConnectionString("SettleAccountService");
@ -276,6 +349,7 @@ namespace Win.Sfs.SettleAccount.Entities.BQ
return repo.FirstOrDefault(o => o.Id == id);
}
// 更新指定id的JobItem对象的心跳时间为当前时间
private void JobItemHeartBeat(Guid id)
{
var connectionString = this._serviceProvider.GetRequiredService<IConfiguration>().GetConnectionString("SettleAccountService");
@ -290,6 +364,7 @@ namespace Win.Sfs.SettleAccount.Entities.BQ
}
}
public void RemoveJob(JobItem item)
{
lock (_lockObj)

1
code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/BQ/Syncs/SeSyncExtendManager.cs

@ -182,7 +182,6 @@ namespace Win.Sfs.SettleAccount.Entities.BQ.Syncs
SettlementPartCode = (!string.IsNullOrEmpty(t.PN) ? t.PN : string.Empty) + (!string.IsNullOrEmpty(t.CustomerPartCodeNoSpace) ? t.CustomerPartCodeNoSpace : string.Empty)
,
}).ToList();
var returnVmiLogList = returnSeDetails.Select(t => new VmiLog
{

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

@ -239,12 +239,17 @@ namespace Win.Sfs.SettleAccount.Entities.BQ
[HttpPost]
public async Task<PagedResultDto<VmiBalanceSumDetailDto>> Balance(RequestDto input)
{
if (input != null && !string.IsNullOrEmpty(input.Sorting))
{
input.Sorting= input.Sorting.ToUpper().Replace("BillTime".ToUpper(), "ReceiveTime".ToUpper())
.Replace("Qty".ToUpper(), "SumQty".ToUpper());
}
var first = input.Filters.FirstOrDefault(p => p.Column == "BillTime");
if (first != null)
{
input.Filters.Remove(first);
}
var entities = await _vmiBalanceSumDetailRepository.GetListByFilterAsync(input.Filters, input.Sorting, input.MaxResultCount, input.SkipCount, true).ConfigureAwait(false);
var totalCount = await _vmiBalanceSumDetailRepository.GetCountByFilterAsync(input.Filters).ConfigureAwait(false);
var dtos = _maper.Map<List<VmiBalanceSumDetail>, List<VmiBalanceSumDetailDto>>(entities);
@ -252,6 +257,13 @@ namespace Win.Sfs.SettleAccount.Entities.BQ
return new PagedResultDto<VmiBalanceSumDetailDto>(totalCount, dtos);
}
/// <summary>
/// 1.1库存余额导出
/// </summary>

2
code/src/Modules/SettleAccount/src/SettleAccount.EntityFrameworkCore/EntityFrameworkCore/SettleAccountDbContext.cs

@ -14,7 +14,7 @@ namespace Win.Sfs.SettleAccount
public SettleAccountDbContext(DbContextOptions<SettleAccountDbContext> options)
: base(options)
{
this.Database.SetCommandTimeout(System.TimeSpan.FromMinutes(30));
this.Database.SetCommandTimeout(System.TimeSpan.FromMinutes(120));
}
protected override void OnModelCreating(ModelBuilder builder)

Loading…
Cancel
Save