LqShareStatisticsTechDeptService.cs 9.88 KB
using Microsoft.AspNetCore.Mvc;
using NCC.Common.Filter;
using NCC.Dependency;
using NCC.DynamicApiController;
using NCC.Extend.Entitys.Dto.LqShareStatisticsTechDept;
using NCC.Extend.Entitys.lq_share_statistics_tech_dept;
using NCC.Extend.Entitys.lq_mdxx;
using NCC.Extend.Entitys.lq_kd_pxmx;
using NCC.Extend.Entitys.lq_kd_kdjlb;
using NCC.Extend.Entitys.lq_hytk_jksyj;
using NCC.Extend.Entitys.lq_xh_jksyj;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Yitter.IdGenerator;

namespace NCC.Extend
{
    /// <summary>
    /// 科技部股份统计服务
    /// </summary>
    [ApiDescriptionSettings(Tag = "科技部股份统计服务", Name = "LqShareStatisticsTechDept", Order = 401)]
    [Route("api/Extend/[controller]")]
    public class LqShareStatisticsTechDeptService : IDynamicApiController, ITransient
    {
        private readonly ISqlSugarClient _db;

        public LqShareStatisticsTechDeptService(ISqlSugarClient db)
        {
            _db = db;
        }

        /// <summary>
        /// 生成科技部股份统计数据
        /// </summary>
        /// <param name="input">生成参数</param>
        /// <returns>生成结果</returns>
        [HttpPost("generate")]
        public async Task<dynamic> GenerateStatistics([FromBody] ShareStatisticsTechDeptGenerateInput input)
        {
            if (string.IsNullOrEmpty(input.StatisticsMonth) || input.StatisticsMonth.Length != 6)
            {
                return new { code = 500, msg = "统计月份格式错误,应为 YYYYMM" };
            }

            var year = int.Parse(input.StatisticsMonth.Substring(0, 4));
            var month = int.Parse(input.StatisticsMonth.Substring(4, 2));
            var startDate = new DateTime(year, month, 1);
            var endDate = startDate.AddMonths(1).AddDays(-1);

            // 确定要生成的部门列表
            var departments = new List<string>();
            if (!string.IsNullOrEmpty(input.DepartmentName))
            {
                departments.Add(input.DepartmentName);
            }
            else
            {
                departments.Add("科技一部");
                departments.Add("科技二部");
            }

            var generatedCount = 0;
            var updatedCount = 0;

            foreach (var deptName in departments)
            {
                // 检查是否已存在
                var existing = await _db.Queryable<LqShareStatisticsTechDeptEntity>()
                    .FirstAsync(x => x.DepartmentName == deptName && x.StatisticsMonth == input.StatisticsMonth);

                var entity = existing ?? new LqShareStatisticsTechDeptEntity
                {
                    Id = YitIdHelper.NextId().ToString(),
                    DepartmentName = deptName,
                    StatisticsMonth = input.StatisticsMonth,
                    IsEffective = 1,
                    CreateTime = DateTime.Now,
                    CreateUser = "System"
                };

                // 计算各项数据
                await CalculateIncome(entity, deptName, startDate, endDate);
                await CalculateCost(entity, deptName, startDate, endDate, input.StatisticsMonth);
                CalculateProfit(entity);

                entity.UpdateTime = DateTime.Now;
                entity.UpdateUser = "System";

                if (existing == null)
                {
                    await _db.Insertable(entity).ExecuteCommandAsync();
                    generatedCount++;
                }
                else
                {
                    await _db.Updateable(entity).ExecuteCommandAsync();
                    updatedCount++;
                }
            }

            return new
            {
                code = 200,
                msg = "生成成功",
                data = new
                {
                    generatedCount,
                    updatedCount,
                    totalCount = departments.Count
                }
            };
        }

        /// <summary>
        /// 查询科技部股份统计列表
        /// </summary>
        /// <param name="input">查询参数</param>
        /// <returns>统计列表</returns>
        [HttpGet("list")]
        public async Task<dynamic> GetList([FromQuery] ShareStatisticsTechDeptQueryInput input)
        {
            var query = _db.Queryable<LqShareStatisticsTechDeptEntity>()
                .Where(x => x.IsEffective == 1);

            if (!string.IsNullOrEmpty(input.StatisticsMonth))
            {
                query = query.Where(x => x.StatisticsMonth == input.StatisticsMonth);
            }

            if (!string.IsNullOrEmpty(input.DepartmentName))
            {
                query = query.Where(x => x.DepartmentName == input.DepartmentName);
            }

            var list = await query.OrderBy(x => x.StatisticsMonth, OrderByType.Desc)
                .OrderBy(x => x.DepartmentName)
                .Select(x => new ShareStatisticsTechDeptOutput
                {
                    Id = x.Id,
                    DepartmentName = x.DepartmentName,
                    StatisticsMonth = x.StatisticsMonth,
                    Income = x.Income,
                    CostReimbursement = x.CostReimbursement,
                    CostTeacherBase = x.CostTeacherBase,
                    CostTeacherManual = x.CostTeacherManual,
                    CostTeacherBillingComm = x.CostTeacherBillingComm,
                    CostTeacherConsumeComm = x.CostTeacherConsumeComm,
                    CostTeacherExpertComm = x.CostTeacherExpertComm,
                    CostTeacherOvertime = x.CostTeacherOvertime,
                    CostGMBase = x.CostGMBase,
                    CostGMComm = x.CostGMComm,
                    RewardTechDept = x.RewardTechDept,
                    CostOther1 = x.CostOther1,
                    CostOther2 = x.CostOther2,
                    Profit = x.Profit,
                    CreateTime = x.CreateTime,
                    UpdateTime = x.UpdateTime
                })
                .ToListAsync();

            return new { code = 200, msg = "查询成功", data = list };
        }

