From bb6dbabc8cb9f1ffa5bfa2b936c91463cda84000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B4=BE=E8=8D=A3=E5=9B=BD?= Date: Wed, 6 Jul 2022 17:25:11 +0800 Subject: [PATCH] =?UTF-8?q?[fix]=E6=97=A0PO=20ASN=E6=8F=90=E4=BE=9B?= =?UTF-8?q?=E4=B8=93=E7=94=A8=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AsnBackgroundWorker.cs | 149 +++++++- .../Asns/AsnDetDTO.cs | 113 ++++++ .../Asns/AsnMstrDTO.cs | 98 ++++++ .../Asns/IAsnAppService.cs | 26 ++ .../Asns/IX12AsnAppService.cs | 1 + .../RouteConsts.cs | 1 + .../Asns/AsnAppService.cs | 325 ++++++++++++++++++ .../Asns/X12AsnAppService.cs | 29 ++ .../Win_in.Sfs.Scp.WebApi.Application.csproj | 4 + .../NoPoASN/AsnDet.cs | 118 +++++++ .../NoPoASN/AsnMstr.cs | 96 ++++++ .../ScpWebApiConsts.cs | 8 + ...Backup.Sfs.Scp.WebApi.Domain.Shared.csproj | 35 ++ .../Asns/IAsnRepository.cs | 16 + .../Asns/IX12AsnRepository.cs | 2 + .../Asns/X12Asn.cs | 4 +- .../DbContext/IWebApiDbContext.cs | 2 + .../DbContext/WebApiDbContext.cs | 1 + .../WebApiDbContextModelCreatingExtensions.cs | 66 ++++ .../Repositories/AsnRepository.cs | 69 ++++ .../Repositories/X12AsnRepository.cs | 24 +- 21 files changed, 1168 insertions(+), 19 deletions(-) create mode 100644 WebApiService/src/Win_in.Sfs.Scp.WebApi.Application.Contracts/Asns/AsnDetDTO.cs create mode 100644 WebApiService/src/Win_in.Sfs.Scp.WebApi.Application.Contracts/Asns/AsnMstrDTO.cs create mode 100644 WebApiService/src/Win_in.Sfs.Scp.WebApi.Application.Contracts/Asns/IAsnAppService.cs create mode 100644 WebApiService/src/Win_in.Sfs.Scp.WebApi.Application/Asns/AsnAppService.cs create mode 100644 WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain.Shared/NoPoASN/AsnDet.cs create mode 100644 WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain.Shared/NoPoASN/AsnMstr.cs create mode 100644 WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain.Shared/ScpWebApiConsts.cs create mode 100644 WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain.Shared/Win_in - Backup.Sfs.Scp.WebApi.Domain.Shared.csproj create mode 100644 WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain/Asns/IAsnRepository.cs create mode 100644 WebApiService/src/Win_in.Sfs.Scp.WebApi.EntityFrameworkCore/Repositories/AsnRepository.cs diff --git a/WebApiService/src/Win_in.Sfs.Scp.WebApi.Agent/AsnBackgroundWorker/AsnBackgroundWorker.cs b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Agent/AsnBackgroundWorker/AsnBackgroundWorker.cs index a87223e..88bcac9 100644 --- a/WebApiService/src/Win_in.Sfs.Scp.WebApi.Agent/AsnBackgroundWorker/AsnBackgroundWorker.cs +++ b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Agent/AsnBackgroundWorker/AsnBackgroundWorker.cs @@ -1,8 +1,10 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.Serialization; using System.Text.Json; using System.Threading.Tasks; +using AutoMapper; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -13,26 +15,33 @@ using Volo.Abp.Data; using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Repositories; using Volo.Abp.MultiTenancy; +using Volo.Abp.ObjectMapping; using Volo.Abp.TenantManagement; using Volo.Abp.Threading; using Volo.Abp.Uow; using Win_in.Sfs.Scp.v1.Domain; using Win_in.Sfs.Scp.v1.Domain.Asns; +using Win_in.Sfs.Scp.WebApi.Agent; using Win_in.Sfs.Scp.WebApi.Asns; +using Win_in.Sfs.Scp.WebApi.EntityFrameworkCore; +using IObjectMapper = Volo.Abp.ObjectMapping.IObjectMapper; namespace Win_in.Sfs.Scp.WebApi { public class AsnBackgroundWorker : AsyncPeriodicBackgroundWorkerBase { private readonly IOptions _options; + private readonly IObjectMapper _objectMapper; public AsnBackgroundWorker( AbpAsyncTimer timer, IOptions options, - IServiceScopeFactory serviceScopeFactory + IServiceScopeFactory serviceScopeFactory, + IObjectMapper objectMapper ) : base(timer, serviceScopeFactory) { _options = options; + _objectMapper = objectMapper; Timer.Period = options.Value.PeriodSeconds * 1000; //default 5 minutes } @@ -49,15 +58,16 @@ namespace Win_in.Sfs.Scp.WebApi //Resolve dependencies var scpAsnManager = workerContext.ServiceProvider.GetRequiredService(); var x12AsnRepository = workerContext.ServiceProvider.GetRequiredService(); + // var noPoAsnRepository = workerContext.ServiceProvider.GetRequiredService(); var tenantStore = workerContext.ServiceProvider.GetRequiredService(); var currentTenant = workerContext.ServiceProvider.GetRequiredService(); var dataFilter = workerContext.ServiceProvider.GetRequiredService(); - //Do the work - var asnX12List = new List(); foreach (var site in _options.Value.Sites) { + var asnX12List = new List(); + // var noPoAsnList = new List(); var siteCode = site.Code; var siteMinUid = site.MinUid; try @@ -90,14 +100,17 @@ namespace Win_in.Sfs.Scp.WebApi foreach (var asn in scpAsns) { var barcodes = await scpAsnManager.GetBarcodesAsync(siteCode, asn.AsnBillNum); - var asnFactory = new AsnFactory(); - var asnX128563060 = - asnFactory.CreateAsnX128563060(site.Receiver, asn, barcodes); - var jsonString = JsonSerializer.Serialize(asnX128563060); - var ediString = asnX128563060.ToString(); - var asnX12 = new X12Asn(asn.Id, asn.Site, asn.AsnBillNum, jsonString, ediString, - asn.ShipTime ?? DateTime.Today); - asnX12List.Add(asnX12); + + if (string.IsNullOrEmpty(asn.PoBillNum)) //without PO + { + var noPoAsn = CreateNoPoAsn(asn, barcodes); + asnX12List.Add(noPoAsn); + } + else //with PO + { + var asnX12 = CreateX12Asn(site, asn, barcodes); + asnX12List.Add(asnX12); + } Logger.LogInformation($"{siteCode}:{asn.Id} {asn.AsnBillNum} was loaded"); } } @@ -108,9 +121,117 @@ namespace Win_in.Sfs.Scp.WebApi Logger.LogException(ex); } + await AddX12AsnsAsync(asnX12List, x12AsnRepository); + // await AddNoPoAsnsAsync(noPoAsnList,noPoAsnRepository); + } + + + Logger.LogInformation("Get ASN from SCP: Complete"); + } + + private X12Asn CreateNoPoAsn(TB_ASN asn, List barcodes) + { + var asnMstr = new AsnMstr() + { + UID = asn.Id, + Company = asn.Site, + Site = asn.Site, + AsnNbr = asn.AskBillNum, + RpNbr = asn.AskBillNum, + PoNbr = asn.PoBillNum, + VendorCode = asn.VendId, + Contacts = asn.ReceiveUser, + Phone = "", + TruckNbr = asn.PlateNumber, + Whse = "", + Dock = "", + ShipDate = asn.ShipTime, + DueDate = asn.ReceiveTime, + TimeWindow = asn.ReceivedPort, + Remark = asn.Remark, + }; + + foreach (var barcode in barcodes) + { + var det = new AsnDet() + { + AsnNbr = asn.AsnBillNum, + PoNbr = asn.PoBillNum, + PoLine = barcode.PoBillLine, + PartCode = barcode.PartCode, + Lot = barcode.Batch, + Qty = barcode.Qty, + ProductionDate = barcode.ProduceDate, + WareClass = "", + WareCode = "", + StdPackQty = barcode.PackQty, + PoUm = barcode.PoUnit, + LocUm = barcode.LocUnit, + UmConv = 1, + PartType = "", + Supplierlot = barcode.VendBatch, + Status = barcode.State.ToString(), + LabelCode = barcode.Extend2, + EntireBarCode = barcode.FullBarCode, + PalletLabelCode = barcode.PalletCode, + Remark = barcode.Remark, + }; + asnMstr.Details.Add(det); } + var jsonString = JsonSerializer.Serialize(asnMstr); + var ediString = asnMstr.ToString(); + var asnX12 = new X12Asn(asn.Id, asn.Site, asn.AsnBillNum, ScpWebApiConsts.NO_PO_ASN, jsonString, ediString, + asn.ShipTime ?? DateTime.Today); + return asnX12; + } + private static X12Asn CreateX12Asn(AsnOptions.Site site, TB_ASN asn, List barcodes) + { + var asnFactory = new AsnFactory(); + var asnX128563060 = + asnFactory.CreateAsnX128563060(site.Receiver, asn, barcodes); + var jsonString = JsonSerializer.Serialize(asnX128563060); + var ediString = asnX128563060.ToString(); + var asnX12 = new X12Asn(asn.Id, asn.Site, asn.AsnBillNum, ScpWebApiConsts.ASN, jsonString, ediString, + asn.ShipTime ?? DateTime.Today); + return asnX12; + } + + /* + private async Task AddNoPoAsnsAsync(List noPoAsnList, IAsnRepository noPoAsnRepository) + { + foreach (var asn in noPoAsnList) + { + var exist = await noPoAsnRepository.FirstOrDefaultAsync( + p => p.UID == asn.UID && p.Site == asn.Site); + if (exist == null) + { + await noPoAsnRepository.InsertAsync(asn); + } + else + { + exist.RpNbr = asn.RpNbr; + exist.Contacts = asn.Contacts; + exist.Phone = asn.Phone; + exist.TruckNbr = asn.TruckNbr; + exist.Whse = asn.Whse; + exist.Dock = asn.Dock; + exist.ShipDate = asn.ShipDate; + exist.DueDate = asn.DueDate; + exist.TimeWindow = asn.TimeWindow; + exist.Remark = asn.Remark; + exist.Details = asn.Details; + exist.SetEffectiveDate(asn.EffectiveDate); + exist.Reset(); + await noPoAsnRepository.UpdateAsync(exist); + } + } + } + */ + + private static async Task AddX12AsnsAsync(List asnX12List, IX12AsnRepository x12AsnRepository) + { foreach (var x12Asn in asnX12List) { var exist = await x12AsnRepository.FirstOrDefaultAsync( @@ -122,15 +243,11 @@ namespace Win_in.Sfs.Scp.WebApi else { exist.JsonString = x12Asn.JsonString; + exist.EdiString = x12Asn.EdiString; exist.Reset(); await x12AsnRepository.UpdateAsync(exist); } } - - await x12AsnRepository.InsertManyAsync(asnX12List, true); - - Logger.LogInformation("Get ASN from SCP: Complete"); } - } } \ No newline at end of file diff --git a/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application.Contracts/Asns/AsnDetDTO.cs b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application.Contracts/Asns/AsnDetDTO.cs new file mode 100644 index 0000000..ca2ff8f --- /dev/null +++ b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application.Contracts/Asns/AsnDetDTO.cs @@ -0,0 +1,113 @@ +using System; +using System.ComponentModel.DataAnnotations; +using Win_in.Sfs.Scp.WebApi.Domain.Shared; + +namespace Win_in.Sfs.Scp.WebApi +{ + /// + /// QAD发货单明细(ASN detail) SupplierAsnDetailInput + /// + public class AsnDetDTO :EntityDtoBase + { + /// + /// 送货单号(ASN number)(Asn number) + /// + public virtual string AsnNbr { get; set; } + + /// + /// 采购订单号(Purchase order number) + /// + public virtual string PoNbr { get; set; } + + /// + /// 采购订单行(Purchase order line) + /// + public virtual int PoLine { get; set; } + + /// + /// 物料号(Part number)(Part number) + /// + public virtual string PartCode { get; set; } + + /// + /// 批次(Lot number) + /// + public virtual string Lot { get; set; } + + /// + /// 送货总量(Quantity) + /// + public virtual decimal Qty { get; set; } + + /// + /// 生产日期(Production date) + /// + public virtual DateTime? ProductionDate { get; set; } + + /// + /// 器具型号(Ware class) + /// + public virtual string WareClass { get; set; } + + /// + /// 器具号(Ware code) + /// + public virtual string WareCode { get; set; } + + /// + /// 标准包装量(Standard pack quantity) + /// + public virtual decimal StdPackQty { get; set; } + + /// + /// 采购单位(Purchase um) + /// + public virtual string PoUm { get; set; } + + /// + /// 基本单位(Base um) + /// + public virtual string LocUm { get; set; } + + /// + /// 转换率(Um conversion) + /// + public virtual decimal UmConv { get; set; } + + /// + /// 物料类型(Part type) + /// + public virtual string PartType { get; set; } + + /// + /// 供应商批号(Vendor batch) + /// + public virtual string Supplierlot { get; set; } + + /// + /// 状态(Status) + /// + public virtual string Status { get; set; } + + /// + /// 标签代码(Label code) + /// + public virtual string LabelCode { get; set; } + + /// + /// 完整条码数据(Full barcode string) + /// + public virtual string EntireBarCode { get; set; } + + /// + /// 托盘标签代码(Pallet label code) + /// + public virtual string PalletLabelCode { get; set; } + + /// + /// 备注(Remark) + /// + public virtual string Remark { get; set; } + + } +} diff --git a/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application.Contracts/Asns/AsnMstrDTO.cs b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application.Contracts/Asns/AsnMstrDTO.cs new file mode 100644 index 0000000..47db1e6 --- /dev/null +++ b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application.Contracts/Asns/AsnMstrDTO.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using Win_in.Sfs.Scp.WebApi.Asns; +using Win_in.Sfs.Scp.WebApi.Domain.Shared; + +namespace Win_in.Sfs.Scp.WebApi +{ + /// + /// QAD发货单主表(ASN Master) SupplierAsnCreateInput ISupplierAsnAppService + /// + public class AsnMstrDTO:EntityDtoBase + { + /// + /// + /// + public virtual long UID { get; set; } + + /// + /// 公司(Company code) + /// + public virtual string Company { get; set; } + + /// + /// 工厂(Site) + /// + public virtual string Site { get; set; } + + /// + /// 送货单号(ASN number) + /// + public virtual string AsnNbr { get; set; } + + /// + /// 采购订单号(Purchase order number) + /// + public virtual string PoNbr { get; set; } + + /// + /// 供应商(Vendor) + /// + public virtual string VendorCode { get; set; } + + /// + /// 联系人(Contacts name) + /// + public virtual string Contacts { get; set; } + + /// + /// 联系电话(Phone) + /// + public virtual string Phone { get; set; } + + /// + /// 车牌号(Truck license plate number) + /// + public virtual string TruckNbr { get; set; } + + /// + /// 仓库(Warehouse)(Warehouse) + /// + public virtual string Whse { get; set; } + + /// + /// 收货口(Dock) + /// + public virtual string Dock { get; set; } + + + /// + /// 发货日期(Shipping date) + /// + public virtual DateTime? ShipDate { get; set; } + + /// + /// 采购单到期日(Due date) + /// + public virtual DateTime? DueDate { get; set; } + + + /// + /// 时间窗口 + /// + public string TimeWindow { get; set; } + + /// + /// 状态 + /// + public string Status { get; set; } + + /// + /// 备注(Remark) + /// + public virtual string Remark { get; set; } + + public virtual List Details { get; set; } = new List(); + } +} diff --git a/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application.Contracts/Asns/IAsnAppService.cs b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application.Contracts/Asns/IAsnAppService.cs new file mode 100644 index 0000000..dc4516b --- /dev/null +++ b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application.Contracts/Asns/IAsnAppService.cs @@ -0,0 +1,26 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; + +namespace Win_in.Sfs.Scp.WebApi.Asns +{ + /// + /// QAD发货单(ASN Master) + /// + public interface IAsnAppService : IApplicationService + { + Task> GetUnreadListAsync(string site, int count, bool autoUpdateStatus); + + Task> GetListAsync(string site, long beginUid, long endUid); + + Task> GetListAsync(string site, DateTime beginDate, DateTime endDate); + + Task> GetAsync(string site, long uid); + + Task> GetAsync(string site, string number); + + Task> UpdateStatusAsync(string site, string number, EnumExchangeDataStatus status); + } +} diff --git a/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application.Contracts/Asns/IX12AsnAppService.cs b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application.Contracts/Asns/IX12AsnAppService.cs index 863224f..3446cbb 100644 --- a/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application.Contracts/Asns/IX12AsnAppService.cs +++ b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application.Contracts/Asns/IX12AsnAppService.cs @@ -15,6 +15,7 @@ namespace Win_in.Sfs.Scp.WebApi public interface IX12AsnAppService : IReadOnlyAppService { Task> GetUnreadListAsync(string site, int count,bool autoUpdateStatus); + Task> GetNoPoUnreadListAsync(string site, int count, bool autoUpdateStatus); Task> GetListAsync(string site, long beginUid,long endUid); diff --git a/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application.Contracts/RouteConsts.cs b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application.Contracts/RouteConsts.cs index ddf6c12..208a05a 100644 --- a/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application.Contracts/RouteConsts.cs +++ b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application.Contracts/RouteConsts.cs @@ -11,5 +11,6 @@ namespace Win_in.Sfs.Scp.WebApi public const string Supplier = "api/scp/supplier"; public const string UnplannedReceipt = "api/scp/unplanned-receipt"; public const string X12Asn = "api/scp/asn"; + public const string AsnMstr = "api/scp/nopo-asn"; } } \ No newline at end of file diff --git a/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application/Asns/AsnAppService.cs b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application/Asns/AsnAppService.cs new file mode 100644 index 0000000..ba9dd2f --- /dev/null +++ b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application/Asns/AsnAppService.cs @@ -0,0 +1,325 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text.Json; +using System.Threading.Tasks; +using System.Threading.Tasks.Dataflow; +using AutoMapper; +using AutoMapper.Configuration; +using FluentValidation; +using Microsoft.AspNetCore.Http; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.Uow; +using Win_in.Sfs.Scp.v1.Domain; +using Microsoft.Extensions.Configuration; +using Volo.Abp.Clients; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Validation; +using IConfiguration = Microsoft.Extensions.Configuration.IConfiguration; +using Volo.Abp.TenantManagement; +using Win_in.Sfs.Scp.WebApi.Asns; +using Volo.Abp.Domain.Entities; +using System.Security.Cryptography; +using IdentityModel; +using Microsoft.Extensions.Options; +using Volo.Abp; + +namespace Win_in.Sfs.Scp.WebApi +{ + /// + /// ASN服务(AsnMstr Service) + /// + [Authorize] + [Route(RouteConsts.AsnMstr)] + [ApiExplorerSettings(GroupName = SwaggerGroupConsts.ScpWebApi)] + + public class AsnAppService : ReadOnlyAppService, IAsnAppService + { + private readonly IAsnRepository _asnRepository; + private readonly ITenantRepository _tenantRepository; + private readonly IOptions _options; + + public AsnAppService( + IAsnRepository repository + , ITenantRepository tenantRepository + , IOptions options + + ) : base(repository) + { + _asnRepository = repository; + _tenantRepository = tenantRepository; + _options = options; + } + + /// + /// 按ID获取ASN (Get AsnMstr by ID) + /// + /// 唯一ID(unique ID) + /// + + [HttpGet] + [Route("{id}")] + [HiddenApi] + public override async Task GetAsync(Guid id) + { + return await base.GetAsync(id); + } + + + /// + /// 按条件获取ASN分页列表 (Get AsnMstr paged list by request condition) + /// + /// 请求条件DTO(Request condition DTO) + /// + [HttpGet] + [Route("paged-list")] + [HiddenApi] + public override async Task> GetListAsync(RequestDTO requestDTO) + { + return await base.GetListAsync(requestDTO); + } + + /// + /// 获取未读ASN列表(Get unread AsnMstr list) + /// + /// 地点(Site) + /// 数量(Count) + /// 是否自动更新状态(Auto update data status to finish) + /// + [HttpGet] + [Route("unread-list")] + public async Task> GetUnreadListAsync(string site, int count, bool autoUpdateStatus) + { + try + { + Validator.CheckSite(_tenantRepository, site); + + if (count < 1 || count > _options.Value.MaxCount) + { + throw new UserFriendlyException($"Count must between 1 and {_options.Value.MaxCount}"); + } + } + catch (Exception ex) + { + throw new AbpValidationException(new List + { + new(ex.Message) + }); + } + + var entities = await _asnRepository.GetUnreadListAsync(site, count, autoUpdateStatus); + + var dtos = BuildDtos(entities); + + return new ListResultDto(dtos); + + } + + /// + /// 根据UID范围获取ASN列表(Get AsnMstr list by UID range) + /// + /// 地点(Site) + /// 开始UID(Begin UID) + /// 结束UID(End UID) + /// + /// + [HttpGet] + [Route("between-uid")] + public async Task> GetListAsync(string site, long beginUid, long endUid) + { + try + { + Validator.CheckSite(_tenantRepository, site); + + if (endUid < beginUid) + { + throw new UserFriendlyException("beginUid can not bigger than endUid"); + } + } + catch (Exception ex) + { + throw new AbpValidationException(new List + { + new(ex.Message) + }); + } + + var entities = await _asnRepository.GetListAsync(p => p.Site == site && p.UID >= beginUid && p.UID <= endUid); + + var dtos = BuildDtos(entities); + + return new ListResultDto(dtos); + } + + /// + /// 根据日期范围获取ASN列表(Get AsnMstr list by date range) + /// + /// 地点(Site) + /// 开始日期(Begin date) + /// 结束日期(End date) + /// + /// + [HttpGet] + [Route("between-date")] + public async Task> GetListAsync(string site, DateTime beginDate, DateTime endDate) + { + try + { + Validator.CheckSite(_tenantRepository, site); + + if (endDate < beginDate) + { + throw new UserFriendlyException("beginDate can not after endDate"); + } + } + catch (Exception ex) + { + throw new AbpValidationException(new List + { + new(ex.Message) + }); + } + var entities = await _asnRepository.GetListAsync(p => p.Site == site && p.EffectiveDate >= beginDate && p.EffectiveDate <= endDate); + + var dtos = BuildDtos(entities); + + return new ListResultDto(dtos); + } + + /// + /// 根据UID获取ASN(Get AsnMstr by UID) + /// + /// 地点(Site) + /// UID(UID) + /// + /// + [HttpGet] + [Route("by-uid")] + public async Task> GetAsync(string site, long uid) + { + AsnMstr entity; + try + { + Validator.CheckSite(_tenantRepository, site); + + entity = await _asnRepository.FirstOrDefaultAsync(p => p.Site == site && p.UID == uid); + + if (entity == null) + { + + throw new UserFriendlyException($"ASN of {uid} in {site} is not found"); + } + } + catch (Exception ex) + { + throw new AbpValidationException(new List + { + new(ex.Message) + }); + } + var dto = BuildDto(entity); + + return dto; + } + + /// + /// 根据单据编号获取ANS(Get AsnMstr by asn number) + /// + /// 地点(Site) + /// 单据编号(Asn number) + /// + /// + [HttpGet] + [Route("by-number")] + public async Task> GetAsync(string site, string number) + { + AsnMstr entity; + try + { + Validator.CheckSite(_tenantRepository, site); + + + entity = await _asnRepository.FirstOrDefaultAsync(p => p.Site == site && p.AsnNbr == number); + + if (entity == null) + { + throw new UserFriendlyException($"ASN of {number} in {site} is not found"); + } + } + catch (Exception ex) + { + throw new AbpValidationException(new List + { + new(ex.Message) + }); + } + var dto = BuildDto(entity); + + return dto; + + } + + /// + /// 根据单据编号更新ASN状态(Update AsnMstr Status by asn number) + /// + /// 地点(Site) + /// 单据编号(Asn number) + /// 状态(Status) + /// 0: 新增(new) + /// 1: 处理中(Processing) + /// 2: 完成(Finish) + /// 9: 搁置(Hold) + /// -1: 错误(Error) + /// + /// + /// + [HttpPost] + [Route("update-status")] + public async Task> UpdateStatusAsync(string site, string number, EnumExchangeDataStatus status) + { + AsnMstr entity; + try + { + Validator.CheckSite(_tenantRepository, site); + + + entity = await _asnRepository.FirstOrDefaultAsync(p => p.Site == site && p.AsnNbr == number); + + if (entity == null) + { + throw new UserFriendlyException($"ASN of {number} in {site} is not found"); + } + } + catch (Exception ex) + { + throw new AbpValidationException(new List + { + new(ex.Message) + }); + } + var result = await _asnRepository.UpdateStatusAsync(entity.Id, status); + + var dto = BuildDto(result); + + return dto; + } + + private List BuildDtos(List entities) + { + var dtos = ObjectMapper.Map, List>(entities); + return dtos; + } + + private AsnMstrDTO BuildDto(AsnMstr entity) + { + var dto = ObjectMapper.Map(entity); + return dto; + } + } +} diff --git a/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application/Asns/X12AsnAppService.cs b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application/Asns/X12AsnAppService.cs index c0fbd9b..a15d36c 100644 --- a/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application/Asns/X12AsnAppService.cs +++ b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application/Asns/X12AsnAppService.cs @@ -121,6 +121,35 @@ namespace Win_in.Sfs.Scp.WebApi } + [HttpGet] + [Route("nopo-unread-list")] + public async Task> GetNoPoUnreadListAsync(string site, int count, bool autoUpdateStatus) + { + try + { + Validator.CheckSite(_tenantRepository, site); + + if (count < 1 || count > _options.Value.MaxCount) + { + throw new UserFriendlyException($"Count must between 1 and {_options.Value.MaxCount}"); + } + } + catch (Exception ex) + { + throw new AbpValidationException(new List + { + new(ex.Message) + }); + } + + var entities = await _x12AsnRepository.GetNoPoUnreadListAsync(site, count, autoUpdateStatus); + + var dtos = BuildDtos(entities); + + return new ListResultDto(dtos); + + } + /// /// 根据UID范围获取ASN列表(Get X12Asn list by UID range) /// diff --git a/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application/Win_in.Sfs.Scp.WebApi.Application.csproj b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application/Win_in.Sfs.Scp.WebApi.Application.csproj index f62f66e..fc3fbe6 100644 --- a/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application/Win_in.Sfs.Scp.WebApi.Application.csproj +++ b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Application/Win_in.Sfs.Scp.WebApi.Application.csproj @@ -12,6 +12,10 @@ ..\Win_in.Sfs.Scp.WebApi.HttpApi.Host\bin\Debug\net5.0\Win_in.Sfs.Scp.WebApi.Application.xml + + + + diff --git a/WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain.Shared/NoPoASN/AsnDet.cs b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain.Shared/NoPoASN/AsnDet.cs new file mode 100644 index 0000000..2273d40 --- /dev/null +++ b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain.Shared/NoPoASN/AsnDet.cs @@ -0,0 +1,118 @@ +using System; +using Volo.Abp.Domain.Entities.Auditing; + +namespace Win_in.Sfs.Scp.WebApi +{ + /// + /// QAD发货单明细(ASN detail) SupplierAsnDetailInput + /// + public class AsnDet : CreationAuditedEntity + { + /// + /// 自增长数字主键 + /// + //public virtual int uid { get; set; } + + /// + /// 送货单号 + /// + public virtual string AsnNbr { get; set; } + + /// + /// 采购订单号 + /// + public virtual string PoNbr { get; set; } + + /// + /// 采购订单行 + /// + public virtual int PoLine { get; set; } + + /// + /// 物料号 + /// + public virtual string PartCode { get; set; } + + /// + /// 批次 + /// + public virtual string Lot { get; set; } + + /// + /// 送货总量 + /// + public virtual decimal Qty { get; set; } + + /// + /// 生产日期 + /// + public virtual DateTime? ProductionDate { get; set; } + + /// + /// 器具型号 + /// + public virtual string WareClass { get; set; } + + /// + /// 器具号 + /// + public virtual string WareCode { get; set; } + + /// + /// 标准包装量 + /// + public virtual decimal StdPackQty { get; set; } + + /// + /// 采购单位 + /// + public virtual string PoUm { get; set; } + + /// + /// 基本单位 + /// + public virtual string LocUm { get; set; } + + /// + /// 转换率 + /// + public virtual decimal UmConv { get; set; } + + /// + /// 物料类型 + /// + public virtual string PartType { get; set; } + + /// + /// 供应商批号 + /// + public virtual string Supplierlot { get; set; } + + /// + /// 状态(0:Closed,1:Open) + /// + public virtual string Status { get; set; } + + /// + /// 标签代码 + /// + public virtual string LabelCode { get; set; } + + /// + /// 完整条码数据 + /// + public virtual string EntireBarCode { get; set; } + + /// + /// 托盘标签代码 + /// + public virtual string PalletLabelCode { get; set; } + + /// + /// 备注 + /// + public virtual string Remark { get; set; } + + + } +} diff --git a/WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain.Shared/NoPoASN/AsnMstr.cs b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain.Shared/NoPoASN/AsnMstr.cs new file mode 100644 index 0000000..aa91c96 --- /dev/null +++ b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain.Shared/NoPoASN/AsnMstr.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using Win_in.Sfs.Scp.WebApi.Domain.Shared; + +namespace Win_in.Sfs.Scp.WebApi +{ + /// + /// QAD发货单主表(ASN Master) SupplierAsnCreateInput ISupplierAsnAppService + /// + public class AsnMstr : EntityBase + { + /// + /// 自增长数字主键 + /// + public virtual long UID { get; set; } + + /// + /// 公司 + /// + public virtual string Company { get; set; } + + /// + /// 工厂 + /// + public virtual string Site { get; set; } + + /// + /// 送货单号 + /// + public virtual string AsnNbr { get; set; } + + /// + /// 要货计划单号 + /// + public virtual string RpNbr { get; set; } + + /// + /// 采购订单号 + /// + public virtual string PoNbr { get; set; } + + /// + /// 供应商 + /// + public virtual string VendorCode { get; set; } + + /// + /// 联系人 + /// + public virtual string Contacts { get; set; } + + /// + /// 联系电话 + /// + public virtual string Phone { get; set; } + + /// + /// 车牌号 + /// + public virtual string TruckNbr { get; set; } + + /// + /// 仓库 + /// + public virtual string Whse { get; set; } + + /// + /// 收货口 + /// + public virtual string Dock { get; set; } + + /// + /// 发货日期 + /// + public DateTime? ShipDate { get; set; } + + /// + /// 到货日期 + /// + public DateTime? DueDate { get; set; } + + /// + /// 时间窗口 + /// + public string TimeWindow { get; set; } + + /// + /// 备注 + /// + public virtual string Remark { get; set; } + + + public virtual List Details { get; set; } = new List(); + + } +} diff --git a/WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain.Shared/ScpWebApiConsts.cs b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain.Shared/ScpWebApiConsts.cs new file mode 100644 index 0000000..b66269f --- /dev/null +++ b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain.Shared/ScpWebApiConsts.cs @@ -0,0 +1,8 @@ +namespace Win_in.Sfs.Scp.WebApi +{ + public class ScpWebApiConsts + { + public const string ASN = "ASN"; + public const string NO_PO_ASN = "NoPoASN"; + } +} \ No newline at end of file diff --git a/WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain.Shared/Win_in - Backup.Sfs.Scp.WebApi.Domain.Shared.csproj b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain.Shared/Win_in - Backup.Sfs.Scp.WebApi.Domain.Shared.csproj new file mode 100644 index 0000000..f0900ed --- /dev/null +++ b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain.Shared/Win_in - Backup.Sfs.Scp.WebApi.Domain.Shared.csproj @@ -0,0 +1,35 @@ + + + + + + netstandard2.0 + Win_in.Sfs.Scp.WebApi + true + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain/Asns/IAsnRepository.cs b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain/Asns/IAsnRepository.cs new file mode 100644 index 0000000..8bf0c13 --- /dev/null +++ b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain/Asns/IAsnRepository.cs @@ -0,0 +1,16 @@ +/* + using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Domain.Repositories; + +namespace Win_in.Sfs.Scp.WebApi.Asns +{ + public interface IAsnRepository : IRepository + { + Task> GetUnreadListAsync(string site, int count, bool autoUpdateStatus); + + Task UpdateStatusAsync(Guid id, EnumExchangeDataStatus status); + } +} +*/ \ No newline at end of file diff --git a/WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain/Asns/IX12AsnRepository.cs b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain/Asns/IX12AsnRepository.cs index db1e9af..7bf75ee 100644 --- a/WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain/Asns/IX12AsnRepository.cs +++ b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain/Asns/IX12AsnRepository.cs @@ -9,5 +9,7 @@ public interface IX12AsnRepository : IRepository { Task> GetUnreadListAsync(string site, int count, bool autoUpdateStatus); + Task> GetNoPoUnreadListAsync(string site, int count, bool autoUpdateStatus); + Task UpdateStatusAsync(Guid id, EnumExchangeDataStatus status); } \ No newline at end of file diff --git a/WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain/Asns/X12Asn.cs b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain/Asns/X12Asn.cs index a2cf419..48c9351 100644 --- a/WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain/Asns/X12Asn.cs +++ b/WebApiService/src/Win_in.Sfs.Scp.WebApi.Domain/Asns/X12Asn.cs @@ -90,12 +90,12 @@ public class X12Asn: EntityBase } - public X12Asn(long uid,string site,string billNum,string jsonString,string ediString,DateTime effectiveDate) + public X12Asn(long uid,string site,string billNum,string dataType,string jsonString,string ediString,DateTime effectiveDate) { UID = uid; Site = site; BillNum = billNum; - DataType = "ASN"; + DataType = dataType; JsonString = jsonString; EdiString = ediString; EffectiveDate = effectiveDate; diff --git a/WebApiService/src/Win_in.Sfs.Scp.WebApi.EntityFrameworkCore/DbContext/IWebApiDbContext.cs b/WebApiService/src/Win_in.Sfs.Scp.WebApi.EntityFrameworkCore/DbContext/IWebApiDbContext.cs index 1feecd6..0ebb241 100644 --- a/WebApiService/src/Win_in.Sfs.Scp.WebApi.EntityFrameworkCore/DbContext/IWebApiDbContext.cs +++ b/WebApiService/src/Win_in.Sfs.Scp.WebApi.EntityFrameworkCore/DbContext/IWebApiDbContext.cs @@ -19,5 +19,7 @@ namespace Win_in.Sfs.Scp.WebApi.EntityFrameworkCore DbSet UnplannedReceipts { get; set; } DbSet X12Asns { get; set; } + + // DbSet AsnMstrs { get; set; } } } \ No newline at end of file diff --git a/WebApiService/src/Win_in.Sfs.Scp.WebApi.EntityFrameworkCore/DbContext/WebApiDbContext.cs b/WebApiService/src/Win_in.Sfs.Scp.WebApi.EntityFrameworkCore/DbContext/WebApiDbContext.cs index fe267ed..491bf13 100644 --- a/WebApiService/src/Win_in.Sfs.Scp.WebApi.EntityFrameworkCore/DbContext/WebApiDbContext.cs +++ b/WebApiService/src/Win_in.Sfs.Scp.WebApi.EntityFrameworkCore/DbContext/WebApiDbContext.cs @@ -36,6 +36,7 @@ namespace Win_in.Sfs.Scp.WebApi.EntityFrameworkCore public virtual DbSet X12Asns { get; set; } + // public virtual DbSet AsnMstrs { get; set; } #region Entities from the modules diff --git a/WebApiService/src/Win_in.Sfs.Scp.WebApi.EntityFrameworkCore/DbContext/WebApiDbContextModelCreatingExtensions.cs b/WebApiService/src/Win_in.Sfs.Scp.WebApi.EntityFrameworkCore/DbContext/WebApiDbContextModelCreatingExtensions.cs index 1520316..0035e5a 100644 --- a/WebApiService/src/Win_in.Sfs.Scp.WebApi.EntityFrameworkCore/DbContext/WebApiDbContextModelCreatingExtensions.cs +++ b/WebApiService/src/Win_in.Sfs.Scp.WebApi.EntityFrameworkCore/DbContext/WebApiDbContextModelCreatingExtensions.cs @@ -49,6 +49,7 @@ namespace Win_in.Sfs.Scp.WebApi.EntityFrameworkCore builder.ConfigurePurchaseOrderDetail(options); builder.ConfigureUnplannedReceipt(options); builder.ConfigureX12Asn(options); + // builder.ConfigureAsn(options); } /// @@ -308,6 +309,71 @@ namespace Win_in.Sfs.Scp.WebApi.EntityFrameworkCore }); } + /* + private static void ConfigureAsn(this ModelBuilder builder, WebApiModelBuilderConfigurationOptions options) + { + builder.Entity(b => + { + //Configure table & schema Name + b.ToTable(options.TablePrefix + nameof(AsnMstr), options.Schema); + //Configure ABP properties + b.ConfigureByConvention(); + + //Properties + //b.Property(q => q.Uid); + b.Property(q => q.Company).HasMaxLength(200); + b.Property(q => q.Site).HasMaxLength(200); + b.Property(q => q.AsnNbr).HasMaxLength(200); + b.Property(q => q.RpNbr).HasMaxLength(200); + b.Property(q => q.PoNbr).HasMaxLength(200); + b.Property(q => q.VendorCode).HasMaxLength(200); + b.Property(q => q.Status).HasMaxLength(200); + b.Property(q => q.Contacts).HasMaxLength(200); + b.Property(q => q.Phone).HasMaxLength(200); + b.Property(q => q.TruckNbr).HasMaxLength(200); + b.Property(q => q.Whse).HasMaxLength(200); + b.Property(q => q.Dock).HasMaxLength(200); + b.Property(q => q.ShipDate); + b.Property(q => q.DueDate); + b.Property(q => q.TimeWindow).HasMaxLength(200); + b.Property(q => q.Remark).HasMaxLength(4096); + }); + + builder.Entity(b => + { + //Configure table & schema Name + b.ToTable(options.TablePrefix + nameof(AsnDet), options.Schema); + //Configure ABP properties + b.ConfigureByConvention(); + + //b.Property(q => q.Uid); + b.Property(q => q.AsnNbr).HasMaxLength(50); + b.Property(q => q.PoNbr).HasMaxLength(50); + b.Property(q => q.PoLine); //INT + b.Property(q => q.PartCode).HasMaxLength(50); + b.Property(q => q.Lot).HasMaxLength(200); + b.Property(q => q.Qty); //DECIMAL + b.Property(q => q.ProductionDate); //DATETIME + b.Property(q => q.WareClass).HasMaxLength(200); + b.Property(q => q.WareCode).HasMaxLength(200); + b.Property(q => q.StdPackQty); //DECIMAL + b.Property(q => q.PoUm).HasMaxLength(200); + b.Property(q => q.LocUm).HasMaxLength(200); + b.Property(q => q.UmConv); //DECIMAL + b.Property(q => q.PartType).HasMaxLength(200); + b.Property(q => q.Supplierlot).HasMaxLength(200); + b.Property(q => q.Status).HasMaxLength(200); + b.Property(q => q.LabelCode).HasMaxLength(200); + b.Property(q => q.EntireBarCode).HasMaxLength(2000); + b.Property(q => q.PalletLabelCode).HasMaxLength(200); + b.Property(q => q.Remark).HasMaxLength(4096); + + }); + + + } + */ + /* /// /// 发货单主表 diff --git a/WebApiService/src/Win_in.Sfs.Scp.WebApi.EntityFrameworkCore/Repositories/AsnRepository.cs b/WebApiService/src/Win_in.Sfs.Scp.WebApi.EntityFrameworkCore/Repositories/AsnRepository.cs new file mode 100644 index 0000000..e56209d --- /dev/null +++ b/WebApiService/src/Win_in.Sfs.Scp.WebApi.EntityFrameworkCore/Repositories/AsnRepository.cs @@ -0,0 +1,69 @@ +/* +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Domain.Repositories.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; +using Win_in.Sfs.Scp.WebApi.Asns; + +namespace Win_in.Sfs.Scp.WebApi.EntityFrameworkCore; + +public class AsnRepository : EfCoreRepository, IAsnRepository +{ + private const string Reader = "QAD Agent"; + + public AsnRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider) + { + } + + public async Task> GetUnreadListAsync(string site, int count, bool autoUpdateStatus) + { + var dbSet = await GetDbSetAsync(); + var list = await dbSet + .Where(p => p.Site == site && p.Status == EnumExchangeDataStatus.New) + .OrderBy(p => p.Id) + .Take(count) + .ToListAsync(); + + if (autoUpdateStatus) + { + foreach (var entity in list) + { + entity.SetSuccess(Reader); + await UpdateAsync(entity); + } + } + + return list; + } + + + public async Task UpdateStatusAsync(Guid id, EnumExchangeDataStatus status) + { + var entity = await base.GetAsync(id); + switch (status) + { + case EnumExchangeDataStatus.New: + entity.Reset(); + break; + case EnumExchangeDataStatus.Processing: + entity.SetProcessing(); + break; + case EnumExchangeDataStatus.Finish: + entity.SetSuccess(Reader); + break; + case EnumExchangeDataStatus.Hold: + entity.SetHold(); + break; + case EnumExchangeDataStatus.Error: + entity.SetError(Reader, EnumExchangeDataErrorCode.Exception, ""); + break; + default: + throw new ArgumentOutOfRangeException(nameof(status), status, null); + } + return await UpdateAsync(entity); + } +} +*/ \ No newline at end of file diff --git a/WebApiService/src/Win_in.Sfs.Scp.WebApi.EntityFrameworkCore/Repositories/X12AsnRepository.cs b/WebApiService/src/Win_in.Sfs.Scp.WebApi.EntityFrameworkCore/Repositories/X12AsnRepository.cs index 9d66bc2..e3e0fa1 100644 --- a/WebApiService/src/Win_in.Sfs.Scp.WebApi.EntityFrameworkCore/Repositories/X12AsnRepository.cs +++ b/WebApiService/src/Win_in.Sfs.Scp.WebApi.EntityFrameworkCore/Repositories/X12AsnRepository.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Linq.Dynamic.Core; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; @@ -22,7 +23,28 @@ public class X12AsnRepository : EfCoreRepository, { var dbSet = await GetDbSetAsync(); var list =await dbSet - .Where(p =>p.Site ==site && p.Status == EnumExchangeDataStatus.New) + .Where(p =>p.Site ==site && p.DataType== ScpWebApiConsts.ASN && p.Status == EnumExchangeDataStatus.New) + .OrderBy(p => p.UID) + .Take(count) + .ToListAsync(); + + if (autoUpdateStatus) + { + foreach (var entity in list) + { + entity.SetSuccess(Reader); + await UpdateAsync(entity); + } + } + + return list; + } + + public async Task> GetNoPoUnreadListAsync(string site, int count, bool autoUpdateStatus) + { + var dbSet = await GetDbSetAsync(); + var list = await dbSet + .Where(p => p.Site == site && p.DataType== ScpWebApiConsts.NO_PO_ASN && p.Status == EnumExchangeDataStatus.New) .OrderBy(p => p.UID) .Take(count) .ToListAsync();