LqMdTargetService.cs 16.2 KB
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
{
    /// <summary>
    /// 门店目标服务
    /// </summary>
    [ApiDescriptionSettings(Tag = "绿纤门店目标服务", Name = "LqMdTarget", Order = 200)]
    [Route("api/Extend/[controller]")]
    public class LqMdTargetService : ILqMdTargetService, IDynamicApiController, ITransient
    {
        private readonly ISqlSugarRepository<LqMdTargetEntity> _lqMdTargetRepository;
        private readonly SqlSugarScope _db;
        private readonly IUserManager _userManager;

        /// <summary>
        /// 初始化一个<see cref="LqMdTargetService"/>类型的新实例
        /// </summary>
        public LqMdTargetService(ISqlSugarRepository<LqMdTargetEntity> lqMdTargetRepository, IUserManager userManager)
        {
            _lqMdTargetRepository = lqMdTargetRepository;
            _db = _lqMdTargetRepository.Context;
            _userManager = userManager;
        }

        #region 获取门店目标信息
        /// <summary>
        /// 获取门店目标信息
        /// </summary>
        /// <param name="id">主键ID</param>
        /// <returns></returns>
        [HttpGet("{id}")]
        public async Task<dynamic> GetInfo(string id)
        {
            var entity = await _db.Queryable<LqMdTargetEntity>().FirstAsync(p => p.Id == id);
            _ = entity ?? throw NCCException.Oh(ErrorCode.COM1005);
            var output = entity.Adapt<LqMdTargetInfoOutput>();
            return output;
        }
        #endregion

        #region 获取门店目标列表
        /// <summary>
        /// 获取门店目标列表
        /// </summary>
        /// <param name="input">请求参数</param>
        /// <returns></returns>
        [HttpGet("")]
        public async Task<dynamic> 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<LqMdTargetEntity>()
                .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<LqMdTargetListOutput>.SqlSugarPageResult(data);
        }
        #endregion

        #region 新建门店目标
        /// <summary>
        /// 新建门店目标
        /// </summary>
        /// <param name="input">参数</param>
        /// <returns></returns>
        [HttpPost("")]
        public async Task Create([FromBody] LqMdTargetCrInput input)
        {
            var userInfo = await _userManager.GetUserInfo();

            // 验证门店ID和月份的唯一性
            var exists = await _db.Queryable<LqMdTargetEntity>().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<LqMdTargetEntity>();
            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 根据门店批量创建数据
        /// <summary>
        /// 根据门店批量创建数据
        /// 会删除设置月份的所有门店数据(谨用!!!)
        /// </summary>
        /// <param name="month">月份(YYYYMM格式)</param>
        /// <returns></returns>
        [HttpPost("BatchCreateByStores")]
        public async Task<dynamic> 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<LqMdxxEntity>().Select(p => p.Id).ToListAsync();

            if (storeList == null || storeList.Count == 0)
            {
                return new { success = true, message = "没有有效的门店数据", createdCount = 0 };
            }

            // 删除设置月份的所有门店数据
            await _db.Deleteable<LqMdTargetEntity>().Where(p => p.Month == month).ExecuteCommandAsync();

            // 批量创建
            var entities = new List<LqMdTargetEntity>();
            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 更新门店目标
        /// <summary>
        /// 更新门店目标
        /// </summary>
        /// <param name="id">主键ID</param>
        /// <param name="input">参数</param>
        /// <returns></returns>
        [HttpPut("{id}")]
        public async Task Update(string id, [FromBody] LqMdTargetUpInput input)
        {
            var userInfo = await _userManager.GetUserInfo();

            // 验证记录是否存在
            var entity = await _db.Queryable<LqMdTargetEntity>().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<LqMdTargetEntity>().Where(p => p.StoreId == input.storeId && p.Month == input.month && p.Id != id).AnyAsync();
                if (exists)
                {
                    throw NCCException.Oh("该门店在该月份已存在目标记录");
                }
            }
            var updateEntity = input.Adapt<LqMdTargetEntity>();
            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 删除门店目标
        /// <summary>
        /// 删除门店目标
        /// </summary>
        /// <param name="id">主键ID</param>
        /// <returns></returns>
        [HttpDelete("{id}")]
        public async Task Delete(string id)
        {
            var entity = await _db.Queryable<LqMdTargetEntity>().FirstAsync(p => p.Id == id);
            _ = entity ?? throw NCCException.Oh(ErrorCode.COM1005);
            var isOk = await _db.Deleteable<LqMdTargetEntity>().Where(d => d.Id == id).ExecuteCommandAsync();
            if (!(isOk > 0))
                throw NCCException.Oh(ErrorCode.COM1002);
        }
        #endregion

        #region 同步上月数据
        /// <summary>
        /// 同步上月数据
        /// </summary>
        /// <param name="targetMonth">目标月份(YYYYMM格式),如果为空则同步到当前月份</param>
        /// <returns></returns>
        [HttpPost("SyncLastMonthData")]
        public async Task<dynamic> 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<LqMdTargetEntity>()
                .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<LqMdTargetEntity>()
                .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
    }
}