        #region 私有计算方法

        /// <summary>
        /// 计算收入部分
        /// </summary>
        private async Task CalculateIncome(LqShareStatisticsTechDeptEntity entity, string deptName, DateTime startDate, DateTime endDate)
        {
            // 1. 找到该科技部管辖的所有门店
            var stores = await _db.Queryable<LqMdxxEntity>()
                .Where(x => x.Kjb == deptName)
                .Select(x => x.Id)
                .ToListAsync();

            if (stores.Count == 0)
            {
                entity.Income = 0;
                return;
            }

            // 2. 统计这些门店的科美项目开单实付业绩
            // 需要关联 lq_kd_kdjlb 来获取门店信息
            var kemeiIncome = await _db.Queryable<LqKdPxmxEntity, LqKdKdjlbEntity>((px, kd) => new JoinQueryInfos(
                JoinType.Inner, px.Glkdbh == kd.Id))
                .Where((px, kd) => stores.Contains(kd.Djmd) && px.Yjsj >= startDate && px.Yjsj <= endDate && px.IsEffective == 1)
                .Where((px, kd) => px.ItemCategory == "科美")
                .SumAsync((px, kd) => px.TotalPrice);

            // 3. 减去对应的科美项目实退金额
            var kemeiRefund = await _db.Queryable<LqHytkJksyjEntity>()
                .Where(x => stores.Contains(x.StoreId) && x.Tksj >= startDate && x.Tksj <= endDate && x.IsEffective == 1)
                .Where(x => x.ItemCategory == "科美")
                .SumAsync(x => x.Jksyj ?? 0);

            // 4. 结果 * 30%
            entity.Income = (kemeiIncome - kemeiRefund) * 0.3m;
        }

        /// <summary>
        /// 计算成本部分
        /// </summary>
        private async Task CalculateCost(LqShareStatisticsTechDeptEntity entity, string deptName, DateTime startDate, DateTime endDate, string statisticsMonth)
        {
            // 1. 成本-报销 (TODO: 需要确认报销分类的具体判定方式)
            entity.CostReimbursement = 0;

            // 2. 成本-人工-科技部老师底薪 (TODO: 需要确认科技部老师工资表名和字段)
            entity.CostTeacherBase = 0;

            // 3. 成本-人工-科技部手工费
            // 从消耗表中统计科技部老师的手工费
            // TODO: 需要确认如何识别科技部老师
            entity.CostTeacherManual = 0;

            // 4. 成本-人工-科技部开单提成 (TODO: 需要确认字段名)
            entity.CostTeacherBillingComm = 0;

            // 5. 成本-人工-科技部消耗提成 (TODO: 需要确认字段名)
            entity.CostTeacherConsumeComm = 0;

            // 6. 成本-人工-科技部总经理 (TODO: 需要确认科技部总经理工资表)
            entity.CostGMBase = 0;
            entity.CostGMComm = 0;

            // 保留字段
            entity.CostTeacherExpertComm = 0;
            entity.CostTeacherOvertime = 0;
            entity.RewardTechDept = 0;
            entity.CostOther1 = 0;
            entity.CostOther2 = 0;
        }

        /// <summary>
        /// 计算利润
        /// </summary>
        private void CalculateProfit(LqShareStatisticsTechDeptEntity entity)
        {
            // 科技部利润 = 收入 - 成本报销 - 成本人工 - 其他
            var totalCost = entity.CostReimbursement
                + entity.CostTeacherBase
                + entity.CostTeacherManual
                + entity.CostTeacherBillingComm
                + entity.CostTeacherConsumeComm
                + entity.CostTeacherExpertComm
                + entity.CostTeacherOvertime
                + entity.CostGMBase
                + entity.CostGMComm
                + entity.RewardTechDept
                + entity.CostOther1
                + entity.CostOther2;

            entity.Profit = entity.Income - totalCost;
        }

        #endregion
    }
}