using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using NCC.Common.Core.Manager;
using NCC.Common.Enum;
using NCC.Common.Filter;
using NCC.Dependency;
using NCC.DynamicApiController;
using NCC.Extend.Entitys.Dto.LqMdTarget;
using NCC.Extend.Entitys.Enum;
using NCC.Extend.Entitys.lq_md_target;
using NCC.Extend.Entitys.lq_mdxx;
using NCC.Extend.Interfaces.LqMdTarget;
using NCC.FriendlyException;
using SqlSugar;
using Yitter.IdGenerator;
namespace NCC.Extend.LqMdTarget
{
///
/// 门店目标服务
///
[ApiDescriptionSettings(Tag = "绿纤门店目标服务", Name = "LqMdTarget", Order = 200)]
[Route("api/Extend/[controller]")]
public class LqMdTargetService : ILqMdTargetService, IDynamicApiController, ITransient
{
private readonly ISqlSugarRepository _lqMdTargetRepository;
private readonly SqlSugarScope _db;
private readonly IUserManager _userManager;
///
/// 初始化一个类型的新实例
///
public LqMdTargetService(ISqlSugarRepository lqMdTargetRepository, IUserManager userManager)
{
_lqMdTargetRepository = lqMdTargetRepository;
_db = _lqMdTargetRepository.Context;
_userManager = userManager;
}
#region 获取门店目标信息
///
/// 获取门店目标信息
///
/// 主键ID
///
[HttpGet("{id}")]
public async Task GetInfo(string id)
{
var entity = await _db.Queryable().FirstAsync(p => p.Id == id);
_ = entity ?? throw NCCException.Oh(ErrorCode.COM1005);
var output = entity.Adapt();
return output;
}
#endregion
#region 获取门店目标列表
///
/// 获取门店目标列表
///
/// 请求参数
///
[HttpGet("")]
public async Task GetList([FromQuery] LqMdTargetListQueryInput input)
{
var sidx = input.sidx == null ? "id" : input.sidx;
var sort = string.IsNullOrEmpty(input.sort) ? "DESC" : input.sort;
var data = await _db.Queryable()
.WhereIF(!string.IsNullOrEmpty(input.storeId), p => p.StoreId.Contains(input.storeId))
.WhereIF(!string.IsNullOrEmpty(input.month), p => p.Month == input.month)
.WhereIF(!string.IsNullOrEmpty(input.businessUnit), p => p.BusinessUnit.Contains(input.businessUnit))
.WhereIF(!string.IsNullOrEmpty(input.techDepartment), p => p.TechDepartment.Contains(input.techDepartment))
.WhereIF(!string.IsNullOrEmpty(input.educationDepartment), p => p.EducationDepartment.Contains(input.educationDepartment))
.WhereIF(!string.IsNullOrEmpty(input.majorProjectDepartment), p => p.MajorProjectDepartment.Contains(input.majorProjectDepartment))
.Select(it => new LqMdTargetListOutput
{
id = it.Id,
storeId = it.StoreId,
month = it.Month,
businessUnit = it.BusinessUnit,
techDepartment = it.TechDepartment,
educationDepartment = it.EducationDepartment,
majorProjectDepartment = it.MajorProjectDepartment,
businessUnitTarget = it.BusinessUnitTarget,
techDepartmentTarget = it.TechDepartmentTarget,
educationDepartmentTarget = it.EducationDepartmentTarget,
majorProjectDepartmentTarget = it.MajorProjectDepartmentTarget,
businessUnitGeneralManager = it.BusinessUnitGeneralManager,
businessUnitManager = it.BusinessUnitManager,
storeTarget = it.StoreTarget,
storeLifeline = it.StoreLifeline,
storeConsumeTarget = it.StoreConsumeTarget,
storeProjectTarget = it.StoreProjectTarget,
storeHeadcountTarget = it.StoreHeadcountTarget,
assistantHeadcountTargetStage1 = it.AssistantHeadcountTargetStage1,
assistantHeadcountTargetStage2 = it.AssistantHeadcountTargetStage2,
createTime = it.CreateTime,
createUser = it.CreateUser,
updateTime = it.UpdateTime,
updateUser = it.UpdateUser,
})
.MergeTable()
.OrderBy($"{sidx} {sort}")
.ToPagedListAsync(input.currentPage, input.pageSize);
return PageResult.SqlSugarPageResult(data);
}
#endregion
#region 新建门店目标
///
/// 新建门店目标
///
/// 参数
///
[HttpPost("")]
public async Task Create([FromBody] LqMdTargetCrInput input)
{
var userInfo = await _userManager.GetUserInfo();
// 验证门店ID和月份的唯一性
var exists = await _db.Queryable().Where(p => p.StoreId == input.storeId && p.Month == input.month).AnyAsync();
if (exists)
{
throw NCCException.Oh(ErrorCode.COM1000, "该门店在该月份已存在目标记录");
}
// 验证月份格式
if (input.month.Length != 6 || !Regex.IsMatch(input.month, @"^\d{6}$"))
{
throw NCCException.Oh(ErrorCode.COM1000, "月份格式必须为YYYYMM(如:202501)");
}
var entity = input.Adapt();
entity.Id = YitIdHelper.NextId().ToString();
entity.CreateTime = DateTime.Now;
entity.CreateUser = userInfo.userId;
var isOk = await _db.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteCommandAsync();
if (!(isOk > 0))
throw NCCException.Oh(ErrorCode.COM1000);
}
#endregion
#region 根据门店批量创建数据
///
/// 根据门店批量创建数据
/// 会删除设置月份的所有门店数据(谨用!!!)
///
/// 月份(YYYYMM格式)
///
[HttpPost("BatchCreateByStores")]
public async Task BatchCreateByStores([FromQuery] string month)
{
var userInfo = await _userManager.GetUserInfo();
if (userInfo == null || string.IsNullOrEmpty(userInfo.userId))
{
throw NCCException.Oh("用户信息获取失败,请重新登录");
}
// 验证月份格式
if (string.IsNullOrEmpty(month) || month.Length != 6 || !Regex.IsMatch(month, @"^\d{6}$"))
{
throw NCCException.Oh("月份格式必须为YYYYMM(如:202501)");
}
//查询门店列表
var storeList = await _db.Queryable().Select(p => p.Id).ToListAsync();
if (storeList == null || storeList.Count == 0)
{
return new { success = true, message = "没有有效的门店数据", createdCount = 0 };
}
// 删除设置月份的所有门店数据
await _db.Deleteable().Where(p => p.Month == month).ExecuteCommandAsync();
// 批量创建
var entities = new List();
foreach (var storeId in storeList)
{
if (string.IsNullOrEmpty(storeId))
continue;
entities.Add(new LqMdTargetEntity
{
Id = YitIdHelper.NextId().ToString(),
StoreId = storeId,
Month = month,
BusinessUnit = "",
TechDepartment = "",
EducationDepartment = "",
MajorProjectDepartment = "",
BusinessUnitTarget = 0,
TechDepartmentTarget = 0,
EducationDepartmentTarget = 0,
BusinessUnitGeneralManager = "",
BusinessUnitManager = "",
StoreTarget = 0,
StoreLifeline = 0,
StoreConsumeTarget = 0,
StoreProjectTarget = 0,
StoreHeadcountTarget = 0,
AssistantHeadcountTargetStage1 = 0,
AssistantHeadcountTargetStage2 = 0,
CreateTime = DateTime.Now,
CreateUser = userInfo.userId,
});
}
if (entities.Count == 0)
{
return new { success = true, message = "没有有效的门店数据可创建", createdCount = 0 };
}
var isOk = await _db.Insertable(entities).ExecuteCommandAsync();
if (!(isOk > 0))
throw NCCException.Oh(ErrorCode.COM1000, "批量创建失败");
return new { success = true, message = $"成功创建{isOk}条记录", createdCount = isOk };
}
#endregion
#region 更新门店目标
///
/// 更新门店目标
///
/// 主键ID
/// 参数
///
[HttpPut("{id}")]
public async Task Update(string id, [FromBody] LqMdTargetUpInput input)
{
var userInfo = await _userManager.GetUserInfo();
// 验证记录是否存在
var entity = await _db.Queryable().FirstAsync(p => p.Id == id);
_ = entity ?? throw NCCException.Oh(ErrorCode.COM1005);
// 验证月份格式
if (input.month.Length != 6 || !Regex.IsMatch(input.month, @"^\d{6}$"))
{
throw NCCException.Oh("月份格式必须为YYYYMM(如:202501)");
}
// 如果门店ID或月份发生变化,需要验证唯一性
if (entity.StoreId != input.storeId || entity.Month != input.month)
{
var exists = await _db.Queryable().Where(p => p.StoreId == input.storeId && p.Month == input.month && p.Id != id).AnyAsync();
if (exists)
{
throw NCCException.Oh("该门店在该月份已存在目标记录");
}
}
var updateEntity = input.Adapt();
updateEntity.Id = id;
updateEntity.UpdateTime = DateTime.Now;
updateEntity.UpdateUser = userInfo.userId;
var isOk = await _db.Updateable(updateEntity).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
if (!(isOk > 0))
throw NCCException.Oh(ErrorCode.COM1001);
}
#endregion
#region 删除门店目标
///
/// 删除门店目标
///
/// 主键ID
///
[HttpDelete("{id}")]
public async Task Delete(string id)
{
var entity = await _db.Queryable().FirstAsync(p => p.Id == id);
_ = entity ?? throw NCCException.Oh(ErrorCode.COM1005);
var isOk = await _db.Deleteable().Where(d => d.Id == id).ExecuteCommandAsync();
if (!(isOk > 0))
throw NCCException.Oh(ErrorCode.COM1002);
}
#endregion
#region 同步上月数据
///
/// 同步上月数据
///
/// 目标月份(YYYYMM格式),如果为空则同步到当前月份
///
[HttpPost("SyncLastMonthData")]
public async Task SyncLastMonthData([FromQuery] string targetMonth = null)
{
var userInfo = await _userManager.GetUserInfo();
// 确定目标月份
string targetMonthStr;
if (string.IsNullOrEmpty(targetMonth))
{
// 如果未指定,使用当前月份
var now = DateTime.Now;
targetMonthStr = now.ToString("yyyyMM");
}
else
{
// 验证月份格式
if (targetMonth.Length != 6 || !Regex.IsMatch(targetMonth, @"^\d{6}$"))
{
throw NCCException.Oh(ErrorCode.COM1000, "月份格式必须为YYYYMM(如:202501)");
}
targetMonthStr = targetMonth;
}
// 计算上个月份
var targetDate = DateTime.ParseExact(targetMonthStr, "yyyyMM", null);
var lastMonthDate = targetDate.AddMonths(-1);
var lastMonthStr = lastMonthDate.ToString("yyyyMM");
// 查询上个月的所有门店目标数据
var lastMonthData = await _db.Queryable()
.Where(p => p.Month == lastMonthStr)
.ToListAsync();
if (lastMonthData == null || lastMonthData.Count == 0)
{
return new
{
success = true,
message = $"上个月({lastMonthStr})没有数据可同步",
syncedCount = 0,
skippedCount = 0
};
}
// 查询目标月份已存在的记录
var existingStoreIds = await _db.Queryable()
.Where(p => p.Month == targetMonthStr)
.Select(p => p.StoreId)
.ToListAsync();
// 过滤掉已存在的门店,只同步新门店
var newEntities = lastMonthData
.Where(p => !existingStoreIds.Contains(p.StoreId))
.Select(p => new LqMdTargetEntity
{
Id = YitIdHelper.NextId().ToString(),
StoreId = p.StoreId,
Month = targetMonthStr,
BusinessUnit = p.BusinessUnit,
TechDepartment = p.TechDepartment,
EducationDepartment = p.EducationDepartment,
MajorProjectDepartment = p.MajorProjectDepartment,
BusinessUnitTarget = p.BusinessUnitTarget,
TechDepartmentTarget = p.TechDepartmentTarget,
EducationDepartmentTarget = p.EducationDepartmentTarget,
BusinessUnitGeneralManager = p.BusinessUnitGeneralManager,
BusinessUnitManager = p.BusinessUnitManager,
StoreTarget = p.StoreTarget,
StoreLifeline = p.StoreLifeline,
StoreConsumeTarget = p.StoreConsumeTarget,
StoreProjectTarget = p.StoreProjectTarget,
StoreHeadcountTarget = p.StoreHeadcountTarget,
AssistantHeadcountTargetStage1 = p.AssistantHeadcountTargetStage1,
AssistantHeadcountTargetStage2 = p.AssistantHeadcountTargetStage2,
CreateTime = DateTime.Now,
CreateUser = userInfo.userId,
})
.ToList();
int syncedCount = 0;
int skippedCount = lastMonthData.Count - newEntities.Count;
if (newEntities.Count > 0)
{
syncedCount = await _db.Insertable(newEntities).ExecuteCommandAsync();
}
return new
{
success = true,
message = $"同步完成:成功同步{syncedCount}条记录,跳过{skippedCount}条已存在的记录",
syncedCount = syncedCount,
skippedCount = skippedCount,
lastMonth = lastMonthStr,
targetMonth = targetMonthStr
};
}
#endregion
#region 获取部门管理的门店列表
///
/// 获取部门管理的门店列表
///
///
/// 根据年月、组织类型、部门ID查询该部门在该月份管理的门店列表
///
/// 示例请求:
/// ```json
/// {
/// "month": "202511",
/// "organizationType": "事业部",
/// "departmentId": "部门ID"
/// }
/// ```
///
/// 参数说明:
/// - month: 年月,格式为YYYYMM(如:202511表示2025年11月)
/// - organizationType: 组织类型,可选值:事业部、科技部、教育部、大项目部
/// - departmentId: 部门ID
///
/// 查询参数
/// 门店列表(包含门店ID和门店名称)
/// 成功返回门店列表
/// 参数错误
[HttpPost("GetManagedStores")]
public async Task GetManagedStores([FromBody] GetManagedStoresInput input)
{
try
{
// 验证参数
if (input == null)
{
throw NCCException.Oh("参数不能为空");
}
if (string.IsNullOrEmpty(input.Month))
{
throw NCCException.Oh("年月不能为空");
}
if (input.Month.Length != 6 || !Regex.IsMatch(input.Month, @"^\d{6}$"))
{
throw NCCException.Oh("年月格式必须为YYYYMM(如:202511)");
}
if (string.IsNullOrEmpty(input.OrganizationType))
{
throw NCCException.Oh("组织类型不能为空");
}
if (string.IsNullOrEmpty(input.DepartmentId))
{
throw NCCException.Oh("部门ID不能为空");
}
// 构建查询条件(使用多表关联方式)
var query = _db.Queryable(
(t, s) => t.StoreId == s.Id)
.Where((t, s) => t.Month == input.Month);
// 根据组织类型添加部门过滤条件
switch (input.OrganizationType)
{
case "事业部":
query = query.Where((t, s) => t.BusinessUnit == input.DepartmentId);
break;
case "科技部":
query = query.Where((t, s) => t.TechDepartment == input.DepartmentId);
break;
case "教育部":
query = query.Where((t, s) => t.EducationDepartment == input.DepartmentId);
break;
case "大项目部":
query = query.Where((t, s) => t.MajorProjectDepartment == input.DepartmentId);
break;
default:
throw NCCException.Oh($"不支持的组织类型:{input.OrganizationType},支持的类型:事业部、科技部、教育部、大项目部");
}
// 关联门店表获取门店名称
var result = await query
.Select((t, s) => new ManagedStoreOutput
{
StoreId = t.StoreId,
StoreName = s.Dm ?? "未知门店"
})
.ToListAsync();
return result;
}
catch (Exception ex)
{
throw NCCException.Oh($"查询失败:{ex.Message}");
}
}
#endregion
}
}