diff --git a/code/src/Modules/SettleAccount/src/SettleAccount.Application.Contracts/Entities/Prices/PriceListDtoBase.cs b/code/src/Modules/SettleAccount/src/SettleAccount.Application.Contracts/Entities/Prices/PriceListDtoBase.cs
index ce1e9d91..52dd4a22 100644
--- a/code/src/Modules/SettleAccount/src/SettleAccount.Application.Contracts/Entities/Prices/PriceListDtoBase.cs
+++ b/code/src/Modules/SettleAccount/src/SettleAccount.Application.Contracts/Entities/Prices/PriceListDtoBase.cs
@@ -413,6 +413,210 @@ namespace Win.Sfs.SettleAccount.Entities.Prices
[Display(Name = "是否作废")]
public bool IsCancel { get; set; }
}
+ #endregion
+
+ #region 印度价格
+ ///
+ /// 印度价格
+ ///
+ public class PriceListYinDuDto : AuditedEntityDto
+ {
+ ///
+ /// 客户零件号
+ ///
+ [Display(Name = "客户零件号")]
+ public string LU { get; set; }
+
+ ///
+ /// 价格
+ ///
+ [Display(Name = "价格")]
+ public decimal Price { get; set; }
+
+ ///
+ /// 开始时间
+ ///
+ [Display(Name = "开始时间")]
+ public DateTime BeginDate { set; get; }
+
+ ///
+ /// 结束时间
+ ///
+ [Display(Name = "结束时间")]
+ public DateTime EndDate { set; get; }
+
+ ///
+ /// 客户编码
+ ///
+ [Display(Name = "客户编码")]
+ public string ClientCode { get; set; }
+
+ ///
+ /// 合同签订时间
+ ///
+ [Display(Name = "合同签订时间")]
+ public DateTime Date { get; set; }
+
+ ///
+ /// 合同号
+ ///
+ [Display(Name = "合同号")]
+ public string ContractNo { get; set; }
+ ///
+ /// 是否作废
+ ///
+ [Display(Name = "是否作废")]
+ public bool IsCancel { get; set; }
+ }
+
+ ///
+ /// 印度价格导出
+ ///
+ [Display(Name = "备件价格")]
+ public class PriceListYinDuExportDto
+ {
+ ///
+ /// 客户零件号
+ ///
+ [Display(Name = "客户零件号")]
+ [ExporterHeader(DisplayName = "客户零件号")]
+ public string LU { get; set; }
+ ///
+ /// 价格
+ ///
+ [Display(Name = "价格")]
+ [ExporterHeader(DisplayName = "价格")]
+ public decimal Price { get; set; }
+ ///
+ /// 开始时间
+ ///
+ [Display(Name = "开始时间")]
+ [ExporterHeader(DisplayName = "开始时间")]
+ public DateTime BeginDate { set; get; }
+ ///
+ /// 结束时间
+ ///
+ [Display(Name = "结束时间")]
+ [ExporterHeader(DisplayName = "结束时间")]
+ public DateTime EndDate { set; get; }
+ ///
+ /// 客户编码
+ ///
+ [Display(Name = "客户编码")]
+ [ExporterHeader(DisplayName = "客户编码")]
+ public string ClientCode { get; set; }
+ ///
+ /// 合同签订时间
+ ///
+ [Display(Name = "合同签订时间")]
+ [ExporterHeader(DisplayName = "合同签订时间")]
+ public DateTime Date { get; set; }
+ ///
+ /// 合同号
+ ///
+ [Display(Name = "合同号")]
+ [ExporterHeader(DisplayName = "合同号")]
+ public string ContractNo { get; set; }
+ ///
+ /// 是否作废
+ ///
+ [Display(Name = "是否作废")]
+ [ExporterHeader(DisplayName = "是否已经停用")]
+ [ValueMapping("否", false)]
+ [ValueMapping("是", true)]
+ public bool IsCancel { get; set; }
+ }
+
+ ///
+ /// 印度价格导入
+ ///
+ [Importer(HeaderRowIndex = 22)]
+ public class PriceListYinDuImportDto
+ {
+ ///
+ /// 合同签订时间
+ ///
+ [ImporterHeader(IsIgnore = true)]
+ [ExcelImporterHeadDesc(Row = 1, Cell = 1)]
+ public string Date { get; set; }
+ ///
+ /// 合同号
+ ///
+ [ImporterHeader(IsIgnore = true)]
+ [ExcelImporterHeadDesc(Row = 2, Cell = 1)]
+ public string ContractNo { get; set; }
+ ///
+ /// 零件号
+ ///
+ [Display(Name = "零件号")]
+ [Required(ErrorMessage = "{0}是必填项")]
+ [ImporterHeader(Name = "Part No.")]
+ public string PartNo { get; set; }
+ ///
+ /// 价格
+ ///
+ [ImporterHeader(Name = "Total Price")]
+ public decimal TotalPrice { get; set; }
+ ///
+ /// 开始时间
+ ///
+ [ImporterHeader(Name = "Valid From")]
+ public DateTime ValidFrom { get; set; }
+ ///
+ /// 结束时间
+ ///
+ [ImporterHeader(Name = "Valid To")]
+ public DateTime ValidTo { get; set; }
+ ///
+ /// 客户编码
+ ///
+ [ImporterHeader(Name = "Plant")]
+ public string Plant { get; set; }
+ ///
+ /// ES1
+ ///
+ [ImporterHeader(Name = "ES1")]
+ public string ES1 { get; set; }
+ ///
+ /// ES2
+ ///
+ [ImporterHeader(Name = "ES2")]
+ public string ES2 { get; set; }
+ }
+
+ public class PriceListYinDuRequestDto : RequestInputBase
+ {
+ [Display(Name = "开始时间")]
+ public DateTime BeginDate { get; set; }
+ [Display(Name = "结算时间")]
+ public DateTime EndDate { get; set; }
+ [Display(Name = "价格")]
+ public decimal Price { get; set; }
+ [Display(Name = "物料编号")]
+ public string MaterialCode { get; set; }
+ [Display(Name = "价格类型")]
+ public int Type { get; set; }
+
+ public Guid ParentId { set; get; }
+
+ public int FileType { set; get; }
+
+ public string Version { set; get; }
+
+ public virtual List Filters { get; set; } = new List();
+ }
+
+ ///
+ /// UpdateDto
+ ///
+ public class PriceListYinDuUpdateDto : EntityDto
+ {
+ ///
+ /// 是否作废
+ ///
+ [Display(Name = "是否作废")]
+ public bool IsCancel { get; set; }
+ }
+ #endregion
}
-#endregion
diff --git a/code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/Prices/PriceListAppServiceBJ.cs b/code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/Prices/PriceListAppServiceBJ.cs
index f7817915..e2c56dc6 100644
--- a/code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/Prices/PriceListAppServiceBJ.cs
+++ b/code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/Prices/PriceListAppServiceBJ.cs
@@ -55,10 +55,10 @@ namespace Win.Sfs.SettleAccount.Entities.Prices
/// * 备件价格单筛选 Plant(客户编码) 为(1049)的数据
/// * 客户零件号为 PartNo+6个空格+ES1+ES2
/// * 根据 合同日期、客户编码、零件号、开始时间、结束时间分组导入(过滤重复数据)
- /// 数据校验
+ /// * 数据校验
/// * 同一合同日期、客户编码、零件号 不能存在时间交集
/// * 判断同一个零件号时间区间是否连续
- /// 作废旧合同日期的数据
+ /// * 作废旧合同日期的数据
/// * 比较新导入的数据和数据库中老数据(同一零件号、旧合同日期的数据修改状态为作废)
///
[HttpPost]
diff --git a/code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/Prices/PriceListAppServiceYinDu.cs b/code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/Prices/PriceListAppServiceYinDu.cs
new file mode 100644
index 00000000..6a59e00c
--- /dev/null
+++ b/code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/Prices/PriceListAppServiceYinDu.cs
@@ -0,0 +1,238 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using EFCore.BulkExtensions;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Shouldly;
+using Volo.Abp;
+using Volo.Abp.Application.Dtos;
+using Volo.Abp.Caching;
+using Win.Abp.Snowflakes;
+using Win.Sfs.BaseData.ImportExcelCommon;
+using Win.Sfs.SettleAccount.CommonManagers;
+using Win.Sfs.SettleAccount.Constant;
+using Win.Sfs.SettleAccount.Entities.BQ.Dtos;
+using Win.Sfs.SettleAccount.ExcelImporter;
+using Win.Sfs.SettleAccount.ExportReports;
+using Win.Sfs.Shared.RepositoryBase;
+
+namespace Win.Sfs.SettleAccount.Entities.Prices
+{
+ ///
+ /// 印度件价格
+ ///
+ [AllowAnonymous]
+ [Route("api/settleaccount/[controller]/[action]")]
+ public class PriceListAppServiceYinDu : SettleAccountApplicationBase
+ {
+ ///
+ /// 数据上下文
+ ///
+ private readonly SettleAccountDbContext _settleAccountDbContext;
+ private readonly INormalEfCoreRepository _repository;
+
+ public PriceListAppServiceYinDu(
+ SettleAccountDbContext settleAccountDbContext,
+ INormalEfCoreRepository repository,
+ IDistributedCache cache,
+ IExcelImportAppService excelImportService,
+ ISnowflakeIdGenerator snowflakeIdGenerator,
+ ICommonManager commonManager
+ ) : base(cache, excelImportService, snowflakeIdGenerator, commonManager)
+ {
+ _settleAccountDbContext = settleAccountDbContext;
+ _repository = repository;
+ }
+
+ #region 导入、导出
+ ///
+ /// 导入
+ ///
+ ///
+ ///
+ ///
+ [HttpPost]
+ public async Task ImportAsync([FromForm] IFormFileCollection files, string version)
+ {
+ var checkList = new List();
+ var _exportImporter = new ExportImporter();
+ var result = await _exportImporter.UploadExcelImportByHeadDesc(files, _excelImportService).ConfigureAwait(false);
+ var filter = new List
+ {
+ "1049"
+ };
+ result = result.Where(p => filter.Contains(p.Plant)).ToList();
+ result.FindAll(t => !string.IsNullOrEmpty(t.ES1) || !string.IsNullOrEmpty(t.ES2)).ForEach(t => t.PartNo = t.PartNo + new string(' ', 6) + t.ES1 + t.ES2);
+ var newPrice = ObjectMapper.Map, List>(result);
+ newPrice = newPrice.GroupBy(p => new { p.Date, p.ClientCode, p.LU, p.BeginDate, p.EndDate }).Select(p => p.FirstOrDefault()).ToList();
+
+ #region 校验
+ if (newPrice.Any())
+ {
+ var query = from item1 in newPrice
+ join item2 in newPrice
+ on new { item1.Date, item1.ClientCode, item1.LU } equals new { item2.Date, item2.ClientCode, item2.LU }
+ where (item1.BeginDate > item2.BeginDate && item1.EndDate < item2.EndDate) || (item2.BeginDate > item1.BeginDate && item2.EndDate < item1.EndDate) || (item1.BeginDate == item2.BeginDate && item1.EndDate != item2.EndDate) || (item1.BeginDate != item2.BeginDate && item1.EndDate == item2.EndDate)
+ select item1;
+ var repeat = query.Distinct().ToList();
+ foreach (var item in repeat)
+ {
+ checkList.Add(new ErrorExportDto(string.Empty, string.Empty, string.Empty, string.Empty, item.LU, string.Empty, $"合同号:{item.ContractNo},合同签订时间:{item.Date:yyyy-MM-dd},时间区间存在交集", string.Empty));
+ }
+
+ //foreach (var item in CheckPriceListContinuity(newPrice))
+ //{
+ // checkList.Add(new ErrorExportDto(string.Empty, string.Empty, string.Empty, string.Empty, item.LU, string.Empty, $"合同号:{item.ContractNo},合同签订时间:{item.Date:yyyy-MM-dd},时间区间【{item.BeginDate:yyyy-MM-dd}至{item.EndDate:yyyy-MM-dd}】不连续", string.Empty));
+ //}
+ }
+ if (checkList.Count > 0)
+ {
+ var fileName = await ExportErrorReportAsync(checkList).ConfigureAwait(false);
+ return new JsonResult(new { code = ApplicationConsts.ImportFailCode, message = "导入失败", fileName });
+ }
+ #endregion
+
+ newPrice.ForEach(t => t.IsCancel = true);
+ newPrice.GroupBy(t => new { t.ClientCode, t.LU })
+ .SelectMany(t =>
+ {
+ var data = t.OrderByDescending(t => t.Date).First().Date;
+ return t.Where(t => t.Date == data);
+ })
+ .ForEach(t => t.IsCancel = false);
+
+ var importLus = newPrice.Select(t => t.LU).Distinct().ToList();
+ var oldPrices = _settleAccountDbContext.Set()
+ .Where(t => t.IsCancel == false)
+ .Where(t => importLus.Contains(t.LU))
+ .ToList();
+ //系统中合同日期比导入文件中的合同日期晚
+ var oldPriceNewDate = from oldPriceItem in oldPrices
+ from newPriceItem in newPrice.FindAll(t => t.IsCancel == false)
+ where oldPriceItem.ClientCode == newPriceItem.ClientCode && oldPriceItem.LU == newPriceItem.LU && oldPriceItem.Date > newPriceItem.Date
+ select new { oldPriceItem, newPriceItem };
+ oldPrices.ForEach(t => t.IsCancel = true);
+ if (oldPriceNewDate.Any())
+ {
+ oldPrices.FindAll(t => t.IsCancel == true && oldPriceNewDate.Select(t => t.oldPriceItem).Contains(t)).ForEach(t => t.IsCancel = false);
+ newPrice.FindAll(t => t.IsCancel == false && oldPriceNewDate.Select(t => t.newPriceItem).Contains(t)).ForEach(t => t.IsCancel = true);
+ }
+ foreach (var item in newPrice)
+ {
+ item.Update(GuidGenerator.Create());
+ }
+ using var transaction = await _settleAccountDbContext.Database.BeginTransactionAsync().ConfigureAwait(false);
+ try
+ {
+ await _settleAccountDbContext.BulkUpdateAsync(oldPrices).ConfigureAwait(false);
+ await _settleAccountDbContext.BulkInsertAsync(newPrice).ConfigureAwait(false);
+ await transaction.CommitAsync().ConfigureAwait(false);
+ }
+ catch (Exception)
+ {
+ await transaction.RollbackAsync().ConfigureAwait(false);
+ return new JsonResult(new { Code = 200, Message = "导入失败" });
+ }
+ return new JsonResult(new { Code = 200, Message = "导入成功" });
+
+ }
+
+ ///
+ /// 价格表时间是否连续
+ ///
+ private List CheckPriceListContinuity(List priceList)
+ {
+ var result = new List();
+ if (priceList.Count <= 1)
+ {
+ return result; // 只有一个或零个价格条目
+ }
+
+ var dateGroups = priceList.GroupBy(t => t.Date);
+ foreach (var dateGroup in dateGroups)
+ {
+ var clientCodeGroups = dateGroup.GroupBy(t => t.ClientCode);
+ foreach (var clientCodeGroup in clientCodeGroups)
+ {
+ if (clientCodeGroup.ToList().Count <= 1)
+ {
+ continue;
+ }
+ var sortedList = clientCodeGroup.OrderBy(t => t.LU).ThenBy(t => t.BeginDate).ToList();
+ for (var i = 1; i < sortedList.Count; i++)
+ {
+ if (sortedList[i].LU == sortedList[i - 1].LU && sortedList[i].BeginDate != sortedList[i - 1].EndDate.AddDays(1))
+ {
+ result.Add(sortedList[i]);
+ }
+ }
+ }
+ }
+
+ return result; // 所有价格时间都连续
+ }
+
+ ///
+ /// 导出
+ ///
+ [HttpPost]
+ public async Task ExportAsync(RequestDto input)
+ {
+ string fileName = $"印度件价格_{Guid.NewGuid()}.xlsx";
+ var entities = await _repository.GetListByFilterAsync(input.Filters, input.Sorting, int.MaxValue, 0, true).ConfigureAwait(false);
+ var dtos = ObjectMapper.Map, List>(entities);
+
+ ExportImporter _exportImporter = new ExportImporter();
+ var result = await _exportImporter.ExcelExporter(dtos).ConfigureAwait(false);
+ result.ShouldNotBeNull();
+
+ await _excelImportService.SaveBlobAsync(new SaveExcelImportInputDto { Name = fileName, Content = result }).ConfigureAwait(false);
+ return fileName;
+ }
+ #endregion
+
+ #region CURD
+ ///
+ /// 获取列表
+ ///
+ [HttpPost]
+ public async Task> GetListAsync(RequestDto input)
+ {
+ var entities = await _repository.GetListByFilterAsync(input.Filters, input.Sorting, input.MaxResultCount, input.SkipCount, true).ConfigureAwait(false);
+ var totalCount = await _repository.GetCountByFilterAsync(input.Filters).ConfigureAwait(false);
+ var dtos = ObjectMapper.Map, List>(entities);
+ return new PagedResultDto(totalCount, dtos);
+ }
+
+ ///
+ /// 修改实体
+ ///
+ [HttpPost]
+ public async Task UpdateAsync(PriceListYinDuUpdateDto input)
+ {
+ var entity = await _settleAccountDbContext.Set().FindAsync(input.Id).ConfigureAwait(false);
+ entity.IsCancel = input.IsCancel;
+ if (entity.IsCancel == false)
+ {
+ var existPrices = _settleAccountDbContext.Set()
+ .Where(t => t.LU == entity.LU)
+ .Where(t => t.IsCancel == false)
+ .Where(t => t.Id != entity.Id)
+ .ToList();
+
+ var existPrice = existPrices.Find(t => (entity.BeginDate >= t.BeginDate && entity.BeginDate < t.EndDate) || (t.BeginDate >= entity.BeginDate && t.BeginDate < entity.EndDate));
+ if (existPrice != null)
+ {
+ throw new UserFriendlyException($"无法启用!此记录启用时间区间与区间【{existPrice.BeginDate:yyyy-MM-dd}至{existPrice.EndDate:yyyy-MM-dd}】存在交集", "400");
+ }
+ }
+ await _settleAccountDbContext.SaveChangesAsync().ConfigureAwait(false);
+ var dto = ObjectMapper.Map(entity);
+ return dto;
+ }
+ #endregion
+ }
+}
diff --git a/code/src/Modules/SettleAccount/src/SettleAccount.Application/SettleAccountApplicationAutoMapperProfile.cs b/code/src/Modules/SettleAccount/src/SettleAccount.Application/SettleAccountApplicationAutoMapperProfile.cs
index d58fc0b1..13ace9f7 100644
--- a/code/src/Modules/SettleAccount/src/SettleAccount.Application/SettleAccountApplicationAutoMapperProfile.cs
+++ b/code/src/Modules/SettleAccount/src/SettleAccount.Application/SettleAccountApplicationAutoMapperProfile.cs
@@ -104,6 +104,7 @@ namespace Win.Sfs.SettleAccount
CreateMapPriceListBJVersion();
CreateMapPriceListBJ();
+ CreateMapPriceListYinDu();
#endregion
#region 派格
@@ -501,6 +502,24 @@ namespace Win.Sfs.SettleAccount
CreateMap().ReverseMap();
}
+ ///
+ /// 印度价格
+ ///
+ private void CreateMapPriceListYinDu()
+ {
+ CreateMap()
+ .ForMember(x => x.LU, y => y.MapFrom(y => y.PartNo))
+ .ForMember(x => x.Price, y => y.MapFrom(y => y.TotalPrice))
+ .ForMember(x => x.BeginDate, y => y.MapFrom(y => y.ValidFrom))
+ .ForMember(x => x.EndDate, y => y.MapFrom(y => y.ValidTo))
+ .ForMember(x => x.ClientCode, y => y.MapFrom(y => y.Plant))
+ .ForMember(x => x.Date, y => y.MapFrom(y => DateTime.ParseExact(y.Date, "dd.MM.yyyy", System.Globalization.CultureInfo.CurrentCulture))); ;
+
+ CreateMap().ReverseMap();
+ CreateMap().ReverseMap();
+ CreateMap().ReverseMap();
+ }
+
private void CreateMapInvoiceSettledDiff()
{