using NCC.Common.Core.Manager; using NCC.Common.Enum; using NCC.Common.Extension; using NCC.Common.Filter; using NCC.Dependency; using NCC.DynamicApiController; using NCC.FriendlyException; using NCC.Extend.Interfaces.LqCooperationCost; using Mapster; using Microsoft.AspNetCore.Mvc; using SqlSugar; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using NCC.Extend.Entitys.lq_cooperation_cost; using NCC.Extend.Entitys.Dto.LqCooperationCost; using NCC.Extend.Entitys.lq_mdxx; using Yitter.IdGenerator; using NCC.Common.Helper; using NCC.Common.Model.NPOI; using NCC.Common.Configuration; using NCC.DataEncryption; using NCC.ClayObject; using NCC.Common.Const; using NCC.Extend.Entitys.Enum; using Microsoft.AspNetCore.Http; using System.IO; using System.Data; namespace NCC.Extend.LqCooperationCost { /// /// 合作成本表服务 /// [ApiDescriptionSettings(Tag = "Extend", Name = "LqCooperationCost", Order = 200)] [Route("api/Extend/[controller]")] public class LqCooperationCostService : ILqCooperationCostService, IDynamicApiController, ITransient { private readonly ISqlSugarRepository _repository; private readonly SqlSugarScope _db; private readonly IUserManager _userManager; /// /// 初始化一个类型的新实例 /// public LqCooperationCostService( ISqlSugarRepository repository, IUserManager userManager) { _repository = repository; _db = _repository.Context; _userManager = userManager; } /// /// 获取合作成本表详情 /// /// 主键ID /// [HttpGet("{id}")] public async Task GetInfo(string id) { var entity = await _db.Queryable() .Where(x => x.Id == id && x.IsEffective == StatusEnum.有效.GetHashCode()) .FirstAsync(); _ = entity ?? throw NCCException.Oh(ErrorCode.COM1005); var output = entity.Adapt(); return output; } /// /// 获取合作成本表列表 /// /// 请求参数 /// [HttpGet("")] public async Task GetList([FromQuery] LqCooperationCostListQueryInput input) { var sidx = input.sidx ?? "CreateTime"; var sortType = input.sort?.ToLower() == "asc" ? OrderByType.Asc : OrderByType.Desc; var query = _db.Queryable() .Where(x => x.IsEffective == StatusEnum.有效.GetHashCode()) .WhereIF(!string.IsNullOrEmpty(input.storeId), x => x.StoreId == input.storeId) .WhereIF(!string.IsNullOrEmpty(input.storeName), x => x.StoreName.Contains(input.storeName)) .WhereIF(input.year.HasValue, x => x.Year == input.year.Value) .WhereIF(!string.IsNullOrEmpty(input.month), x => x.Month == input.month); // 处理排序 switch (sidx.ToLower()) { case "id": query = query.OrderBy(x => x.Id, sortType); break; case "createtime": query = query.OrderBy(x => x.CreateTime, sortType); break; case "storename": query = query.OrderBy(x => x.StoreName, sortType); break; case "year": query = query.OrderBy(x => x.Year, sortType); break; case "month": query = query.OrderBy(x => x.Month, sortType); break; default: query = query.OrderBy(x => x.CreateTime, OrderByType.Desc); break; } var total = await query.CountAsync(); var list = await query.ToPageListAsync(input.currentPage, input.pageSize); var result = list.Select(x => new LqCooperationCostListOutput { id = x.Id, storeId = x.StoreId, storeName = x.StoreName, year = x.Year, month = x.Month, totalAmount = x.TotalAmount, remarks = x.Remarks, createUser = x.CreateUser, createTime = x.CreateTime, updateUser = x.UpdateUser, updateTime = x.UpdateTime }).ToList(); return PageResult.SqlSugarPageResult( new SqlSugarPagedList { list = result, pagination = new PagedModel { PageIndex = input.currentPage, PageSize = input.pageSize, Total = total } }); } /// /// 获取合作成本表无分页列表 /// /// 请求参数 /// [HttpGet("Actions/GetNoPagingList")] public async Task> GetNoPagingList([FromQuery] LqCooperationCostListQueryInput input) { var sidx = input.sidx ?? "CreateTime"; var sortType = input.sort?.ToLower() == "asc" ? OrderByType.Asc : OrderByType.Desc; var query = _db.Queryable() .Where(x => x.IsEffective == StatusEnum.有效.GetHashCode()) .WhereIF(!string.IsNullOrEmpty(input.storeId), x => x.StoreId == input.storeId) .WhereIF(!string.IsNullOrEmpty(input.storeName), x => x.StoreName.Contains(input.storeName)) .WhereIF(input.year.HasValue, x => x.Year == input.year.Value) .WhereIF(!string.IsNullOrEmpty(input.month), x => x.Month == input.month); // 处理排序 switch (sidx.ToLower()) { case "id": query = query.OrderBy(x => x.Id, sortType); break; case "createtime": query = query.OrderBy(x => x.CreateTime, sortType); break; case "storename": query = query.OrderBy(x => x.StoreName, sortType); break; case "year": query = query.OrderBy(x => x.Year, sortType); break; case "month": query = query.OrderBy(x => x.Month, sortType); break; default: query = query.OrderBy(x => x.CreateTime, OrderByType.Desc); break; } var list = await query .Select(x => new LqCooperationCostListOutput { id = x.Id, storeId = x.StoreId, storeName = x.StoreName, year = x.Year, month = x.Month, totalAmount = x.TotalAmount, remarks = x.Remarks, createUser = x.CreateUser, createTime = x.CreateTime, updateUser = x.UpdateUser, updateTime = x.UpdateTime }) .ToListAsync(); return list; } /// /// 创建合作成本表 /// /// 参数 /// [HttpPost("")] public async Task Create([FromBody] LqCooperationCostCrInput input) { var userInfo = await _userManager.GetUserInfo(); var entity = input.Adapt(); entity.Id = YitIdHelper.NextId().ToString(); entity.IsEffective = StatusEnum.有效.GetHashCode(); entity.CreateUser = _userManager.UserId; entity.CreateTime = DateTime.Now; // 如果未提供门店名称,根据门店ID查询 if (string.IsNullOrEmpty(entity.StoreName) && !string.IsNullOrEmpty(entity.StoreId)) { var store = await _db.Queryable() .Where(x => x.Id == entity.StoreId) .Select(x => x.Dm) .FirstAsync(); entity.StoreName = store; } var isOk = await _db.Insertable(entity).ExecuteCommandAsync(); if (!(isOk > 0)) throw NCCException.Oh(ErrorCode.COM1000); } /// /// 更新合作成本表 /// /// 主键 /// 参数 /// [HttpPut("{id}")] public async Task Update(string id, [FromBody] LqCooperationCostUpInput input) { var entity = await _db.Queryable() .Where(x => x.Id == id && x.IsEffective == StatusEnum.有效.GetHashCode()) .FirstAsync(); _ = entity ?? throw NCCException.Oh(ErrorCode.COM1005); entity.StoreId = input.storeId; entity.StoreName = input.storeName; entity.Year = input.year; entity.Month = input.month; entity.TotalAmount = input.totalAmount; entity.Remarks = input.remarks; entity.UpdateUser = _userManager.UserId; entity.UpdateTime = DateTime.Now; // 如果未提供门店名称,根据门店ID查询 if (string.IsNullOrEmpty(entity.StoreName) && !string.IsNullOrEmpty(entity.StoreId)) { var store = await _db.Queryable() .Where(x => x.Id == entity.StoreId) .Select(x => x.Dm) .FirstAsync(); entity.StoreName = store; } var isOk = await _db.Updateable(entity).ExecuteCommandAsync(); if (!(isOk > 0)) throw NCCException.Oh(ErrorCode.COM1001); } /// /// 删除合作成本表 /// /// 主键 /// [HttpDelete("{id}")] public async Task Delete(string id) { var entity = await _db.Queryable() .Where(x => x.Id == id && x.IsEffective == StatusEnum.有效.GetHashCode()) .FirstAsync(); _ = entity ?? throw NCCException.Oh(ErrorCode.COM1005); // 逻辑删除 entity.IsEffective = StatusEnum.无效.GetHashCode(); entity.UpdateUser = _userManager.UserId; entity.UpdateTime = DateTime.Now; var isOk = await _db.Updateable(entity).ExecuteCommandAsync(); if (!(isOk > 0)) throw NCCException.Oh(ErrorCode.COM1002); } /// /// 导出合作成本表 /// /// 请求参数 /// [HttpGet("Actions/Export")] public async Task Export([FromQuery] LqCooperationCostListQueryInput input) { var userInfo = await _userManager.GetUserInfo(); var exportData = new List(); if (input.dataType == 0) { var data = Clay.Object(await this.GetList(input)); exportData = data.Solidify>().list; } else { exportData = await this.GetNoPagingList(input); } List paramList = "[{\"value\":\"门店ID\",\"field\":\"storeId\"},{\"value\":\"门店名称\",\"field\":\"storeName\"},{\"value\":\"年份\",\"field\":\"year\"},{\"value\":\"月份\",\"field\":\"month\"},{\"value\":\"合计金额\",\"field\":\"totalAmount\"},{\"value\":\"备注说明\",\"field\":\"remarks\"},{\"value\":\"创建人\",\"field\":\"createUser\"},{\"value\":\"创建时间\",\"field\":\"createTime\"},]".ToList(); ExcelConfig excelconfig = new ExcelConfig(); excelconfig.FileName = "合作成本表.xls"; excelconfig.HeadFont = "微软雅黑"; excelconfig.HeadPoint = 10; excelconfig.IsAllSizeColumn = true; excelconfig.ColumnModel = new List(); List selectKeyList = !string.IsNullOrEmpty(input.selectKey) ? input.selectKey.Split(',').ToList() : paramList.Select(p => p.field).ToList(); foreach (var item in selectKeyList) { var isExist = paramList.Find(p => p.field == item); if (isExist != null) { excelconfig.ColumnModel.Add(new ExcelColumnModel() { Column = isExist.field, ExcelColumn = isExist.value }); } } var addPath = FileVariable.TemporaryFilePath + excelconfig.FileName; ExcelExportHelper.Export(exportData, excelconfig, addPath); var fileName = _userManager.UserId + "|" + addPath + "|xls"; var output = new { name = excelconfig.FileName, url = "/api/File/Download?encryption=" + DESCEncryption.Encrypt(fileName, "NCC") }; return output; } /// /// 导入合作成本数据 /// /// /// 从Excel文件导入合作成本数据 /// /// Excel格式要求: /// 第一行为标题行:门店ID、门店名称、年份、月份、合计金额、备注说明 /// 从第二行开始为数据行 /// /// 示例请求: /// POST /api/Extend/LqCooperationCost/Actions/Import /// Content-Type: multipart/form-data /// /// Excel文件 /// 导入结果 /// 导入成功 /// 文件格式错误或数据验证失败 [HttpPost("Actions/Import")] public async Task Import(IFormFile file) { try { if (file == null || file.Length == 0) { throw NCCException.Oh("请选择要上传的Excel文件"); } // 检查文件格式 var allowedExtensions = new[] { ".xlsx", ".xls" }; var fileExtension = Path.GetExtension(file.FileName).ToLowerInvariant(); if (!allowedExtensions.Contains(fileExtension)) { throw NCCException.Oh("只支持.xlsx和.xls格式的Excel文件"); } var successCount = 0; var failCount = 0; var failMessages = new List(); // 保存临时文件 var tempFilePath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + Path.GetExtension(file.FileName)); try { using (var stream = new FileStream(tempFilePath, FileMode.Create)) { await file.CopyToAsync(stream); } // 使用ExcelImportHelper读取Excel文件(第一行为标题行) var dataTable = ExcelImportHelper.ToDataTable(tempFilePath, 0, 0); if (dataTable.Rows.Count <= 1) { throw NCCException.Oh("Excel文件中没有数据行(至少需要标题行和一行数据)"); } // 从第1行开始读取数据(跳过标题行) for (int i = 1; i < dataTable.Rows.Count; i++) { try { var row = dataTable.Rows[i]; var storeId = row[0]?.ToString()?.Trim(); var storeName = row[1]?.ToString()?.Trim(); var yearText = row[2]?.ToString()?.Trim(); var monthText = row[3]?.ToString()?.Trim(); var totalAmountText = row[4]?.ToString()?.Trim(); var remarks = row[5]?.ToString()?.Trim(); // 跳过空行 if (string.IsNullOrEmpty(storeId) && string.IsNullOrEmpty(storeName)) { continue; } // 验证必填字段 if (string.IsNullOrEmpty(storeId)) { failMessages.Add($"第{i + 1}行:门店ID不能为空"); failCount++; continue; } if (string.IsNullOrEmpty(yearText) || !int.TryParse(yearText, out int year)) { failMessages.Add($"第{i + 1}行:年份格式错误(应为数字)"); failCount++; continue; } if (string.IsNullOrEmpty(monthText) || monthText.Length != 6) { failMessages.Add($"第{i + 1}行:月份格式错误(应为YYYYMM格式,如:202501)"); failCount++; continue; } if (string.IsNullOrEmpty(totalAmountText) || !decimal.TryParse(totalAmountText, out decimal totalAmount)) { failMessages.Add($"第{i + 1}行:合计金额格式错误(应为数字)"); failCount++; continue; } // 如果未提供门店名称,根据门店ID查询 if (string.IsNullOrEmpty(storeName)) { var store = await _db.Queryable() .Where(x => x.Id == storeId) .Select(x => x.Dm) .FirstAsync(); storeName = store ?? ""; } // 检查是否已存在相同门店、年份、月份的记录 var exists = await _db.Queryable() .Where(x => x.StoreId == storeId && x.Year == year && x.Month == monthText && x.IsEffective == StatusEnum.有效.GetHashCode()) .AnyAsync(); if (exists) { failMessages.Add($"第{i + 1}行:该门店{year}年{monthText}月的记录已存在"); failCount++; continue; } // 创建记录 var entity = new LqCooperationCostEntity { Id = YitIdHelper.NextId().ToString(), StoreId = storeId, StoreName = storeName, Year = year, Month = monthText, TotalAmount = totalAmount, Remarks = remarks, IsEffective = StatusEnum.有效.GetHashCode(), CreateUser = _userManager.UserId, CreateTime = DateTime.Now }; var isOk = await _db.Insertable(entity).ExecuteCommandAsync(); if (isOk > 0) { successCount++; } else { failMessages.Add($"第{i + 1}行:保存失败"); failCount++; } } catch (Exception ex) { failMessages.Add($"第{i + 1}行:{ex.Message}"); failCount++; } } } finally { // 清理临时文件 if (File.Exists(tempFilePath)) { File.Delete(tempFilePath); } } return new { success = true, message = $"导入完成:成功{successCount}条,失败{failCount}条", successCount = successCount, failCount = failCount, failMessages = failMessages }; } catch (Exception ex) { throw NCCException.Oh($"导入失败:{ex.Message}"); } } } }