diff --git a/generate_salary_html.py b/generate_salary_html.py
deleted file mode 100644
index 34a9519..0000000
--- a/generate_salary_html.py
+++ /dev/null
@@ -1,565 +0,0 @@
-#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
-"""
-生成健康师工资信息说明HTML - 直接使用数据库数据
-"""
-
-def generate_html():
- # 数据直接来自数据库查询结果 - 不做任何计算,只展示
- employees = [
- {
- 'name': '苟小春', 'id': '766260517894358278', 'emp_id': '15828942309',
- 'store': '绿纤468店', 'position': '顾问', 'team': '精英队', 'team_count': 3,
- 'is_new': '否', 'stage': 0,
- 'total_perf': 16526.90, 'base_perf': 9215.00, 'coop_perf': 7311.90,
- 'base_reward': 2000.00, 'coop_reward': 1000.00,
- 'actual_base': 11215.00, 'actual_coop': 6311.90, # 数据库存储值
- 'team_perf': 92548.30, 'percentage': 0.18,
- 'new_cust_perf': 0.00, 'new_cust_rate': 0.00,
- 'upgrade_perf': 0.00, 'upgrade_count': 0,
- 'other_add': 4000.00, 'other_subtract': 0.00,
- 'consumption': 22650.24, 'project_count': 114, 'customer_count': 57,
- 'working_days': 27, 'leave_days': 0,
- 'point': 0.05, 'base_comm': 532.71, 'coop_comm': 194.88,
- 'consultant_comm': 740.39, 'new_cust_comm': 0.00, 'upgrade_comm': 0.00,
- 'total_comm': 1467.98, 'base_salary': 2000, 'handwork': 1583,
- 'actual_salary': 5050.98
- },
- {
- 'name': '李芳', 'id': '766260517806277893', 'emp_id': '18566028067',
- 'store': '绿纤468店', 'position': '健康师', 'team': '精英队', 'team_count': 3,
- 'is_new': '否', 'stage': 0,
- 'total_perf': 35181.30, 'base_perf': 28635.00, 'coop_perf': 6546.30,
- 'base_reward': 0.00, 'coop_reward': 0.00,
- 'actual_base': 28635.00, 'actual_coop': 6546.30, # 数据库存储值
- 'team_perf': 92548.30, 'percentage': 0.38,
- 'new_cust_perf': 0.00, 'new_cust_rate': 0.00,
- 'upgrade_perf': 0.00, 'upgrade_count': 0,
- 'other_add': 0.00, 'other_subtract': 0.00,
- 'consumption': 18341.43, 'project_count': 96, 'customer_count': 50,
- 'working_days': 23, 'leave_days': 7,
- 'point': 0.05, 'base_comm': 1360.16, 'coop_comm': 202.12,
- 'consultant_comm': 0.00, 'new_cust_comm': 0.00, 'upgrade_comm': 0.00,
- 'total_comm': 1562.28, 'base_salary': 2000, 'handwork': 1189,
- 'actual_salary': 4751.28
- },
- {
- 'name': '罗丹', 'id': '766260517810472197', 'emp_id': '13540428522',
- 'store': '绿纤468店', 'position': '健康师', 'team': '精英队', 'team_count': 3,
- 'is_new': '否', 'stage': 0,
- 'total_perf': 40840.10, 'base_perf': 23190.10, 'coop_perf': 17650.00,
- 'base_reward': 0.00, 'coop_reward': 0.00,
- 'actual_base': 23190.10, 'actual_coop': 17650.00, # 数据库存储值
- 'team_perf': 92548.30, 'percentage': 0.44,
- 'new_cust_perf': 0.00, 'new_cust_rate': 0.00,
- 'upgrade_perf': 0.00, 'upgrade_count': 0,
- 'other_add': 0.00, 'other_subtract': 0.00,
- 'consumption': 28095.53, 'project_count': 119, 'customer_count': 64,
- 'working_days': 26, 'leave_days': 4,
- 'point': 0.05, 'base_comm': 1101.53, 'coop_comm': 544.94,
- 'consultant_comm': 0.00, 'new_cust_comm': 0.00, 'upgrade_comm': 0.00,
- 'total_comm': 1646.47, 'base_salary': 2000, 'handwork': 1310,
- 'actual_salary': 4956.47
- },
- {
- 'name': '何玲', 'id': '766260517860803845', 'emp_id': '17628345607',
- 'store': '绿纤金沙店', 'position': '健康师', 'team': '何玲', 'team_count': 1,
- 'is_new': '是', 'stage': 1,
- 'total_perf': 28235.40, 'base_perf': 26318.60, 'coop_perf': 1916.80,
- 'base_reward': 7769.10, 'coop_reward': 84.84,
- 'actual_base': 16897.14, 'actual_coop': 1831.96, # 数据库存储值
- 'team_perf': 28235.40, 'percentage': 1.00,
- 'new_cust_perf': 7679.50, 'new_cust_rate': 0.46,
- 'upgrade_perf': 5771.99, 'upgrade_count': 8,
- 'other_add': 6189.21, 'other_subtract': 162.07,
- 'consumption': 4199.07, 'project_count': 89.50, 'customer_count': 53,
- 'working_days': 27, 'leave_days': 0,
- 'point': 0.04, 'base_comm': 642.09, 'coop_comm': 45.25,
- 'consultant_comm': 0.00, 'new_cust_comm': 1151.93, 'upgrade_comm': 0.00,
- 'total_comm': 1839.27, 'base_salary': 2000, 'handwork': 1114,
- 'actual_salary': 4953.27
- },
- {
- 'name': '汤倩', 'id': '766260517814667397', 'emp_id': '751340541496526085',
- 'store': '绿纤荣华南路店', 'position': '健康师', 'team': '个人', 'team_count': 1,
- 'is_new': '否', 'stage': 0,
- 'total_perf': 5373.70, 'base_perf': 3085.20, 'coop_perf': 2288.50,
- 'base_reward': 0.00, 'coop_reward': 0.00,
- 'actual_base': 3085.20, 'actual_coop': 2288.50, # 数据库存储值
- 'team_perf': 5373.70, 'percentage': 1.00,
- 'new_cust_perf': 0.00, 'new_cust_rate': 0.00,
- 'upgrade_perf': 0.00, 'upgrade_count': 0,
- 'other_add': 0.00, 'other_subtract': 0.00,
- 'consumption': 10102.27, 'project_count': 72, 'customer_count': 59,
- 'working_days': 19, 'leave_days': 0,
- 'point': 0.00, 'base_comm': 0.00, 'coop_comm': 0.00,
- 'consultant_comm': 0.00, 'new_cust_comm': 0.00, 'upgrade_comm': 0.00,
- 'total_comm': 0.00, 'base_salary': 2000, 'handwork': 880,
- 'actual_salary': 2880.00
- }
- ]
-
- html_parts = []
-
- # HTML头部
- html_parts.append('''
-
-
-
-
- 绿纤美业 - 健康师工资信息说明
-
-
-
-
-
健康师工资信息说明 (2025年11月)
-''')
-
- # 为每个员工生成HTML
- for emp in employees:
- html_parts.append(generate_employee_card(emp))
-
- # HTML尾部
- html_parts.append('''
-
-''')
-
- return '\n'.join(html_parts)
-
-
-def generate_employee_card(emp):
- """生成单个员工的工资卡片 - 使用数据库实际值"""
-
- # 确定卡片颜色
- if emp['is_new'] == '是':
- header_color = '#2ecc71'
- subtitle = f"(新店第{emp['stage']}阶段)"
- elif emp['working_days'] < 21:
- header_color = '#f39c12'
- subtitle = '(出勤不足)'
- elif emp['position'] == '顾问':
- header_color = '#007bff'
- subtitle = '(顾问)'
- else:
- header_color = '#007bff'
- subtitle = '(健康师)'
-
- card_html = f'''
-
-
-
-
-
-
-
基本信息
-
-
姓名:{emp['name']}
-
门店:{emp['store']}
-
员工ID:{emp['emp_id']}
-
统计月份:202511
-
岗位:{emp['position']}
-
金三角战队:{emp['team']} ({emp['team_count']}人)
-
是否新店:{emp['is_new']}
-
新店保护阶段:{emp['stage']}
-
-
-
-
-
业绩数据
-
-
总业绩:{emp['total_perf']:,.2f}
-
基础业绩:{emp['base_perf']:,.2f}
-
合作业绩:{emp['coop_perf']:,.2f}
-
基础奖励业绩:{emp['base_reward']:,.2f}
-
合作奖励业绩:{emp['coop_reward']:,.2f}
-
其他业绩加:{emp['other_add']:,.2f}
-
其他业绩减:{emp['other_subtract']:,.2f}
-
队伍业绩:{emp['team_perf']:,.2f}
-
占比:{emp['percentage']:.2f}
-
新客业绩:{emp['new_cust_perf']:,.2f}
-
新客转化率:{emp['new_cust_rate']:.2f}
-
升单业绩:{emp['upgrade_perf']:,.2f}
-
升单人头数:{emp['upgrade_count']:.0f}
-
实际基础业绩:{emp['actual_base']:,.2f}
-
实际合作业绩:{emp['actual_coop']:,.2f}
-
-
-
-
-
消耗与项目数据
-
-
消耗:{emp['consumption']:,.2f}
-
项目数:{emp['project_count']:,.2f}
-
到店人头:{emp['customer_count']:.0f}
-
-
-
-
-
考勤数据
-
-
在店天数:{emp['working_days']:.0f}
-
请假天数:{emp['leave_days']:.0f}
-
迟到次数:0.00
-
缺卡次数:0.00
-
-
-
-
-
提成计算
-
-
提点:{emp['point']:.2f}
-
基础业绩提成:{emp['base_comm']:,.2f}
-
合作业绩提成:{emp['coop_comm']:,.2f}
-
顾问提成:{emp['consultant_comm']:,.2f}
-
新客业绩提成:{emp['new_cust_comm']:,.2f}
-
升单业绩提成:{emp['upgrade_comm']:,.2f}
-
提成合计:{emp['total_comm']:,.2f}
-
-
-
-
-
底薪与补贴
-
-
健康师底薪:{emp['base_salary']:,.2f}
-
手工费:{emp['handwork']:,.2f}
-
额外手工费:0.00
-
车补:0.00
-
少休费:0.00
-
全勤奖:0.00
-
-
-
-
-
- 实发工资
- {emp['actual_salary']:,.2f}
-
-
-
-
- {generate_calculation_details(emp)}
-
-'''
- return card_html
-
-
-def generate_calculation_details(emp):
- """生成计算过程说明 - 基于数据库实际值"""
-
- details_html = '\n'
- details_html += '
计算过程说明
\n'
-
- step_num = 1
-
- # 提成点计算说明
- if emp['point'] > 0:
- point_rule = get_commission_point_rule(emp['team_count'], emp['team_perf'])
- details_html += f'''
-
{step_num}. 提成点 ({emp['point']:.0%})
-
战队人数({emp['team_count']}人) + 战队业绩({emp['team_perf']:,.2f}) → {point_rule}
-
根据提成点表查询得出
-
-'''
- step_num += 1
- else:
- details_html += f'''
-
{step_num}. 提成资格判定
-
出勤{emp['working_days']:.0f}天 < 21天 → 无提成资格
-
出勤不足21天,所有提成归零
-
-'''
- step_num += 1
-
- # 实际业绩计算说明
- if emp['base_reward'] > 0 or emp['other_add'] > 0 or emp['other_subtract'] > 0 or emp['new_cust_perf'] > 0:
- details_html += f'''
-
{step_num}. 实际基础业绩计算
-
{emp['base_perf']:,.2f} - {emp['base_reward']:,.2f} + {emp['other_add']:,.2f} - {emp['other_subtract']:,.2f} - {emp['new_cust_perf']:,.2f} = {emp['actual_base']:,.2f}
-
基础业绩 - 基础奖励业绩 + 其他业绩加 - 其他业绩减 - 新客业绩
-
-'''
- step_num += 1
-
- if emp['coop_reward'] > 0:
- details_html += f'''
-
{step_num}. 实际合作业绩计算
-
{emp['coop_perf']:,.2f} - {emp['coop_reward']:,.2f} = {emp['actual_coop']:,.2f}
-
合作业绩 - 合作奖励业绩
-
-'''
- step_num += 1
-
- # 基础业绩提成
- if emp['base_comm'] > 0:
- details_html += f'''
-
{step_num}. 基础业绩提成 ({emp['base_comm']:,.2f})
-
{emp['actual_base']:,.2f} × 0.95 × {emp['point']:.0%} = {emp['base_comm']:,.2f}
-
实际基础业绩 × 95% × 提成点
-
-'''
- step_num += 1
-
- # 合作业绩提成
- if emp['coop_comm'] > 0:
- details_html += f'''
-
{step_num}. 合作业绩提成 ({emp['coop_comm']:,.2f})
-
{emp['actual_coop']:,.2f} × 0.95 × 0.65 × {emp['point']:.0%} = {emp['coop_comm']:,.2f}
-
实际合作业绩 × 95% × 65% × 提成点
-
-'''
- step_num += 1
-
- # 顾问提成
- if emp['consultant_comm'] > 0:
- consultant_rule = get_consultant_commission_rule(emp['team_perf'], emp['consumption'], emp['is_new'])
- details_html += f'''
-
{step_num}. 顾问提成 ({emp['consultant_comm']:,.2f})
-
{emp['team_perf']:,.2f} × 0.8% = {emp['consultant_comm']:,.2f}
-
{consultant_rule}
-
-'''
- step_num += 1
-
- # 新客转化率提成
- if emp['new_cust_comm'] > 0:
- new_cust_rate = get_new_customer_commission_rate(emp['new_cust_rate'])
- details_html += f'''
-
{step_num}. 新客转化率提成 ({emp['new_cust_comm']:,.2f})
-
{emp['new_cust_perf']:,.2f} × {new_cust_rate:.0%} = {emp['new_cust_comm']:,.2f}
-
新客业绩 × 转化率提成比例({emp['new_cust_rate']:.0%} → {new_cust_rate:.0%})
-
-'''
- step_num += 1
-
- # 实发工资
- details_html += f'''
-
{step_num}. 实发工资 ({emp['actual_salary']:,.2f})
-
{emp['base_salary']:,.2f} + {emp['total_comm']:,.2f} + {emp['handwork']:,.2f} = {emp['actual_salary']:,.2f}
-
底薪 + 提成合计 + 手工费
-
-'''
-
- details_html += '
\n'
- return details_html
-
-
-def get_commission_point_rule(team_count, team_perf):
- """获取提成点规则说明"""
- if team_count >= 3:
- if team_perf >= 150000:
- return "查表得7% (3人以上,业绩≥15万)"
- elif team_perf >= 120000:
- return "查表得6% (3人以上,业绩≥12万)"
- elif team_perf >= 90000:
- return "查表得5% (3人以上,业绩≥9万)"
- elif team_perf >= 60000:
- return "查表得4% (3人以上,业绩≥6万)"
- elif team_perf >= 30000:
- return "查表得3% (3人以上,业绩≥3万)"
- elif team_count == 2:
- if team_perf >= 80000:
- return "查表得6% (2人,业绩≥8万)"
- elif team_perf >= 60000:
- return "查表得5% (2人,业绩≥6万)"
- elif team_perf >= 40000:
- return "查表得4% (2人,业绩≥4万)"
- elif team_perf >= 20000:
- return "查表得3% (2人,业绩≥2万)"
- else: # 1人
- if team_perf >= 60000:
- return "查表得6% (1人,业绩≥6万)"
- elif team_perf >= 40000:
- return "查表得5% (1人,业绩≥4万)"
- elif team_perf >= 20000:
- return "查表得4% (1人,业绩≥2万)"
- elif team_perf >= 10000:
- return "查表得3% (1人,业绩≥1万)"
- return "查表得0% (未达标)"
-
-
-def get_consultant_commission_rule(team_perf, consumption, is_new):
- """获取顾问提成规则说明"""
- if team_perf >= 60000:
- if is_new == '是' or consumption >= 60000:
- return f"高级顾问: 战队业绩≥6万 且 消耗≥6万(或新店) → 提成0.8%"
- if team_perf >= 40000:
- if is_new == '是' or consumption >= 40000:
- return f"普通顾问: 战队业绩≥4万 且 消耗≥4万(或新店) → 提成0.3%"
- return "未达顾问提成标准"
-
-
-def get_new_customer_commission_rate(conversion_rate):
- """获取新客转化率提成比例"""
- if conversion_rate >= 0.5:
- return 0.20
- elif conversion_rate >= 0.45:
- return 0.15
- elif conversion_rate >= 0.35:
- return 0.10
- elif conversion_rate > 0:
- return 0.06
- return 0
-
-
-if __name__ == '__main__':
- html_content = generate_html()
-
- # 写入文件
- with open('健康师工资信息说明.html', 'w', encoding='utf-8') as f:
- f.write(html_content)
-
- print("HTML文件已生成: 健康师工资信息说明.html")
- print("\n数据验证:")
- print("- 苟小春: 基础业绩=9,215.00, 基础奖励=2,000.00, 实际基础业绩=11,215.00 ✓")
- print("- 苟小春: 合作业绩=7,311.90, 合作奖励=1,000.00, 实际合作业绩=6,311.90 ✓")
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqAssistantSalary/AssistantSalaryInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqAssistantSalary/AssistantSalaryInput.cs
new file mode 100644
index 0000000..2fbcadb
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqAssistantSalary/AssistantSalaryInput.cs
@@ -0,0 +1,32 @@
+using NCC.Common.Filter;
+using System;
+
+namespace NCC.Extend.Entitys.Dto.LqAssistantSalary
+{
+ ///
+ /// 店助工资查询参数
+ ///
+ public class AssistantSalaryInput : PageInputBase
+ {
+ ///
+ /// 年份
+ ///
+ public int Year { get; set; }
+
+ ///
+ /// 月份
+ ///
+ public int Month { get; set; }
+
+ ///
+ /// 门店ID(可选,用于筛选特定门店)
+ ///
+ public string StoreId { get; set; }
+
+ ///
+ /// 员工姓名/账号(可选,用于模糊搜索)
+ ///
+ public string Keyword { get; set; }
+ }
+}
+
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqAssistantSalary/AssistantSalaryOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqAssistantSalary/AssistantSalaryOutput.cs
new file mode 100644
index 0000000..ab75df1
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqAssistantSalary/AssistantSalaryOutput.cs
@@ -0,0 +1,216 @@
+using System;
+
+namespace NCC.Extend.Entitys.Dto.LqAssistantSalary
+{
+ ///
+ /// 店助工资输出
+ ///
+ public class AssistantSalaryOutput
+ {
+ ///
+ /// 主键ID
+ ///
+ public string Id { get; set; }
+
+ ///
+ /// 门店名称
+ ///
+ public string StoreName { get; set; }
+
+ ///
+ /// 员工姓名
+ ///
+ public string EmployeeName { get; set; }
+
+ ///
+ /// 岗位
+ ///
+ public string Position { get; set; }
+
+ ///
+ /// 门店总业绩
+ ///
+ public decimal StoreTotalPerformance { get; set; }
+
+ ///
+ /// 门店开单业绩
+ ///
+ public decimal StoreBillingPerformance { get; set; }
+
+ ///
+ /// 门店退卡业绩
+ ///
+ public decimal StoreRefundPerformance { get; set; }
+
+ ///
+ /// 门店生命线
+ ///
+ public decimal StoreLifeline { get; set; }
+
+ ///
+ /// 业绩完成率
+ ///
+ public decimal PerformanceCompletionRate { get; set; }
+
+ ///
+ /// 提成比例
+ ///
+ public decimal CommissionRate { get; set; }
+
+ ///
+ /// 提成金额
+ ///
+ public decimal CommissionAmount { get; set; }
+
+ ///
+ /// 进店消耗人数
+ ///
+ public int HeadCount { get; set; }
+
+ ///
+ /// 第一阶段目标人数
+ ///
+ public int Stage1TargetHeadCount { get; set; }
+
+ ///
+ /// 第二阶段目标人数
+ ///
+ public int Stage2TargetHeadCount { get; set; }
+
+ ///
+ /// 是否达到第一阶段
+ ///
+ public string ReachedStage1 { get; set; }
+
+ ///
+ /// 是否达到第二阶段
+ ///
+ public string ReachedStage2 { get; set; }
+
+ ///
+ /// 阶段奖励金额
+ ///
+ public decimal StageRewardAmount { get; set; }
+
+ ///
+ /// 第一阶段奖励
+ ///
+ public decimal Stage1Reward { get; set; }
+
+ ///
+ /// 第二阶段奖励
+ ///
+ public decimal Stage2Reward { get; set; }
+
+ ///
+ /// 底薪金额
+ ///
+ public decimal BaseSalary { get; set; }
+
+ ///
+ /// 手机管理费
+ ///
+ public decimal PhoneManagementFee { get; set; }
+
+ ///
+ /// 在店天数
+ ///
+ public int WorkingDays { get; set; }
+
+ ///
+ /// 请假天数
+ ///
+ public int LeaveDays { get; set; }
+
+ ///
+ /// 应发工资
+ ///
+ public decimal GrossSalary { get; set; }
+
+ ///
+ /// 实发工资
+ ///
+ public decimal ActualSalary { get; set; }
+
+ ///
+ /// 扣款合计
+ ///
+ public decimal TotalDeduction { get; set; }
+
+ ///
+ /// 补贴合计
+ ///
+ public decimal TotalSubsidy { get; set; }
+
+ ///
+ /// 发奖金
+ ///
+ public decimal Bonus { get; set; }
+
+ ///
+ /// 退手机押金
+ ///
+ public decimal ReturnPhoneDeposit { get; set; }
+
+ ///
+ /// 退住宿押金
+ ///
+ public decimal ReturnAccommodationDeposit { get; set; }
+
+ ///
+ /// 当月是否发放
+ ///
+ public string MonthlyPaymentStatus { get; set; }
+
+ ///
+ /// 支付金额
+ ///
+ public decimal PaidAmount { get; set; }
+
+ ///
+ /// 待支付金额
+ ///
+ public decimal PendingAmount { get; set; }
+
+ ///
+ /// 补发上月
+ ///
+ public decimal LastMonthSupplement { get; set; }
+
+ ///
+ /// 当月支付总额
+ ///
+ public decimal MonthlyTotalPayment { get; set; }
+
+ ///
+ /// 是否锁定
+ ///
+ public int IsLocked { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ public DateTime UpdateTime { get; set; }
+
+ ///
+ /// 门店类型
+ ///
+ public int? StoreType { get; set; }
+
+ ///
+ /// 门店类别
+ ///
+ public int? StoreCategory { get; set; }
+
+ ///
+ /// 是否新店
+ ///
+ public string IsNewStore { get; set; }
+
+ ///
+ /// 新店保护阶段
+ ///
+ public int NewStoreProtectionStage { get; set; }
+ }
+}
+
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqDirectorSalary/DirectorSalaryInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqDirectorSalary/DirectorSalaryInput.cs
new file mode 100644
index 0000000..e463c86
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqDirectorSalary/DirectorSalaryInput.cs
@@ -0,0 +1,32 @@
+using NCC.Common.Filter;
+using System;
+
+namespace NCC.Extend.Entitys.Dto.LqDirectorSalary
+{
+ ///
+ /// 主任工资查询参数
+ ///
+ public class DirectorSalaryInput : PageInputBase
+ {
+ ///
+ /// 年份
+ ///
+ public int Year { get; set; }
+
+ ///
+ /// 月份
+ ///
+ public int Month { get; set; }
+
+ ///
+ /// 门店ID(可选,用于筛选特定门店)
+ ///
+ public string StoreId { get; set; }
+
+ ///
+ /// 员工姓名/账号(可选,用于模糊搜索)
+ ///
+ public string Keyword { get; set; }
+ }
+}
+
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqDirectorSalary/DirectorSalaryOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqDirectorSalary/DirectorSalaryOutput.cs
new file mode 100644
index 0000000..a6a8ca1
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqDirectorSalary/DirectorSalaryOutput.cs
@@ -0,0 +1,236 @@
+using System;
+
+namespace NCC.Extend.Entitys.Dto.LqDirectorSalary
+{
+ ///
+ /// 主任工资输出
+ ///
+ public class DirectorSalaryOutput
+ {
+ ///
+ /// 主键ID
+ ///
+ public string Id { get; set; }
+
+ ///
+ /// 门店名称
+ ///
+ public string StoreName { get; set; }
+
+ ///
+ /// 员工姓名
+ ///
+ public string EmployeeName { get; set; }
+
+ ///
+ /// 岗位
+ ///
+ public string Position { get; set; }
+
+ ///
+ /// 门店总业绩
+ ///
+ public decimal StoreTotalPerformance { get; set; }
+
+ ///
+ /// 门店开单业绩
+ ///
+ public decimal StoreBillingPerformance { get; set; }
+
+ ///
+ /// 门店退卡业绩
+ ///
+ public decimal StoreRefundPerformance { get; set; }
+
+ ///
+ /// 门店生命线
+ ///
+ public decimal StoreLifeline { get; set; }
+
+ ///
+ /// 业绩完成率
+ ///
+ public decimal PerformanceCompletionRate { get; set; }
+
+ ///
+ /// 业绩是否达标
+ ///
+ public string PerformanceReached { get; set; }
+
+ ///
+ /// 人头是否达标
+ ///
+ public string HeadCountReached { get; set; }
+
+ ///
+ /// 消耗是否达标
+ ///
+ public string ConsumeReached { get; set; }
+
+ ///
+ /// 考核扣款金额
+ ///
+ public decimal AssessmentDeduction { get; set; }
+
+ ///
+ /// 未达标指标数量
+ ///
+ public int UnreachedIndicatorCount { get; set; }
+
+ ///
+ /// 进店消耗人数
+ ///
+ public int HeadCount { get; set; }
+
+ ///
+ /// 目标人头数
+ ///
+ public decimal TargetHeadCount { get; set; }
+
+ ///
+ /// 门店消耗金额
+ ///
+ public decimal StoreConsume { get; set; }
+
+ ///
+ /// 目标消耗金额
+ ///
+ public decimal TargetConsume { get; set; }
+
+ ///
+ /// ≤生命线部分提成比例
+ ///
+ public decimal CommissionRateBelowLifeline { get; set; }
+
+ ///
+ /// >生命线部分提成比例
+ ///
+ public decimal CommissionRateAboveLifeline { get; set; }
+
+ ///
+ /// ≤生命线部分提成金额
+ ///
+ public decimal CommissionAmountBelowLifeline { get; set; }
+
+ ///
+ /// >生命线部分提成金额
+ ///
+ public decimal CommissionAmountAboveLifeline { get; set; }
+
+ ///
+ /// 提成总金额
+ ///
+ public decimal TotalCommissionAmount { get; set; }
+
+ ///
+ /// 底薪金额
+ ///
+ public decimal BaseSalary { get; set; }
+
+ ///
+ /// 实际底薪
+ ///
+ public decimal ActualBaseSalary { get; set; }
+
+ ///
+ /// 在店天数
+ ///
+ public int WorkingDays { get; set; }
+
+ ///
+ /// 请假天数
+ ///
+ public int LeaveDays { get; set; }
+
+ ///
+ /// 应发工资
+ ///
+ public decimal GrossSalary { get; set; }
+
+ ///
+ /// 实发工资
+ ///
+ public decimal ActualSalary { get; set; }
+
+ ///
+ /// 扣款合计
+ ///
+ public decimal TotalDeduction { get; set; }
+
+ ///
+ /// 补贴合计
+ ///
+ public decimal TotalSubsidy { get; set; }
+
+ ///
+ /// 发奖金
+ ///
+ public decimal Bonus { get; set; }
+
+ ///
+ /// 退手机押金
+ ///
+ public decimal ReturnPhoneDeposit { get; set; }
+
+ ///
+ /// 退住宿押金
+ ///
+ public decimal ReturnAccommodationDeposit { get; set; }
+
+ ///
+ /// 当月是否发放
+ ///
+ public string MonthlyPaymentStatus { get; set; }
+
+ ///
+ /// 支付金额
+ ///
+ public decimal PaidAmount { get; set; }
+
+ ///
+ /// 待支付金额
+ ///
+ public decimal PendingAmount { get; set; }
+
+ ///
+ /// 补发上月
+ ///
+ public decimal LastMonthSupplement { get; set; }
+
+ ///
+ /// 当月支付总额
+ ///
+ public decimal MonthlyTotalPayment { get; set; }
+
+ ///
+ /// 是否锁定
+ ///
+ public int IsLocked { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ public DateTime UpdateTime { get; set; }
+
+ ///
+ /// 门店类型
+ ///
+ public int? StoreType { get; set; }
+
+ ///
+ /// 门店类别
+ ///
+ public int? StoreCategory { get; set; }
+
+ ///
+ /// 是否新店
+ ///
+ public string IsNewStore { get; set; }
+
+ ///
+ /// 新店保护阶段
+ ///
+ public int NewStoreProtectionStage { get; set; }
+ }
+}
+
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqReimbursementApplicationCrInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqReimbursementApplicationCrInput.cs
index ca53669..ef85e65 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqReimbursementApplicationCrInput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqReimbursementApplicationCrInput.cs
@@ -12,56 +12,91 @@ namespace NCC.Extend.Entitys.Dto.LqReimbursementApplication
/// 申请编号
///
public string id { get; set; }
-
+
///
/// 申请人编号
///
public string applicationUserId { get; set; }
-
+
///
/// 申请人姓名
///
public string applicationUserName { get; set; }
-
+
///
/// 申请门店
///
public string applicationStoreId { get; set; }
-
+
///
/// 申请时间
///
public DateTime? applicationTime { get; set; }
-
+
///
/// 总金额
///
public string amount { get; set; }
-
+
///
/// 审批人
///
public string approveUser { get; set; }
-
+
///
/// 审批结果
///
public string approveStatus { get; set; }
-
+
///
/// 审批时间
///
public DateTime? approveTime { get; set; }
-
+
///
/// 关联购买编号
///
public string purchaseRecordsId { get; set; }
-
+
///
/// 选中的购买记录ID列表(用于更新购买记录的审批单编号)
///
public List selectedPurchaseRecordIds { get; set; }
-
+
+ ///
+ /// 节点配置列表(3-5个节点)
+ ///
+ public List nodes { get; set; }
+ }
+
+ ///
+ /// 审批节点配置
+ ///
+ public class ApprovalNodeConfig
+ {
+ ///
+ /// 节点顺序(1, 2, 3, 4, 5)
+ ///
+ public int nodeOrder { get; set; }
+
+ ///
+ /// 节点名称(如:部门经理审批、财务审批等)
+ ///
+ public string nodeName { get; set; }
+
+ ///
+ /// 审批类型(会签/或签)
+ ///
+ public string approvalType { get; set; }
+
+ ///
+ /// 审批人ID列表(可多选)
+ ///
+ public List approverIds { get; set; }
+
+ ///
+ /// 审批人姓名列表(用于显示)
+ ///
+ public List approverNames { get; set; }
}
}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqReimbursementApplicationListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqReimbursementApplicationListOutput.cs
index ccc6243..2d190ad 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqReimbursementApplicationListOutput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqReimbursementApplicationListOutput.cs
@@ -56,6 +56,21 @@ namespace NCC.Extend.Entitys.Dto.LqReimbursementApplication
/// 关联购买编号
///
public string purchaseRecordsId { get; set; }
+
+ ///
+ /// 当前审批人(多个用逗号分隔)
+ ///
+ public string currentApprovers { get; set; }
+
+ ///
+ /// 当前节点顺序
+ ///
+ public int? currentNodeOrder { get; set; }
+
+ ///
+ /// 节点总数
+ ///
+ public int? nodeCount { get; set; }
}
}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqSalary/HealthCoachSalaryOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqSalary/HealthCoachSalaryOutput.cs
index 97799c9..aadbbbb 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqSalary/HealthCoachSalaryOutput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqSalary/HealthCoachSalaryOutput.cs
@@ -181,5 +181,270 @@ namespace NCC.Extend.Entitys.Dto.LqSalary
/// 升单提点
///
public decimal UpgradePoint { get; set; }
+
+ ///
+ /// 基础奖励业绩
+ ///
+ public decimal BaseRewardPerformance { get; set; }
+
+ ///
+ /// 合作奖励业绩
+ ///
+ public decimal CooperationRewardPerformance { get; set; }
+
+ ///
+ /// 日均消耗
+ ///
+ public decimal DailyAverageConsumption { get; set; }
+
+ ///
+ /// 日均项目数
+ ///
+ public decimal DailyAverageProjectCount { get; set; }
+
+ ///
+ /// 战队总消耗
+ ///
+ public decimal TeamTotalConsumption { get; set; }
+
+ ///
+ /// 门店ID
+ ///
+ public string StoreId { get; set; }
+
+ ///
+ /// 员工ID
+ ///
+ public string EmployeeId { get; set; }
+
+ ///
+ /// 金三角ID
+ ///
+ public string GoldTriangleId { get; set; }
+
+ ///
+ /// 门店总业绩
+ ///
+ public decimal StoreTotalPerformance { get; set; }
+
+ ///
+ /// 队伍业绩
+ ///
+ public decimal TeamPerformance { get; set; }
+
+ ///
+ /// 占比
+ ///
+ public decimal Percentage { get; set; }
+
+ ///
+ /// 其他业绩加
+ ///
+ public decimal OtherPerformanceAdd { get; set; }
+
+ ///
+ /// 其他业绩减
+ ///
+ public decimal OtherPerformanceSubtract { get; set; }
+
+ ///
+ /// 请假天数
+ ///
+ public decimal LeaveDays { get; set; }
+
+ ///
+ /// 提点
+ ///
+ public decimal CommissionPoint { get; set; }
+
+ ///
+ /// 基础业绩提成
+ ///
+ public decimal BasePerformanceCommission { get; set; }
+
+ ///
+ /// 合作业绩提成
+ ///
+ public decimal CooperationPerformanceCommission { get; set; }
+
+ ///
+ /// 顾问提成
+ ///
+ public decimal ConsultantCommission { get; set; }
+
+ ///
+ /// 门店T区提成
+ ///
+ public decimal StoreTZoneCommission { get; set; }
+
+ ///
+ /// 额外手工费
+ ///
+ public decimal OutherHandworkFee { get; set; }
+
+ ///
+ /// 车补
+ ///
+ public decimal TransportationAllowance { get; set; }
+
+ ///
+ /// 少休费
+ ///
+ public decimal LessRest { get; set; }
+
+ ///
+ /// 全勤奖
+ ///
+ public decimal FullAttendance { get; set; }
+
+ ///
+ /// 核算应发工资
+ ///
+ public decimal CalculatedGrossSalary { get; set; }
+
+ ///
+ /// 保底工资
+ ///
+ public decimal GuaranteedSalary { get; set; }
+
+ ///
+ /// 保底请假扣款
+ ///
+ public decimal GuaranteedLeaveDeduction { get; set; }
+
+ ///
+ /// 保底底薪
+ ///
+ public decimal GuaranteedBaseSalary { get; set; }
+
+ ///
+ /// 保底补差
+ ///
+ public decimal GuaranteedSupplement { get; set; }
+
+ ///
+ /// 最终应发工资
+ ///
+ public decimal FinalGrossSalary { get; set; }
+
+ ///
+ /// 当月培训补贴
+ ///
+ public decimal MonthlyTrainingSubsidy { get; set; }
+
+ ///
+ /// 当月交通补贴
+ ///
+ public decimal MonthlyTransportSubsidy { get; set; }
+
+ ///
+ /// 上月培训补贴
+ ///
+ public decimal LastMonthTrainingSubsidy { get; set; }
+
+ ///
+ /// 上月交通补贴
+ ///
+ public decimal LastMonthTransportSubsidy { get; set; }
+
+ ///
+ /// 缺卡扣款
+ ///
+ public decimal MissingCard { get; set; }
+
+ ///
+ /// 迟到扣款
+ ///
+ public decimal LateArrival { get; set; }
+
+ ///
+ /// 请假扣款
+ ///
+ public decimal LeaveDeduction { get; set; }
+
+ ///
+ /// 扣社保
+ ///
+ public decimal SocialInsuranceDeduction { get; set; }
+
+ ///
+ /// 扣除奖励
+ ///
+ public decimal RewardDeduction { get; set; }
+
+ ///
+ /// 扣住宿费
+ ///
+ public decimal AccommodationDeduction { get; set; }
+
+ ///
+ /// 扣学习期费用
+ ///
+ public decimal StudyPeriodDeduction { get; set; }
+
+ ///
+ /// 扣工作服费用
+ ///
+ public decimal WorkClothesDeduction { get; set; }
+
+ ///
+ /// 发奖金
+ ///
+ public decimal Bonus { get; set; }
+
+ ///
+ /// 退手机押金
+ ///
+ public decimal ReturnPhoneDeposit { get; set; }
+
+ ///
+ /// 退住宿押金
+ ///
+ public decimal ReturnAccommodationDeposit { get; set; }
+
+ ///
+ /// 当月是否发放
+ ///
+ public string MonthlyPaymentStatus { get; set; }
+
+ ///
+ /// 支付金额
+ ///
+ public decimal PaidAmount { get; set; }
+
+ ///
+ /// 待支付金额
+ ///
+ public decimal PendingAmount { get; set; }
+
+ ///
+ /// 补发上月
+ ///
+ public decimal LastMonthSupplement { get; set; }
+
+ ///
+ /// 当月支付总额
+ ///
+ public decimal MonthlyTotalPayment { get; set; }
+
+ ///
+ /// 统计月份(YYYYMM)
+ ///
+ public string StatisticsMonth { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ public DateTime CreateTime { get; set; }
+
+ ///
+ /// 创建人
+ ///
+ public string CreateUser { get; set; }
+
+ ///
+ /// 更新人
+ ///
+ public string UpdateUser { get; set; }
}
}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/LqReimbursementApplicationEntity.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/LqReimbursementApplicationEntity.cs
index 201fcac..a220086 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/LqReimbursementApplicationEntity.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/LqReimbursementApplicationEntity.cs
@@ -16,60 +16,96 @@ namespace NCC.Extend.Entitys
///
[SugarColumn(ColumnName = "F_Id", IsPrimaryKey = true)]
public string Id { get; set; }
-
+
///
/// 申请人编号
///
- [SugarColumn(ColumnName = "F_ApplicationUserId")]
+ [SugarColumn(ColumnName = "F_ApplicationUserId")]
public string ApplicationUserId { get; set; }
-
+
///
/// 申请人姓名
///
- [SugarColumn(ColumnName = "F_ApplicationUserName")]
+ [SugarColumn(ColumnName = "F_ApplicationUserName")]
public string ApplicationUserName { get; set; }
-
+
///
/// 申请门店
///
- [SugarColumn(ColumnName = "F_ApplicationStoreId")]
+ [SugarColumn(ColumnName = "F_ApplicationStoreId")]
public string ApplicationStoreId { get; set; }
-
+
///
/// 申请时间
///
- [SugarColumn(ColumnName = "F_ApplicationTime")]
+ [SugarColumn(ColumnName = "F_ApplicationTime")]
public DateTime? ApplicationTime { get; set; }
-
+
///
/// 总金额
///
- [SugarColumn(ColumnName = "F_Amount")]
+ [SugarColumn(ColumnName = "F_Amount")]
public string Amount { get; set; }
-
+
///
/// 审批人
///
- [SugarColumn(ColumnName = "F_ApproveUser")]
+ [SugarColumn(ColumnName = "F_ApproveUser")]
public string ApproveUser { get; set; }
-
+
///
/// 审批结果
///
- [SugarColumn(ColumnName = "F_ApproveStatus")]
+ [SugarColumn(ColumnName = "F_ApproveStatus")]
public string ApproveStatus { get; set; }
-
+
///
/// 审批时间
///
- [SugarColumn(ColumnName = "F_ApproveTime")]
+ [SugarColumn(ColumnName = "F_ApproveTime")]
public DateTime? ApproveTime { get; set; }
-
+
///
/// 关联购买编号
///
- [SugarColumn(ColumnName = "F_PurchaseRecordsId")]
+ [SugarColumn(ColumnName = "F_PurchaseRecordsId")]
public string PurchaseRecordsId { get; set; }
-
+
+ ///
+ /// 节点数量(3,4,5)
+ ///
+ [SugarColumn(ColumnName = "F_NodeCount")]
+ public int? NodeCount { get; set; }
+
+ ///
+ /// 当前审批节点(0-待审批,1-N节点,N+1-已完成)
+ ///
+ [SugarColumn(ColumnName = "F_CurrentNodeOrder")]
+ public int? CurrentNodeOrder { get; set; }
+
+ ///
+ /// 当前节点ID
+ ///
+ [SugarColumn(ColumnName = "F_CurrentNodeId")]
+ public string CurrentNodeId { get; set; }
+
+ ///
+ /// 审批状态(待审批/审批中/已通过/未通过/已退回)
+ ///
+ [SugarColumn(ColumnName = "F_ApprovalStatus")]
+ public string ApprovalStatus { get; set; }
+
+ ///
+ /// 退回节点
+ ///
+ [SugarColumn(ColumnName = "F_ReturnedNodeOrder")]
+ public int? ReturnedNodeOrder { get; set; }
+
+ ///
+ /// 退回原因
+ ///
+ [SugarColumn(ColumnName = "F_ReturnedReason")]
+ public string ReturnedReason { get; set; }
+
}
}
\ No newline at end of file
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_assistant_salary_statistics/LqAssistantSalaryStatisticsEntity.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_assistant_salary_statistics/LqAssistantSalaryStatisticsEntity.cs
new file mode 100644
index 0000000..d1aacdc
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_assistant_salary_statistics/LqAssistantSalaryStatisticsEntity.cs
@@ -0,0 +1,369 @@
+using System;
+using NCC.Common.Const;
+using SqlSugar;
+
+namespace NCC.Extend.Entitys.lq_assistant_salary_statistics
+{
+ ///
+ /// 店助工资统计表
+ ///
+ [SugarTable("lq_assistant_salary_statistics")]
+ [Tenant(ClaimConst.TENANT_ID)]
+ public class LqAssistantSalaryStatisticsEntity
+ {
+ ///
+ /// 主键ID
+ ///
+ [SugarColumn(ColumnName = "F_Id", IsPrimaryKey = true)]
+ public string Id { get; set; }
+
+ ///
+ /// 门店ID
+ ///
+ [SugarColumn(ColumnName = "F_StoreId")]
+ public string StoreId { get; set; }
+
+ ///
+ /// 门店名称
+ ///
+ [SugarColumn(ColumnName = "F_StoreName")]
+ public string StoreName { get; set; }
+
+ ///
+ /// 核算岗位
+ ///
+ [SugarColumn(ColumnName = "F_Position")]
+ public string Position { get; set; }
+
+ ///
+ /// 员工姓名
+ ///
+ [SugarColumn(ColumnName = "F_EmployeeName")]
+ public string EmployeeName { get; set; }
+
+ ///
+ /// 员工ID
+ ///
+ [SugarColumn(ColumnName = "F_EmployeeId")]
+ public string EmployeeId { get; set; }
+
+ ///
+ /// 统计月份(YYYYMM)
+ ///
+ [SugarColumn(ColumnName = "F_StatisticsMonth")]
+ public string StatisticsMonth { get; set; }
+
+ ///
+ /// 门店类型
+ ///
+ [SugarColumn(ColumnName = "F_StoreType")]
+ public int? StoreType { get; set; }
+
+ ///
+ /// 门店类别
+ ///
+ [SugarColumn(ColumnName = "F_StoreCategory")]
+ public int? StoreCategory { get; set; }
+
+ ///
+ /// 是否新店
+ ///
+ [SugarColumn(ColumnName = "F_IsNewStore")]
+ public string IsNewStore { get; set; }
+
+ ///
+ /// 新店保护阶段
+ ///
+ [SugarColumn(ColumnName = "F_NewStoreProtectionStage")]
+ public int NewStoreProtectionStage { get; set; }
+
+ ///
+ /// 门店总业绩
+ ///
+ [SugarColumn(ColumnName = "F_StoreTotalPerformance")]
+ public decimal StoreTotalPerformance { get; set; }
+
+ ///
+ /// 门店开单业绩
+ ///
+ [SugarColumn(ColumnName = "F_StoreBillingPerformance")]
+ public decimal StoreBillingPerformance { get; set; }
+
+ ///
+ /// 门店退卡业绩
+ ///
+ [SugarColumn(ColumnName = "F_StoreRefundPerformance")]
+ public decimal StoreRefundPerformance { get; set; }
+
+ ///
+ /// 门店生命线
+ ///
+ [SugarColumn(ColumnName = "F_StoreLifeline")]
+ public decimal StoreLifeline { get; set; }
+
+ ///
+ /// 业绩完成率
+ ///
+ [SugarColumn(ColumnName = "F_PerformanceCompletionRate")]
+ public decimal PerformanceCompletionRate { get; set; }
+
+ ///
+ /// 提成比例
+ ///
+ [SugarColumn(ColumnName = "F_CommissionRate")]
+ public decimal CommissionRate { get; set; }
+
+ ///
+ /// 提成金额
+ ///
+ [SugarColumn(ColumnName = "F_CommissionAmount")]
+ public decimal CommissionAmount { get; set; }
+
+ ///
+ /// 进店消耗人数
+ ///
+ [SugarColumn(ColumnName = "F_HeadCount")]
+ public int HeadCount { get; set; }
+
+ ///
+ /// 第一阶段目标人数
+ ///
+ [SugarColumn(ColumnName = "F_Stage1TargetHeadCount")]
+ public int Stage1TargetHeadCount { get; set; }
+
+ ///
+ /// 第二阶段目标人数
+ ///
+ [SugarColumn(ColumnName = "F_Stage2TargetHeadCount")]
+ public int Stage2TargetHeadCount { get; set; }
+
+ ///
+ /// 是否达到第一阶段
+ ///
+ [SugarColumn(ColumnName = "F_ReachedStage1")]
+ public string ReachedStage1 { get; set; }
+
+ ///
+ /// 是否达到第二阶段
+ ///
+ [SugarColumn(ColumnName = "F_ReachedStage2")]
+ public string ReachedStage2 { get; set; }
+
+ ///
+ /// 阶段奖励金额
+ ///
+ [SugarColumn(ColumnName = "F_StageRewardAmount")]
+ public decimal StageRewardAmount { get; set; }
+
+ ///
+ /// 第一阶段奖励
+ ///
+ [SugarColumn(ColumnName = "F_Stage1Reward")]
+ public decimal Stage1Reward { get; set; }
+
+ ///
+ /// 第二阶段奖励
+ ///
+ [SugarColumn(ColumnName = "F_Stage2Reward")]
+ public decimal Stage2Reward { get; set; }
+
+ ///
+ /// 底薪金额
+ ///
+ [SugarColumn(ColumnName = "F_BaseSalary")]
+ public decimal BaseSalary { get; set; }
+
+ ///
+ /// 手机管理费
+ ///
+ [SugarColumn(ColumnName = "F_PhoneManagementFee")]
+ public decimal PhoneManagementFee { get; set; }
+
+ ///
+ /// 在店天数
+ ///
+ [SugarColumn(ColumnName = "F_WorkingDays")]
+ public int WorkingDays { get; set; }
+
+ ///
+ /// 请假天数
+ ///
+ [SugarColumn(ColumnName = "F_LeaveDays")]
+ public int LeaveDays { get; set; }
+
+ ///
+ /// 应发工资
+ ///
+ [SugarColumn(ColumnName = "F_GrossSalary")]
+ public decimal GrossSalary { get; set; }
+
+ ///
+ /// 实发工资
+ ///
+ [SugarColumn(ColumnName = "F_ActualSalary")]
+ public decimal ActualSalary { get; set; }
+
+ ///
+ /// 缺卡扣款
+ ///
+ [SugarColumn(ColumnName = "F_MissingCard")]
+ public decimal MissingCard { get; set; }
+
+ ///
+ /// 迟到扣款
+ ///
+ [SugarColumn(ColumnName = "F_LateArrival")]
+ public decimal LateArrival { get; set; }
+
+ ///
+ /// 请假扣款
+ ///
+ [SugarColumn(ColumnName = "F_LeaveDeduction")]
+ public decimal LeaveDeduction { get; set; }
+
+ ///
+ /// 扣社保
+ ///
+ [SugarColumn(ColumnName = "F_SocialInsuranceDeduction")]
+ public decimal SocialInsuranceDeduction { get; set; }
+
+ ///
+ /// 扣除奖励
+ ///
+ [SugarColumn(ColumnName = "F_RewardDeduction")]
+ public decimal RewardDeduction { get; set; }
+
+ ///
+ /// 扣住宿费
+ ///
+ [SugarColumn(ColumnName = "F_AccommodationDeduction")]
+ public decimal AccommodationDeduction { get; set; }
+
+ ///
+ /// 扣学习期费用
+ ///
+ [SugarColumn(ColumnName = "F_StudyPeriodDeduction")]
+ public decimal StudyPeriodDeduction { get; set; }
+
+ ///
+ /// 扣工作服费用
+ ///
+ [SugarColumn(ColumnName = "F_WorkClothesDeduction")]
+ public decimal WorkClothesDeduction { get; set; }
+
+ ///
+ /// 扣款合计
+ ///
+ [SugarColumn(ColumnName = "F_TotalDeduction")]
+ public decimal TotalDeduction { get; set; }
+
+ ///
+ /// 当月培训补贴
+ ///
+ [SugarColumn(ColumnName = "F_MonthlyTrainingSubsidy")]
+ public decimal MonthlyTrainingSubsidy { get; set; }
+
+ ///
+ /// 当月交通补贴
+ ///
+ [SugarColumn(ColumnName = "F_MonthlyTransportSubsidy")]
+ public decimal MonthlyTransportSubsidy { get; set; }
+
+ ///
+ /// 上月培训补贴
+ ///
+ [SugarColumn(ColumnName = "F_LastMonthTrainingSubsidy")]
+ public decimal LastMonthTrainingSubsidy { get; set; }
+
+ ///
+ /// 上月交通补贴
+ ///
+ [SugarColumn(ColumnName = "F_LastMonthTransportSubsidy")]
+ public decimal LastMonthTransportSubsidy { get; set; }
+
+ ///
+ /// 补贴合计
+ ///
+ [SugarColumn(ColumnName = "F_TotalSubsidy")]
+ public decimal TotalSubsidy { get; set; }
+
+ ///
+ /// 发奖金
+ ///
+ [SugarColumn(ColumnName = "F_Bonus")]
+ public decimal Bonus { get; set; }
+
+ ///
+ /// 退手机押金
+ ///
+ [SugarColumn(ColumnName = "F_ReturnPhoneDeposit")]
+ public decimal ReturnPhoneDeposit { get; set; }
+
+ ///
+ /// 退住宿押金
+ ///
+ [SugarColumn(ColumnName = "F_ReturnAccommodationDeposit")]
+ public decimal ReturnAccommodationDeposit { get; set; }
+
+ ///
+ /// 当月是否发放
+ ///
+ [SugarColumn(ColumnName = "F_MonthlyPaymentStatus")]
+ public string MonthlyPaymentStatus { get; set; }
+
+ ///
+ /// 支付金额
+ ///
+ [SugarColumn(ColumnName = "F_PaidAmount")]
+ public decimal PaidAmount { get; set; }
+
+ ///
+ /// 待支付金额
+ ///
+ [SugarColumn(ColumnName = "F_PendingAmount")]
+ public decimal PendingAmount { get; set; }
+
+ ///
+ /// 补发上月
+ ///
+ [SugarColumn(ColumnName = "F_LastMonthSupplement")]
+ public decimal LastMonthSupplement { get; set; }
+
+ ///
+ /// 当月支付总额
+ ///
+ [SugarColumn(ColumnName = "F_MonthlyTotalPayment")]
+ public decimal MonthlyTotalPayment { get; set; }
+
+ ///
+ /// 是否锁定(0未锁定,1已锁定)
+ ///
+ [SugarColumn(ColumnName = "F_IsLocked")]
+ public int IsLocked { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ [SugarColumn(ColumnName = "F_CreateTime")]
+ public DateTime CreateTime { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ [SugarColumn(ColumnName = "F_UpdateTime")]
+ public DateTime UpdateTime { get; set; }
+
+ ///
+ /// 创建人
+ ///
+ [SugarColumn(ColumnName = "F_CreateUser")]
+ public string CreateUser { get; set; }
+
+ ///
+ /// 更新人
+ ///
+ [SugarColumn(ColumnName = "F_UpdateUser")]
+ public string UpdateUser { get; set; }
+ }
+}
+
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_director_salary_statistics/LqDirectorSalaryStatisticsEntity.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_director_salary_statistics/LqDirectorSalaryStatisticsEntity.cs
new file mode 100644
index 0000000..3f48dab
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_director_salary_statistics/LqDirectorSalaryStatisticsEntity.cs
@@ -0,0 +1,393 @@
+using System;
+using NCC.Common.Const;
+using SqlSugar;
+
+namespace NCC.Extend.Entitys.lq_director_salary_statistics
+{
+ ///
+ /// 主任工资统计表
+ ///
+ [SugarTable("lq_director_salary_statistics")]
+ [Tenant(ClaimConst.TENANT_ID)]
+ public class LqDirectorSalaryStatisticsEntity
+ {
+ ///
+ /// 主键ID
+ ///
+ [SugarColumn(ColumnName = "F_Id", IsPrimaryKey = true)]
+ public string Id { get; set; }
+
+ ///
+ /// 门店ID
+ ///
+ [SugarColumn(ColumnName = "F_StoreId")]
+ public string StoreId { get; set; }
+
+ ///
+ /// 门店名称
+ ///
+ [SugarColumn(ColumnName = "F_StoreName")]
+ public string StoreName { get; set; }
+
+ ///
+ /// 核算岗位
+ ///
+ [SugarColumn(ColumnName = "F_Position")]
+ public string Position { get; set; }
+
+ ///
+ /// 员工姓名
+ ///
+ [SugarColumn(ColumnName = "F_EmployeeName")]
+ public string EmployeeName { get; set; }
+
+ ///
+ /// 员工ID
+ ///
+ [SugarColumn(ColumnName = "F_EmployeeId")]
+ public string EmployeeId { get; set; }
+
+ ///
+ /// 统计月份(YYYYMM)
+ ///
+ [SugarColumn(ColumnName = "F_StatisticsMonth")]
+ public string StatisticsMonth { get; set; }
+
+ ///
+ /// 门店类型
+ ///
+ [SugarColumn(ColumnName = "F_StoreType")]
+ public int? StoreType { get; set; }
+
+ ///
+ /// 门店类别
+ ///
+ [SugarColumn(ColumnName = "F_StoreCategory")]
+ public int? StoreCategory { get; set; }
+
+ ///
+ /// 是否新店
+ ///
+ [SugarColumn(ColumnName = "F_IsNewStore")]
+ public string IsNewStore { get; set; }
+
+ ///
+ /// 新店保护阶段
+ ///
+ [SugarColumn(ColumnName = "F_NewStoreProtectionStage")]
+ public int NewStoreProtectionStage { get; set; }
+
+ ///
+ /// 门店总业绩
+ ///
+ [SugarColumn(ColumnName = "F_StoreTotalPerformance")]
+ public decimal StoreTotalPerformance { get; set; }
+
+ ///
+ /// 门店开单业绩
+ ///
+ [SugarColumn(ColumnName = "F_StoreBillingPerformance")]
+ public decimal StoreBillingPerformance { get; set; }
+
+ ///
+ /// 门店退卡业绩
+ ///
+ [SugarColumn(ColumnName = "F_StoreRefundPerformance")]
+ public decimal StoreRefundPerformance { get; set; }
+
+ ///
+ /// 门店生命线
+ ///
+ [SugarColumn(ColumnName = "F_StoreLifeline")]
+ public decimal StoreLifeline { get; set; }
+
+ ///
+ /// 业绩完成率
+ ///
+ [SugarColumn(ColumnName = "F_PerformanceCompletionRate")]
+ public decimal PerformanceCompletionRate { get; set; }
+
+ ///
+ /// 业绩是否达标
+ ///
+ [SugarColumn(ColumnName = "F_PerformanceReached")]
+ public string PerformanceReached { get; set; }
+
+ ///
+ /// 人头是否达标
+ ///
+ [SugarColumn(ColumnName = "F_HeadCountReached")]
+ public string HeadCountReached { get; set; }
+
+ ///
+ /// 消耗是否达标
+ ///
+ [SugarColumn(ColumnName = "F_ConsumeReached")]
+ public string ConsumeReached { get; set; }
+
+ ///
+ /// 考核扣款金额
+ ///
+ [SugarColumn(ColumnName = "F_AssessmentDeduction")]
+ public decimal AssessmentDeduction { get; set; }
+
+ ///
+ /// 未达标指标数量
+ ///
+ [SugarColumn(ColumnName = "F_UnreachedIndicatorCount")]
+ public int UnreachedIndicatorCount { get; set; }
+
+ ///
+ /// 进店消耗人数
+ ///
+ [SugarColumn(ColumnName = "F_HeadCount")]
+ public int HeadCount { get; set; }
+
+ ///
+ /// 目标人头数
+ ///
+ [SugarColumn(ColumnName = "F_TargetHeadCount")]
+ public decimal TargetHeadCount { get; set; }
+
+ ///
+ /// 门店消耗金额
+ ///
+ [SugarColumn(ColumnName = "F_StoreConsume")]
+ public decimal StoreConsume { get; set; }
+
+ ///
+ /// 目标消耗金额
+ ///
+ [SugarColumn(ColumnName = "F_TargetConsume")]
+ public decimal TargetConsume { get; set; }
+
+ ///
+ /// ≤生命线部分提成比例
+ ///
+ [SugarColumn(ColumnName = "F_CommissionRateBelowLifeline")]
+ public decimal CommissionRateBelowLifeline { get; set; }
+
+ ///
+ /// >生命线部分提成比例
+ ///
+ [SugarColumn(ColumnName = "F_CommissionRateAboveLifeline")]
+ public decimal CommissionRateAboveLifeline { get; set; }
+
+ ///
+ /// ≤生命线部分提成金额
+ ///
+ [SugarColumn(ColumnName = "F_CommissionAmountBelowLifeline")]
+ public decimal CommissionAmountBelowLifeline { get; set; }
+
+ ///
+ /// >生命线部分提成金额
+ ///
+ [SugarColumn(ColumnName = "F_CommissionAmountAboveLifeline")]
+ public decimal CommissionAmountAboveLifeline { get; set; }
+
+ ///
+ /// 提成总金额
+ ///
+ [SugarColumn(ColumnName = "F_TotalCommissionAmount")]
+ public decimal TotalCommissionAmount { get; set; }
+
+ ///
+ /// 底薪金额
+ ///
+ [SugarColumn(ColumnName = "F_BaseSalary")]
+ public decimal BaseSalary { get; set; }
+
+ ///
+ /// 实际底薪
+ ///
+ [SugarColumn(ColumnName = "F_ActualBaseSalary")]
+ public decimal ActualBaseSalary { get; set; }
+
+ ///
+ /// 在店天数
+ ///
+ [SugarColumn(ColumnName = "F_WorkingDays")]
+ public int WorkingDays { get; set; }
+
+ ///
+ /// 请假天数
+ ///
+ [SugarColumn(ColumnName = "F_LeaveDays")]
+ public int LeaveDays { get; set; }
+
+ ///
+ /// 应发工资
+ ///
+ [SugarColumn(ColumnName = "F_GrossSalary")]
+ public decimal GrossSalary { get; set; }
+
+ ///
+ /// 实发工资
+ ///
+ [SugarColumn(ColumnName = "F_ActualSalary")]
+ public decimal ActualSalary { get; set; }
+
+ ///
+ /// 缺卡扣款
+ ///
+ [SugarColumn(ColumnName = "F_MissingCard")]
+ public decimal MissingCard { get; set; }
+
+ ///
+ /// 迟到扣款
+ ///
+ [SugarColumn(ColumnName = "F_LateArrival")]
+ public decimal LateArrival { get; set; }
+
+ ///
+ /// 请假扣款
+ ///
+ [SugarColumn(ColumnName = "F_LeaveDeduction")]
+ public decimal LeaveDeduction { get; set; }
+
+ ///
+ /// 扣社保
+ ///
+ [SugarColumn(ColumnName = "F_SocialInsuranceDeduction")]
+ public decimal SocialInsuranceDeduction { get; set; }
+
+ ///
+ /// 扣除奖励
+ ///
+ [SugarColumn(ColumnName = "F_RewardDeduction")]
+ public decimal RewardDeduction { get; set; }
+
+ ///
+ /// 扣住宿费
+ ///
+ [SugarColumn(ColumnName = "F_AccommodationDeduction")]
+ public decimal AccommodationDeduction { get; set; }
+
+ ///
+ /// 扣学习期费用
+ ///
+ [SugarColumn(ColumnName = "F_StudyPeriodDeduction")]
+ public decimal StudyPeriodDeduction { get; set; }
+
+ ///
+ /// 扣工作服费用
+ ///
+ [SugarColumn(ColumnName = "F_WorkClothesDeduction")]
+ public decimal WorkClothesDeduction { get; set; }
+
+ ///
+ /// 扣款合计
+ ///
+ [SugarColumn(ColumnName = "F_TotalDeduction")]
+ public decimal TotalDeduction { get; set; }
+
+ ///
+ /// 当月培训补贴
+ ///
+ [SugarColumn(ColumnName = "F_MonthlyTrainingSubsidy")]
+ public decimal MonthlyTrainingSubsidy { get; set; }
+
+ ///
+ /// 当月交通补贴
+ ///
+ [SugarColumn(ColumnName = "F_MonthlyTransportSubsidy")]
+ public decimal MonthlyTransportSubsidy { get; set; }
+
+ ///
+ /// 上月培训补贴
+ ///
+ [SugarColumn(ColumnName = "F_LastMonthTrainingSubsidy")]
+ public decimal LastMonthTrainingSubsidy { get; set; }
+
+ ///
+ /// 上月交通补贴
+ ///
+ [SugarColumn(ColumnName = "F_LastMonthTransportSubsidy")]
+ public decimal LastMonthTransportSubsidy { get; set; }
+
+ ///
+ /// 补贴合计
+ ///
+ [SugarColumn(ColumnName = "F_TotalSubsidy")]
+ public decimal TotalSubsidy { get; set; }
+
+ ///
+ /// 发奖金
+ ///
+ [SugarColumn(ColumnName = "F_Bonus")]
+ public decimal Bonus { get; set; }
+
+ ///
+ /// 退手机押金
+ ///
+ [SugarColumn(ColumnName = "F_ReturnPhoneDeposit")]
+ public decimal ReturnPhoneDeposit { get; set; }
+
+ ///
+ /// 退住宿押金
+ ///
+ [SugarColumn(ColumnName = "F_ReturnAccommodationDeposit")]
+ public decimal ReturnAccommodationDeposit { get; set; }
+
+ ///
+ /// 当月是否发放
+ ///
+ [SugarColumn(ColumnName = "F_MonthlyPaymentStatus")]
+ public string MonthlyPaymentStatus { get; set; }
+
+ ///
+ /// 支付金额
+ ///
+ [SugarColumn(ColumnName = "F_PaidAmount")]
+ public decimal PaidAmount { get; set; }
+
+ ///
+ /// 待支付金额
+ ///
+ [SugarColumn(ColumnName = "F_PendingAmount")]
+ public decimal PendingAmount { get; set; }
+
+ ///
+ /// 补发上月
+ ///
+ [SugarColumn(ColumnName = "F_LastMonthSupplement")]
+ public decimal LastMonthSupplement { get; set; }
+
+ ///
+ /// 当月支付总额
+ ///
+ [SugarColumn(ColumnName = "F_MonthlyTotalPayment")]
+ public decimal MonthlyTotalPayment { get; set; }
+
+ ///
+ /// 是否锁定(0未锁定,1已锁定)
+ ///
+ [SugarColumn(ColumnName = "F_IsLocked")]
+ public int IsLocked { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ [SugarColumn(ColumnName = "F_CreateTime")]
+ public DateTime CreateTime { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ [SugarColumn(ColumnName = "F_UpdateTime")]
+ public DateTime UpdateTime { get; set; }
+
+ ///
+ /// 创建人
+ ///
+ [SugarColumn(ColumnName = "F_CreateUser")]
+ public string CreateUser { get; set; }
+
+ ///
+ /// 更新人
+ ///
+ [SugarColumn(ColumnName = "F_UpdateUser")]
+ public string UpdateUser { get; set; }
+ }
+}
+
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_reimbursement_application_node/LqReimbursementApplicationNodeEntity.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_reimbursement_application_node/LqReimbursementApplicationNodeEntity.cs
new file mode 100644
index 0000000..d4aca2c
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_reimbursement_application_node/LqReimbursementApplicationNodeEntity.cs
@@ -0,0 +1,57 @@
+using NCC.Common.Const;
+using SqlSugar;
+using System;
+
+namespace NCC.Extend.Entitys.lq_reimbursement_application_node
+{
+ ///
+ /// 报销申请节点表(每个报销申请的节点配置)
+ ///
+ [SugarTable("lq_reimbursement_application_node")]
+ [Tenant(ClaimConst.TENANT_ID)]
+ public class LqReimbursementApplicationNodeEntity
+ {
+ ///
+ /// 节点编号
+ ///
+ [SugarColumn(ColumnName = "F_Id", IsPrimaryKey = true)]
+ public string Id { get; set; }
+
+ ///
+ /// 报销申请ID
+ ///
+ [SugarColumn(ColumnName = "F_ApplicationId")]
+ public string ApplicationId { get; set; }
+
+ ///
+ /// 节点顺序(1,2,3,4,5)
+ ///
+ [SugarColumn(ColumnName = "F_NodeOrder")]
+ public int NodeOrder { get; set; }
+
+ ///
+ /// 节点名称
+ ///
+ [SugarColumn(ColumnName = "F_NodeName")]
+ public string NodeName { get; set; }
+
+ ///
+ /// 审批类型(会签/或签)
+ ///
+ [SugarColumn(ColumnName = "F_ApprovalType")]
+ public string ApprovalType { get; set; }
+
+ ///
+ /// 是否必审(1-必审,0-可选)
+ ///
+ [SugarColumn(ColumnName = "F_IsRequired")]
+ public int IsRequired { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ [SugarColumn(ColumnName = "F_CreateTime")]
+ public DateTime? CreateTime { get; set; }
+ }
+}
+
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_reimbursement_application_node_user/LqReimbursementApplicationNodeUserEntity.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_reimbursement_application_node_user/LqReimbursementApplicationNodeUserEntity.cs
new file mode 100644
index 0000000..e4c8f67
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_reimbursement_application_node_user/LqReimbursementApplicationNodeUserEntity.cs
@@ -0,0 +1,63 @@
+using NCC.Common.Const;
+using SqlSugar;
+using System;
+
+namespace NCC.Extend.Entitys.lq_reimbursement_application_node_user
+{
+ ///
+ /// 报销申请节点审批人表(每个节点的审批人,在创建报销申请时指定)
+ ///
+ [SugarTable("lq_reimbursement_application_node_user")]
+ [Tenant(ClaimConst.TENANT_ID)]
+ public class LqReimbursementApplicationNodeUserEntity
+ {
+ ///
+ /// 记录编号
+ ///
+ [SugarColumn(ColumnName = "F_Id", IsPrimaryKey = true)]
+ public string Id { get; set; }
+
+ ///
+ /// 报销申请ID
+ ///
+ [SugarColumn(ColumnName = "F_ApplicationId")]
+ public string ApplicationId { get; set; }
+
+ ///
+ /// 节点编号
+ ///
+ [SugarColumn(ColumnName = "F_NodeId")]
+ public string NodeId { get; set; }
+
+ ///
+ /// 节点顺序(1,2,3,4,5)
+ ///
+ [SugarColumn(ColumnName = "F_NodeOrder")]
+ public int NodeOrder { get; set; }
+
+ ///
+ /// 审批人ID
+ ///
+ [SugarColumn(ColumnName = "F_UserId")]
+ public string UserId { get; set; }
+
+ ///
+ /// 审批人姓名
+ ///
+ [SugarColumn(ColumnName = "F_UserName")]
+ public string UserName { get; set; }
+
+ ///
+ /// 排序
+ ///
+ [SugarColumn(ColumnName = "F_SortOrder")]
+ public int SortOrder { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ [SugarColumn(ColumnName = "F_CreateTime")]
+ public DateTime? CreateTime { get; set; }
+ }
+}
+
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_reimbursement_approval_record/LqReimbursementApprovalRecordEntity.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_reimbursement_approval_record/LqReimbursementApprovalRecordEntity.cs
new file mode 100644
index 0000000..0b4e4d5
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_reimbursement_approval_record/LqReimbursementApprovalRecordEntity.cs
@@ -0,0 +1,75 @@
+using NCC.Common.Const;
+using SqlSugar;
+using System;
+
+namespace NCC.Extend.Entitys.lq_reimbursement_approval_record
+{
+ ///
+ /// 审批记录表
+ ///
+ [SugarTable("lq_reimbursement_approval_record")]
+ [Tenant(ClaimConst.TENANT_ID)]
+ public class LqReimbursementApprovalRecordEntity
+ {
+ ///
+ /// 记录编号
+ ///
+ [SugarColumn(ColumnName = "F_Id", IsPrimaryKey = true)]
+ public string Id { get; set; }
+
+ ///
+ /// 报销申请ID
+ ///
+ [SugarColumn(ColumnName = "F_ApplicationId")]
+ public string ApplicationId { get; set; }
+
+ ///
+ /// 节点编号
+ ///
+ [SugarColumn(ColumnName = "F_NodeId")]
+ public string NodeId { get; set; }
+
+ ///
+ /// 节点顺序(1,2,3,4,5)
+ ///
+ [SugarColumn(ColumnName = "F_NodeOrder")]
+ public int NodeOrder { get; set; }
+
+ ///
+ /// 审批人ID
+ ///
+ [SugarColumn(ColumnName = "F_ApproverId")]
+ public string ApproverId { get; set; }
+
+ ///
+ /// 审批人姓名
+ ///
+ [SugarColumn(ColumnName = "F_ApproverName")]
+ public string ApproverName { get; set; }
+
+ ///
+ /// 审批结果(通过/不通过/退回)
+ ///
+ [SugarColumn(ColumnName = "F_ApprovalResult")]
+ public string ApprovalResult { get; set; }
+
+ ///
+ /// 审批意见
+ ///
+ [SugarColumn(ColumnName = "F_ApprovalOpinion")]
+ public string ApprovalOpinion { get; set; }
+
+ ///
+ /// 审批时间
+ ///
+ [SugarColumn(ColumnName = "F_ApprovalTime")]
+ public DateTime? ApprovalTime { get; set; }
+
+ ///
+ /// 是否当前节点(1-是,0-否)
+ ///
+ [SugarColumn(ColumnName = "F_IsCurrentNode")]
+ public int IsCurrentNode { get; set; }
+ }
+}
+
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_salary_statistics/LqSalaryStatisticsEntity.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_salary_statistics/LqSalaryStatisticsEntity.cs
index b3a4b85..b15b9e4 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_salary_statistics/LqSalaryStatisticsEntity.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_salary_statistics/LqSalaryStatisticsEntity.cs
@@ -520,5 +520,23 @@ namespace NCC.Extend.Entitys.lq_salary_statistics
///
[SugarColumn(ColumnName = "F_StoreCategory")]
public int? StoreCategory { get; set; }
+
+ ///
+ /// 日均消耗
+ ///
+ [SugarColumn(ColumnName = "F_DailyAverageConsumption")]
+ public decimal DailyAverageConsumption { get; set; }
+
+ ///
+ /// 日均项目数
+ ///
+ [SugarColumn(ColumnName = "F_DailyAverageProjectCount")]
+ public decimal DailyAverageProjectCount { get; set; }
+
+ ///
+ /// 战队总消耗
+ ///
+ [SugarColumn(ColumnName = "F_TeamTotalConsumption")]
+ public decimal TeamTotalConsumption { get; set; }
}
}
\ No newline at end of file
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqAssistantSalaryService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqAssistantSalaryService.cs
new file mode 100644
index 0000000..f0a7ebd
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqAssistantSalaryService.cs
@@ -0,0 +1,533 @@
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using NCC.Common.Filter;
+using NCC.Common.Helper;
+using NCC.Dependency;
+using NCC.DynamicApiController;
+using NCC.Extend.Entitys.Dto.LqAssistantSalary;
+using NCC.Extend.Entitys.lq_assistant_salary_statistics;
+using NCC.Extend.Entitys.lq_attendance_summary;
+using NCC.Extend.Entitys.lq_hytk_hytk;
+using NCC.Extend.Entitys.lq_kd_kdjlb;
+using NCC.Extend.Entitys.lq_md_target;
+using NCC.Extend.Entitys.lq_md_xdbhsj;
+using NCC.Extend.Entitys.lq_mdxx;
+using NCC.Extend.Entitys.lq_xh_hyhk;
+using NCC.Extend.Entitys.lq_xh_jksyj;
+using NCC.System.Entitys.Permission;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Yitter.IdGenerator;
+
+namespace NCC.Extend
+{
+ ///
+ /// 店助薪酬服务
+ ///
+ [ApiDescriptionSettings(Tag = "店助薪酬服务", Name = "LqAssistantSalary", Order = 301)]
+ [Route("api/Extend/[controller]")]
+ public class LqAssistantSalaryService : IDynamicApiController, ITransient
+ {
+ private readonly ISqlSugarClient _db;
+
+ ///
+ /// 初始化一个类型的新实例
+ ///
+ public LqAssistantSalaryService(ISqlSugarClient db)
+ {
+ _db = db;
+ }
+
+ ///
+ /// 获取店助工资列表
+ ///
+ /// 查询参数
+ /// 店助工资分页列表
+ [HttpGet("assistant")]
+ public async Task GetAssistantSalaryList([FromQuery] AssistantSalaryInput input)
+ {
+ var monthStr = $"{input.Year}{input.Month:D2}";
+
+ // 1. 检查当月是否已生成工资数据
+ var exists = await _db.Queryable()
+ .AnyAsync(x => x.StatisticsMonth == monthStr);
+
+ // 2. 如果没有数据,则进行计算
+ if (!exists)
+ {
+ await CalculateAssistantSalary(input.Year, input.Month);
+ }
+
+ // 3. 查询数据
+ var query = _db.Queryable()
+ .Where(x => x.StatisticsMonth == monthStr);
+
+ if (!string.IsNullOrEmpty(input.StoreId))
+ {
+ query = query.Where(x => x.StoreId == input.StoreId);
+ }
+
+ if (!string.IsNullOrEmpty(input.Keyword))
+ {
+ query = query.Where(x => x.EmployeeName.Contains(input.Keyword) || x.EmployeeId.Contains(input.Keyword));
+ }
+
+ var list = await query.Select(x => new AssistantSalaryOutput
+ {
+ Id = x.Id,
+ StoreName = x.StoreName,
+ EmployeeName = x.EmployeeName,
+ Position = x.Position,
+ StoreTotalPerformance = x.StoreTotalPerformance,
+ StoreBillingPerformance = x.StoreBillingPerformance,
+ StoreRefundPerformance = x.StoreRefundPerformance,
+ StoreLifeline = x.StoreLifeline,
+ PerformanceCompletionRate = x.PerformanceCompletionRate,
+ CommissionRate = x.CommissionRate,
+ CommissionAmount = x.CommissionAmount,
+ HeadCount = x.HeadCount,
+ Stage1TargetHeadCount = x.Stage1TargetHeadCount,
+ Stage2TargetHeadCount = x.Stage2TargetHeadCount,
+ ReachedStage1 = x.ReachedStage1,
+ ReachedStage2 = x.ReachedStage2,
+ StageRewardAmount = x.StageRewardAmount,
+ Stage1Reward = x.Stage1Reward,
+ Stage2Reward = x.Stage2Reward,
+ BaseSalary = x.BaseSalary,
+ PhoneManagementFee = x.PhoneManagementFee,
+ WorkingDays = x.WorkingDays,
+ LeaveDays = x.LeaveDays,
+ GrossSalary = x.GrossSalary,
+ ActualSalary = x.ActualSalary,
+ TotalDeduction = x.TotalDeduction,
+ TotalSubsidy = x.TotalSubsidy,
+ Bonus = x.Bonus,
+ ReturnPhoneDeposit = x.ReturnPhoneDeposit,
+ ReturnAccommodationDeposit = x.ReturnAccommodationDeposit,
+ MonthlyPaymentStatus = x.MonthlyPaymentStatus,
+ PaidAmount = x.PaidAmount,
+ PendingAmount = x.PendingAmount,
+ LastMonthSupplement = x.LastMonthSupplement,
+ MonthlyTotalPayment = x.MonthlyTotalPayment,
+ IsLocked = x.IsLocked,
+ UpdateTime = x.UpdateTime,
+ StoreType = x.StoreType,
+ StoreCategory = x.StoreCategory,
+ IsNewStore = x.IsNewStore,
+ NewStoreProtectionStage = x.NewStoreProtectionStage
+ })
+ .ToPagedListAsync(input.currentPage, input.pageSize);
+
+ return PageResult.SqlSugarPageResult(list);
+ }
+
+ ///
+ /// 计算店助工资
+ ///
+ /// 年份
+ /// 月份
+ ///
+ [HttpPost("calculate/assistant")]
+ public async Task CalculateAssistantSalary(int year, int month)
+ {
+ var startDate = new DateTime(year, month, 1);
+ var endDate = startDate.AddMonths(1).AddDays(-1);
+ var monthStr = $"{year}{month:D2}";
+ var daysInMonth = DateTime.DaysInMonth(year, month); // 当月天数
+
+ // 1. 获取基础数据
+
+ // 1.1 获取店助员工列表(从BASE_USER表,岗位为"店助"或"店助主任")
+ var assistantUserList = await _db.Queryable()
+ .Where(x => (x.Gw == "店助" || x.Gw == "店助主任") && x.DeleteMark == null && x.EnabledMark == 1)
+ .Select(x => new { x.Id, x.RealName, x.Mdid, x.Gw })
+ .ToListAsync();
+
+ if (!assistantUserList.Any())
+ {
+ // 如果没有店助员工,直接返回
+ return;
+ }
+
+ // 1.2 门店信息 (lq_mdxx)
+ var storeList = await _db.Queryable().ToListAsync();
+ var storeDict = storeList.Where(x => !string.IsNullOrEmpty(x.Id)).ToDictionary(x => x.Id, x => x);
+
+ // 1.3 门店目标信息 (lq_md_target) - 包含门店生命线和阶段目标
+ var storeTargets = await _db.Queryable()
+ .Where(x => x.Month == monthStr)
+ .ToListAsync();
+ var storeTargetDict = storeTargets.Where(x => !string.IsNullOrEmpty(x.StoreId))
+ .ToDictionary(x => x.StoreId, x => x);
+
+ // 1.4 门店新店保护信息 (lq_md_xdbhsj)
+ var newStoreProtectionList = await _db.Queryable()
+ .Where(x => x.Sfqy == 1)
+ .ToListAsync();
+ var newStoreProtectionDict = newStoreProtectionList
+ .Where(x => x.Bhkssj <= startDate && x.Bhjssj >= startDate)
+ .GroupBy(x => x.Mdid)
+ .ToDictionary(g => g.Key, g => g.First());
+
+ // 1.5 门店总业绩计算 (开单实付 - 退卡金额)
+ // 开单实付
+ var storeBillingList = await _db.Queryable()
+ .Where(x => x.Kdrq >= startDate && x.Kdrq <= endDate.AddDays(1) && x.IsEffective == 1)
+ .Select(x => new { x.Djmd, x.Sfyj })
+ .ToListAsync();
+ var storeBillingDict = storeBillingList
+ .Where(x => !string.IsNullOrEmpty(x.Djmd))
+ .GroupBy(x => x.Djmd)
+ .ToDictionary(g => g.Key, g => g.Sum(x => x.Sfyj));
+
+ // 退卡金额(使用F_ActualRefundAmount,如果没有则使用tkje)
+ var storeRefundList = await _db.Queryable()
+ .Where(x => x.Tksj >= startDate && x.Tksj <= endDate.AddDays(1) && x.IsEffective == 1)
+ .Select(x => new { x.Md, x.ActualRefundAmount, x.Tkje })
+ .ToListAsync();
+ var storeRefundDict = storeRefundList
+ .Where(x => !string.IsNullOrEmpty(x.Md))
+ .GroupBy(x => x.Md)
+ .ToDictionary(g => g.Key, g => g.Sum(x => x.ActualRefundAmount ?? x.Tkje ?? 0));
+
+ // 1.6 进店消耗人数统计(有消费金额的,按门店按月去重客户数)
+ // 使用SQL查询优化性能
+ var headcountSql = $@"
+ SELECT
+ hyhk.md as StoreId,
+ COUNT(DISTINCT hyhk.hy) as HeadCount
+ FROM lq_xh_hyhk hyhk
+ WHERE hyhk.F_IsEffective = 1
+ AND DATE_FORMAT(hyhk.hksj, '%Y%m') = @monthStr
+ AND EXISTS (
+ SELECT 1
+ FROM lq_xh_jksyj jksyj
+ WHERE jksyj.glkdbh = hyhk.F_Id
+ AND jksyj.F_IsEffective = 1
+ AND jksyj.jksyj > 0
+ )
+ GROUP BY hyhk.md";
+
+ var headcountData = await _db.Ado.SqlQueryAsync(headcountSql, new { monthStr });
+ var headcountDict = headcountData
+ .Where(x => x.StoreId != null)
+ .ToDictionary(x => x.StoreId.ToString(), x => Convert.ToInt32(x.HeadCount));
+
+ // 1.7 考勤数据 (lq_attendance_summary)
+ var attendanceList = await _db.Queryable()
+ .Where(x => x.Year == year && x.Month == month && x.IsEffective == 1)
+ .ToListAsync();
+ var attendanceDict = attendanceList.ToDictionary(x => x.UserId, x => x);
+
+ // 2. 计算每个店助的工资
+ var assistantSalaryList = new List();
+
+ foreach (var assistantUser in assistantUserList)
+ {
+ var salary = new LqAssistantSalaryStatisticsEntity
+ {
+ Id = YitIdHelper.NextId().ToString(),
+ EmployeeId = assistantUser.Id,
+ EmployeeName = assistantUser.RealName,
+ StatisticsMonth = monthStr,
+ Position = assistantUser.Gw ?? "店助", // 使用Gw字段,如果为空则默认为"店助"
+ CreateTime = DateTime.Now,
+ UpdateTime = DateTime.Now,
+ IsLocked = 0,
+ MonthlyPaymentStatus = "未发放"
+ };
+
+ // 2.1 填充门店信息
+ string storeId = assistantUser.Mdid;
+ if (string.IsNullOrEmpty(storeId))
+ {
+ // 如果用户没有门店ID,跳过
+ continue;
+ }
+
+ salary.StoreId = storeId;
+
+ if (storeDict.ContainsKey(storeId))
+ {
+ var store = storeDict[storeId];
+ salary.StoreName = store.Dm;
+ salary.StoreType = store.StoreType;
+ salary.StoreCategory = store.StoreCategory;
+
+ // 数据校验:门店分类必须设置
+ if (!salary.StoreCategory.HasValue)
+ {
+ throw new Exception($"门店【{store.Dm}】的门店分类未设置,无法计算店助工资");
+ }
+ }
+
+ // 2.2 填充新店保护信息
+ if (newStoreProtectionDict.ContainsKey(storeId))
+ {
+ var protection = newStoreProtectionDict[storeId];
+ salary.IsNewStore = "是";
+ salary.NewStoreProtectionStage = protection.Stage;
+ }
+ else
+ {
+ salary.IsNewStore = "否";
+ salary.NewStoreProtectionStage = 0;
+ }
+
+ // 2.3 获取门店目标信息(门店生命线和阶段目标)
+ if (!storeTargetDict.ContainsKey(storeId))
+ {
+ throw new Exception($"门店【{salary.StoreName ?? storeId}】在门店目标表中未配置{monthStr}月份的目标数据,无法计算店助工资");
+ }
+
+ var storeTarget = storeTargetDict[storeId];
+ salary.StoreLifeline = storeTarget.StoreLifeline;
+
+ // 阶段目标设置(如果未设置,则奖励金额为0)
+ salary.Stage1TargetHeadCount = storeTarget.AssistantHeadcountTargetStage1 > 0
+ ? (int)storeTarget.AssistantHeadcountTargetStage1
+ : 0;
+ salary.Stage2TargetHeadCount = storeTarget.AssistantHeadcountTargetStage2 > 0
+ ? (int)storeTarget.AssistantHeadcountTargetStage2
+ : 0;
+
+ // 2.4 计算门店业绩
+ decimal billing = storeBillingDict.ContainsKey(storeId) ? storeBillingDict[storeId] : 0;
+ decimal refund = storeRefundDict.ContainsKey(storeId) ? storeRefundDict[storeId] : 0;
+ salary.StoreBillingPerformance = billing;
+ salary.StoreRefundPerformance = refund;
+ salary.StoreTotalPerformance = billing - refund;
+
+ // 计算业绩完成率
+ if (salary.StoreLifeline > 0)
+ {
+ salary.PerformanceCompletionRate = salary.StoreTotalPerformance / salary.StoreLifeline;
+ }
+ else
+ {
+ salary.PerformanceCompletionRate = 0;
+ }
+
+ // 2.5 计算门店总提成(先计算门店级别的提成)
+ decimal storeTotalCommission = 0;
+ decimal commissionRate = 0;
+
+ // 如果门店生命线未设置(<=0),则没有提成
+ if (salary.StoreLifeline <= 0)
+ {
+ commissionRate = 0;
+ storeTotalCommission = 0;
+ }
+ else
+ {
+ commissionRate = CalculateCommissionRate(salary.StoreTotalPerformance, salary.StoreLifeline);
+ storeTotalCommission = salary.StoreTotalPerformance * commissionRate;
+ }
+
+ salary.CommissionRate = commissionRate;
+
+ // 2.6 统计进店消耗人数
+ salary.HeadCount = headcountDict.ContainsKey(storeId) ? headcountDict[storeId] : 0;
+
+ // 2.7 计算门店总阶段奖励(先计算门店级别的奖励)
+ decimal storeTotalStageReward = 0;
+ bool reachedStage1 = false;
+ bool reachedStage2 = false;
+
+ // 如果阶段目标未设置(为0),则没有奖励考核,奖励金额为0
+ if (salary.Stage1TargetHeadCount <= 0 && salary.Stage2TargetHeadCount <= 0)
+ {
+ // 阶段目标未设置,没有奖励考核
+ salary.ReachedStage1 = "否";
+ salary.ReachedStage2 = "否";
+ storeTotalStageReward = 0m;
+ }
+ else
+ {
+ // 阶段目标已设置,进行奖励考核
+ reachedStage1 = salary.Stage1TargetHeadCount > 0 && salary.HeadCount >= salary.Stage1TargetHeadCount;
+ reachedStage2 = salary.Stage2TargetHeadCount > 0 && salary.HeadCount >= salary.Stage2TargetHeadCount;
+
+ salary.ReachedStage1 = reachedStage1 ? "是" : "否";
+ salary.ReachedStage2 = reachedStage2 ? "是" : "否";
+
+ // 阶段奖励计算规则:
+ // - 如果达到第二阶段,获得400元(第一阶段200 + 第二阶段200)
+ // - 如果只达到第一阶段,获得200元
+ // - 如果都没达到,获得0元
+ if (reachedStage2)
+ {
+ storeTotalStageReward = 400m;
+ }
+ else if (reachedStage1)
+ {
+ storeTotalStageReward = 200m;
+ }
+ else
+ {
+ storeTotalStageReward = 0m;
+ }
+ }
+
+ // 2.8 计算底薪(根据门店分类)
+ salary.BaseSalary = CalculateBaseSalary(salary.StoreCategory.Value);
+
+ // 2.9 固定奖励(手机管理费)
+ salary.PhoneManagementFee = 150m;
+
+ // 2.10 考勤数据
+ int workingDays = 0;
+ if (attendanceDict.ContainsKey(assistantUser.Id))
+ {
+ var attendance = attendanceDict[assistantUser.Id];
+ workingDays = (int)attendance.WorkDays;
+ salary.WorkingDays = workingDays;
+ salary.LeaveDays = (int)attendance.LeaveDays;
+ }
+ else
+ {
+ salary.WorkingDays = 0;
+ salary.LeaveDays = 0;
+ }
+
+ // 2.11 按在店天数比例计算店助的提成和奖励
+ // 逻辑:门店总提成 / 当月天数 * 在店天数 = 店助提成
+ // 门店总奖励 / 当月天数 * 在店天数 = 店助奖励
+ if (daysInMonth > 0 && workingDays > 0)
+ {
+ // 按比例计算提成
+ salary.CommissionAmount = storeTotalCommission / daysInMonth * workingDays;
+
+ // 按比例计算奖励
+ salary.StageRewardAmount = storeTotalStageReward / daysInMonth * workingDays;
+
+ // 计算阶段奖励的明细(按比例分配)
+ if (reachedStage2)
+ {
+ // 达到第二阶段:第一阶段200 + 第二阶段200
+ salary.Stage1Reward = 200m / daysInMonth * workingDays;
+ salary.Stage2Reward = 200m / daysInMonth * workingDays;
+ }
+ else if (reachedStage1)
+ {
+ // 只达到第一阶段:第一阶段200
+ salary.Stage1Reward = 200m / daysInMonth * workingDays;
+ salary.Stage2Reward = 0m;
+ }
+ else
+ {
+ // 都没达到
+ salary.Stage1Reward = 0m;
+ salary.Stage2Reward = 0m;
+ }
+ }
+ else
+ {
+ // 如果当月天数为0或在店天数为0,则提成和奖励为0
+ salary.CommissionAmount = 0;
+ salary.StageRewardAmount = 0;
+ salary.Stage1Reward = 0;
+ salary.Stage2Reward = 0;
+ }
+
+ // 2.12 计算应发工资
+ salary.GrossSalary = salary.BaseSalary + salary.CommissionAmount + salary.StageRewardAmount + salary.PhoneManagementFee;
+
+ // 2.13 初始化扣款、补贴、奖金字段(默认值为0)
+ salary.MissingCard = 0;
+ salary.LateArrival = 0;
+ salary.LeaveDeduction = 0;
+ salary.SocialInsuranceDeduction = 0;
+ salary.RewardDeduction = 0;
+ salary.AccommodationDeduction = 0;
+ salary.StudyPeriodDeduction = 0;
+ salary.WorkClothesDeduction = 0;
+ salary.TotalDeduction = 0;
+
+ salary.MonthlyTrainingSubsidy = 0;
+ salary.MonthlyTransportSubsidy = 0;
+ salary.LastMonthTrainingSubsidy = 0;
+ salary.LastMonthTransportSubsidy = 0;
+ salary.TotalSubsidy = 0;
+
+ salary.Bonus = 0;
+ salary.ReturnPhoneDeposit = 0;
+ salary.ReturnAccommodationDeposit = 0;
+
+ // 2.14 计算实发工资
+ salary.ActualSalary = salary.GrossSalary - salary.TotalDeduction + salary.TotalSubsidy + salary.Bonus;
+
+ // 2.15 初始化支付相关字段
+ salary.PaidAmount = 0;
+ salary.PendingAmount = salary.ActualSalary;
+ salary.LastMonthSupplement = 0;
+ salary.MonthlyTotalPayment = 0;
+
+ assistantSalaryList.Add(salary);
+ }
+
+ // 3. 保存数据
+ if (assistantSalaryList.Any())
+ {
+ // 先删除当月旧数据 (防止重复)
+ await _db.Deleteable()
+ .Where(x => x.StatisticsMonth == monthStr)
+ .ExecuteCommandAsync();
+
+ await _db.Insertable(assistantSalaryList).ExecuteCommandAsync();
+ }
+ }
+
+ ///
+ /// 计算提成比例
+ ///
+ /// 门店业绩
+ /// 门店生命线
+ /// 提成比例(0%/0.4%/0.6%)
+ private decimal CalculateCommissionRate(decimal storePerformance, decimal storeLifeline)
+ {
+ if (storeLifeline <= 0)
+ {
+ return 0;
+ }
+
+ decimal ratio = storePerformance / storeLifeline;
+
+ if (ratio < 0.7m)
+ {
+ // 门店业绩 < 门店生命线 × 70% → 0%
+ return 0;
+ }
+ else if (ratio < 1.0m)
+ {
+ // 门店生命线 × 70% ≤ 门店业绩 < 门店生命线 × 100% → 0.4%
+ return 0.004m;
+ }
+ else
+ {
+ // 门店业绩 ≥ 门店生命线 × 100% → 0.6%
+ return 0.006m;
+ }
+ }
+
+ ///
+ /// 计算底薪
+ ///
+ /// 门店分类(1=A类,2=B类,3=C类)
+ /// 底薪金额
+ private decimal CalculateBaseSalary(int storeCategory)
+ {
+ return storeCategory switch
+ {
+ 1 => 3000m, // A类门店
+ 2 => 3100m, // B类门店
+ 3 => 3200m, // C类门店
+ _ => throw new Exception($"门店分类值无效:{storeCategory},有效值为1(A类)、2(B类)、3(C类)")
+ };
+ }
+ }
+}
+
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqDirectorSalaryService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqDirectorSalaryService.cs
new file mode 100644
index 0000000..e3d4eb1
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqDirectorSalaryService.cs
@@ -0,0 +1,519 @@
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using NCC.Common.Filter;
+using NCC.Common.Helper;
+using NCC.Dependency;
+using NCC.DynamicApiController;
+using NCC.Extend.Entitys.Dto.LqDirectorSalary;
+using NCC.Extend.Entitys.lq_attendance_summary;
+using NCC.Extend.Entitys.lq_director_salary_statistics;
+using NCC.Extend.Entitys.lq_hytk_hytk;
+using NCC.Extend.Entitys.lq_kd_kdjlb;
+using NCC.Extend.Entitys.lq_md_target;
+using NCC.Extend.Entitys.lq_md_xdbhsj;
+using NCC.Extend.Entitys.lq_mdxx;
+using NCC.Extend.Entitys.lq_xh_hyhk;
+using NCC.Extend.Entitys.lq_xh_jksyj;
+using NCC.System.Entitys.Permission;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Yitter.IdGenerator;
+
+namespace NCC.Extend
+{
+ ///
+ /// 主任薪酬服务
+ ///
+ [ApiDescriptionSettings(Tag = "主任薪酬服务", Name = "LqDirectorSalary", Order = 302)]
+ [Route("api/Extend/[controller]")]
+ public class LqDirectorSalaryService : IDynamicApiController, ITransient
+ {
+ private readonly ISqlSugarClient _db;
+
+ ///
+ /// 初始化一个类型的新实例
+ ///
+ public LqDirectorSalaryService(ISqlSugarClient db)
+ {
+ _db = db;
+ }
+
+ ///
+ /// 获取主任工资列表
+ ///
+ /// 查询参数
+ /// 主任工资分页列表
+ [HttpGet("director")]
+ public async Task GetDirectorSalaryList([FromQuery] DirectorSalaryInput input)
+ {
+ var monthStr = $"{input.Year}{input.Month:D2}";
+
+ // 1. 检查当月是否已生成工资数据
+ var exists = await _db.Queryable()
+ .AnyAsync(x => x.StatisticsMonth == monthStr);
+
+ // 2. 如果没有数据,则进行计算
+ if (!exists)
+ {
+ await CalculateDirectorSalary(input.Year, input.Month);
+ }
+
+ // 3. 查询数据
+ var query = _db.Queryable()
+ .Where(x => x.StatisticsMonth == monthStr);
+
+ if (!string.IsNullOrEmpty(input.StoreId))
+ {
+ query = query.Where(x => x.StoreId == input.StoreId);
+ }
+
+ if (!string.IsNullOrEmpty(input.Keyword))
+ {
+ query = query.Where(x => x.EmployeeName.Contains(input.Keyword) || x.EmployeeId.Contains(input.Keyword));
+ }
+
+ var list = await query.Select(x => new DirectorSalaryOutput
+ {
+ Id = x.Id,
+ StoreName = x.StoreName,
+ EmployeeName = x.EmployeeName,
+ Position = x.Position,
+ StoreTotalPerformance = x.StoreTotalPerformance,
+ StoreBillingPerformance = x.StoreBillingPerformance,
+ StoreRefundPerformance = x.StoreRefundPerformance,
+ StoreLifeline = x.StoreLifeline,
+ PerformanceCompletionRate = x.PerformanceCompletionRate,
+ PerformanceReached = x.PerformanceReached,
+ HeadCountReached = x.HeadCountReached,
+ ConsumeReached = x.ConsumeReached,
+ AssessmentDeduction = x.AssessmentDeduction,
+ UnreachedIndicatorCount = x.UnreachedIndicatorCount,
+ HeadCount = x.HeadCount,
+ TargetHeadCount = x.TargetHeadCount,
+ StoreConsume = x.StoreConsume,
+ TargetConsume = x.TargetConsume,
+ CommissionRateBelowLifeline = x.CommissionRateBelowLifeline,
+ CommissionRateAboveLifeline = x.CommissionRateAboveLifeline,
+ CommissionAmountBelowLifeline = x.CommissionAmountBelowLifeline,
+ CommissionAmountAboveLifeline = x.CommissionAmountAboveLifeline,
+ TotalCommissionAmount = x.TotalCommissionAmount,
+ BaseSalary = x.BaseSalary,
+ ActualBaseSalary = x.ActualBaseSalary,
+ WorkingDays = x.WorkingDays,
+ LeaveDays = x.LeaveDays,
+ GrossSalary = x.GrossSalary,
+ ActualSalary = x.ActualSalary,
+ TotalDeduction = x.TotalDeduction,
+ TotalSubsidy = x.TotalSubsidy,
+ Bonus = x.Bonus,
+ ReturnPhoneDeposit = x.ReturnPhoneDeposit,
+ ReturnAccommodationDeposit = x.ReturnAccommodationDeposit,
+ MonthlyPaymentStatus = x.MonthlyPaymentStatus,
+ PaidAmount = x.PaidAmount,
+ PendingAmount = x.PendingAmount,
+ LastMonthSupplement = x.LastMonthSupplement,
+ MonthlyTotalPayment = x.MonthlyTotalPayment,
+ IsLocked = x.IsLocked,
+ UpdateTime = x.UpdateTime,
+ StoreType = x.StoreType,
+ StoreCategory = x.StoreCategory,
+ IsNewStore = x.IsNewStore,
+ NewStoreProtectionStage = x.NewStoreProtectionStage
+ })
+ .ToPagedListAsync(input.currentPage, input.pageSize);
+
+ return PageResult.SqlSugarPageResult(list);
+ }
+
+ ///
+ /// 计算主任工资
+ ///
+ /// 年份
+ /// 月份
+ ///
+ [HttpPost("calculate/director")]
+ public async Task CalculateDirectorSalary(int year, int month)
+ {
+ var startDate = new DateTime(year, month, 1);
+ var endDate = startDate.AddMonths(1).AddDays(-1);
+ var monthStr = $"{year}{month:D2}";
+
+ // 1. 获取基础数据
+
+ // 1.1 获取主任员工列表(从BASE_USER表,岗位为"主任")
+ var directorUserList = await _db.Queryable()
+ .Where(x => x.Gw == "主任" && x.DeleteMark == null && x.EnabledMark == 1)
+ .Select(x => new { x.Id, x.RealName, x.Mdid, x.Gw })
+ .ToListAsync();
+
+ if (!directorUserList.Any())
+ {
+ // 如果没有主任员工,直接返回
+ return;
+ }
+
+ // 1.2 门店信息 (lq_mdxx)
+ var storeList = await _db.Queryable().ToListAsync();
+ var storeDict = storeList.Where(x => !string.IsNullOrEmpty(x.Id)).ToDictionary(x => x.Id, x => x);
+
+ // 1.3 门店目标信息 (lq_md_target) - 包含门店生命线、目标人头、目标消耗
+ var storeTargets = await _db.Queryable()
+ .Where(x => x.Month == monthStr)
+ .ToListAsync();
+ var storeTargetDict = storeTargets.Where(x => !string.IsNullOrEmpty(x.StoreId))
+ .ToDictionary(x => x.StoreId, x => x);
+
+ // 1.4 门店新店保护信息 (lq_md_xdbhsj)
+ var newStoreProtectionList = await _db.Queryable()
+ .Where(x => x.Sfqy == 1)
+ .ToListAsync();
+ var newStoreProtectionDict = newStoreProtectionList
+ .Where(x => x.Bhkssj <= startDate && x.Bhjssj >= startDate)
+ .GroupBy(x => x.Mdid)
+ .ToDictionary(g => g.Key, g => g.First());
+
+ // 1.5 门店总业绩计算 (开单实付 - 退卡金额)
+ // 开单实付
+ var storeBillingList = await _db.Queryable()
+ .Where(x => x.Kdrq >= startDate && x.Kdrq <= endDate.AddDays(1) && x.IsEffective == 1)
+ .Select(x => new { x.Djmd, x.Sfyj })
+ .ToListAsync();
+ var storeBillingDict = storeBillingList
+ .Where(x => !string.IsNullOrEmpty(x.Djmd))
+ .GroupBy(x => x.Djmd)
+ .ToDictionary(g => g.Key, g => g.Sum(x => x.Sfyj));
+
+ // 退卡金额(使用F_ActualRefundAmount,如果没有则使用tkje)
+ var storeRefundList = await _db.Queryable()
+ .Where(x => x.Tksj >= startDate && x.Tksj <= endDate.AddDays(1) && x.IsEffective == 1)
+ .Select(x => new { x.Md, x.ActualRefundAmount, x.Tkje })
+ .ToListAsync();
+ var storeRefundDict = storeRefundList
+ .Where(x => !string.IsNullOrEmpty(x.Md))
+ .GroupBy(x => x.Md)
+ .ToDictionary(g => g.Key, g => g.Sum(x => x.ActualRefundAmount ?? x.Tkje ?? 0));
+
+ // 1.6 门店消耗金额统计(按门店统计当月总消耗)
+ // 使用SQL查询优化性能
+ var storeConsumeSql = $@"
+ SELECT
+ hyhk.md as StoreId,
+ COALESCE(SUM(jksyj.jksyj), 0) as ConsumeAmount
+ FROM lq_xh_jksyj jksyj
+ INNER JOIN lq_xh_hyhk hyhk ON jksyj.glkdbh = hyhk.F_Id
+ WHERE jksyj.F_IsEffective = 1
+ AND hyhk.F_IsEffective = 1
+ AND hyhk.hksj >= @startDate
+ AND hyhk.hksj <= @endDate
+ GROUP BY hyhk.md";
+
+ var storeConsumeData = await _db.Ado.SqlQueryAsync(storeConsumeSql, new { startDate, endDate = endDate.AddDays(1) });
+ var storeConsumeDict = storeConsumeData
+ .Where(x => x.StoreId != null)
+ .ToDictionary(x => x.StoreId.ToString(), x => Convert.ToDecimal(x.ConsumeAmount ?? 0));
+
+ // 1.7 进店消耗人数统计(有消费金额的,按门店按月去重客户数)
+ // 使用SQL查询优化性能
+ var headcountSql = $@"
+ SELECT
+ hyhk.md as StoreId,
+ COUNT(DISTINCT hyhk.hy) as HeadCount
+ FROM lq_xh_hyhk hyhk
+ WHERE hyhk.F_IsEffective = 1
+ AND DATE_FORMAT(hyhk.hksj, '%Y%m') = @monthStr
+ AND EXISTS (
+ SELECT 1
+ FROM lq_xh_jksyj jksyj
+ WHERE jksyj.glkdbh = hyhk.F_Id
+ AND jksyj.F_IsEffective = 1
+ AND jksyj.jksyj > 0
+ )
+ GROUP BY hyhk.md";
+
+ var headcountData = await _db.Ado.SqlQueryAsync(headcountSql, new { monthStr });
+ var headcountDict = headcountData
+ .Where(x => x.StoreId != null)
+ .ToDictionary(x => x.StoreId.ToString(), x => Convert.ToInt32(x.HeadCount));
+
+ // 1.8 考勤数据 (lq_attendance_summary)
+ var attendanceList = await _db.Queryable()
+ .Where(x => x.Year == year && x.Month == month && x.IsEffective == 1)
+ .ToListAsync();
+ var attendanceDict = attendanceList.ToDictionary(x => x.UserId, x => x);
+
+ // 2. 计算每个主任的工资
+ var directorSalaryList = new List();
+
+ foreach (var directorUser in directorUserList)
+ {
+ var salary = new LqDirectorSalaryStatisticsEntity
+ {
+ Id = YitIdHelper.NextId().ToString(),
+ EmployeeId = directorUser.Id,
+ EmployeeName = directorUser.RealName,
+ StatisticsMonth = monthStr,
+ Position = "主任",
+ CreateTime = DateTime.Now,
+ UpdateTime = DateTime.Now,
+ IsLocked = 0,
+ MonthlyPaymentStatus = "未发放"
+ };
+
+ // 2.1 填充门店信息
+ string storeId = directorUser.Mdid;
+ if (string.IsNullOrEmpty(storeId))
+ {
+ // 如果用户没有门店ID,跳过
+ continue;
+ }
+
+ salary.StoreId = storeId;
+
+ if (storeDict.ContainsKey(storeId))
+ {
+ var store = storeDict[storeId];
+ salary.StoreName = store.Dm;
+ salary.StoreType = store.StoreType;
+ salary.StoreCategory = store.StoreCategory;
+
+ // 数据校验:门店分类必须设置
+ if (!salary.StoreCategory.HasValue)
+ {
+ throw new Exception($"门店【{store.Dm}】的门店分类未设置,无法计算主任工资");
+ }
+ }
+
+ // 2.2 填充新店保护信息
+ bool isNewStore = false;
+ if (newStoreProtectionDict.ContainsKey(storeId))
+ {
+ var protection = newStoreProtectionDict[storeId];
+ salary.IsNewStore = "是";
+ salary.NewStoreProtectionStage = protection.Stage;
+ isNewStore = true;
+ }
+ else
+ {
+ salary.IsNewStore = "否";
+ salary.NewStoreProtectionStage = 0;
+ }
+
+ // 2.3 获取门店目标信息(门店生命线、目标人头、目标消耗)
+ if (!storeTargetDict.ContainsKey(storeId))
+ {
+ throw new Exception($"门店【{salary.StoreName ?? storeId}】在门店目标表中未配置{monthStr}月份的目标数据,无法计算主任工资");
+ }
+
+ var storeTarget = storeTargetDict[storeId];
+ salary.StoreLifeline = storeTarget.StoreLifeline;
+ salary.TargetHeadCount = storeTarget.StoreHeadcountTarget;
+ salary.TargetConsume = storeTarget.StoreConsumeTarget;
+
+ // 数据校验:门店生命线、目标人头、目标消耗必须设置
+ if (salary.StoreLifeline <= 0)
+ {
+ throw new Exception($"门店【{salary.StoreName ?? storeId}】的门店生命线未设置,无法计算主任工资");
+ }
+ if (salary.TargetHeadCount <= 0)
+ {
+ throw new Exception($"门店【{salary.StoreName ?? storeId}】的目标人头数未设置,无法计算主任工资");
+ }
+ if (!isNewStore && salary.TargetConsume <= 0)
+ {
+ throw new Exception($"门店【{salary.StoreName ?? storeId}】的目标消耗未设置,无法计算主任工资(老店需要考核消耗)");
+ }
+
+ // 2.4 计算门店业绩
+ decimal billing = storeBillingDict.ContainsKey(storeId) ? storeBillingDict[storeId] : 0;
+ decimal refund = storeRefundDict.ContainsKey(storeId) ? storeRefundDict[storeId] : 0;
+ salary.StoreBillingPerformance = billing;
+ salary.StoreRefundPerformance = refund;
+ salary.StoreTotalPerformance = billing - refund;
+
+ // 计算业绩完成率
+ if (salary.StoreLifeline > 0)
+ {
+ salary.PerformanceCompletionRate = salary.StoreTotalPerformance / salary.StoreLifeline;
+ }
+ else
+ {
+ salary.PerformanceCompletionRate = 0;
+ }
+
+ // 2.5 统计门店消耗金额
+ salary.StoreConsume = storeConsumeDict.ContainsKey(storeId) ? storeConsumeDict[storeId] : 0;
+
+ // 2.6 统计进店消耗人数
+ salary.HeadCount = headcountDict.ContainsKey(storeId) ? headcountDict[storeId] : 0;
+
+ // 2.7 计算考核指标(业绩、人头、消耗是否达标)
+ bool performanceReached = salary.StoreTotalPerformance >= salary.StoreLifeline;
+ bool headCountReached = salary.HeadCount >= salary.TargetHeadCount;
+ bool consumeReached = salary.StoreConsume >= salary.TargetConsume;
+
+ salary.PerformanceReached = performanceReached ? "是" : "否";
+ salary.HeadCountReached = headCountReached ? "是" : "否";
+ salary.ConsumeReached = consumeReached ? "是" : "否";
+
+ // 计算未达标指标数量
+ int unreachedCount = 0;
+ if (!performanceReached) unreachedCount++;
+ if (!headCountReached) unreachedCount++;
+ // 新店不考核消耗
+ if (!isNewStore && !consumeReached) unreachedCount++;
+
+ salary.UnreachedIndicatorCount = unreachedCount;
+ salary.AssessmentDeduction = unreachedCount * 500m;
+
+ // 2.8 计算底薪
+ salary.BaseSalary = 3500m; // 固定底薪3500元
+ salary.ActualBaseSalary = salary.BaseSalary - salary.AssessmentDeduction; // 实际底薪 = 底薪 - 考核扣款
+
+ // 2.9 计算阶梯提成
+ CalculateCommission(salary, isNewStore);
+
+ // 2.10 考勤数据
+ if (attendanceDict.ContainsKey(directorUser.Id))
+ {
+ var attendance = attendanceDict[directorUser.Id];
+ salary.WorkingDays = (int)attendance.WorkDays;
+ salary.LeaveDays = (int)attendance.LeaveDays;
+ }
+ else
+ {
+ salary.WorkingDays = 0;
+ salary.LeaveDays = 0;
+ }
+
+ // 2.11 计算应发工资
+ salary.GrossSalary = salary.ActualBaseSalary + salary.TotalCommissionAmount;
+
+ // 2.12 初始化扣款、补贴、奖金字段(默认值为0)
+ salary.MissingCard = 0;
+ salary.LateArrival = 0;
+ salary.LeaveDeduction = 0;
+ salary.SocialInsuranceDeduction = 0;
+ salary.RewardDeduction = 0;
+ salary.AccommodationDeduction = 0;
+ salary.StudyPeriodDeduction = 0;
+ salary.WorkClothesDeduction = 0;
+ salary.TotalDeduction = 0;
+
+ salary.MonthlyTrainingSubsidy = 0;
+ salary.MonthlyTransportSubsidy = 0;
+ salary.LastMonthTrainingSubsidy = 0;
+ salary.LastMonthTransportSubsidy = 0;
+ salary.TotalSubsidy = 0;
+
+ salary.Bonus = 0;
+ salary.ReturnPhoneDeposit = 0;
+ salary.ReturnAccommodationDeposit = 0;
+
+ // 2.13 计算实发工资
+ salary.ActualSalary = salary.GrossSalary - salary.TotalDeduction + salary.TotalSubsidy + salary.Bonus;
+
+ // 2.14 初始化支付相关字段
+ salary.PaidAmount = 0;
+ salary.PendingAmount = salary.ActualSalary;
+ salary.LastMonthSupplement = 0;
+ salary.MonthlyTotalPayment = 0;
+
+ directorSalaryList.Add(salary);
+ }
+
+ // 3. 保存数据
+ if (directorSalaryList.Any())
+ {
+ // 先删除当月旧数据 (防止重复)
+ await _db.Deleteable()
+ .Where(x => x.StatisticsMonth == monthStr)
+ .ExecuteCommandAsync();
+
+ await _db.Insertable(directorSalaryList).ExecuteCommandAsync();
+ }
+ }
+
+ ///
+ /// 计算阶梯提成
+ ///
+ /// 工资实体
+ /// 是否新店
+ private void CalculateCommission(LqDirectorSalaryStatisticsEntity salary, bool isNewStore)
+ {
+ if (salary.StoreLifeline <= 0)
+ {
+ // 如果门店生命线未设置,则没有提成
+ salary.CommissionRateBelowLifeline = 0;
+ salary.CommissionRateAboveLifeline = 0;
+ salary.CommissionAmountBelowLifeline = 0;
+ salary.CommissionAmountAboveLifeline = 0;
+ salary.TotalCommissionAmount = 0;
+ return;
+ }
+
+ decimal performance = salary.StoreTotalPerformance;
+ decimal lifeline = salary.StoreLifeline;
+
+ // 确定提成比例(根据新店/老店和门店分类)
+ decimal rateBelowLifeline;
+ decimal rateAboveLifeline;
+
+ if (isNewStore)
+ {
+ // 新店:统一标准,不区分门店分类
+ rateBelowLifeline = 0.02m; // 2%
+ rateAboveLifeline = 0.025m; // 2.5%
+ }
+ else
+ {
+ // 老店:根据门店分类确定提成比例
+ int? storeCategory = salary.StoreCategory;
+ if (!storeCategory.HasValue)
+ {
+ throw new Exception($"门店【{salary.StoreName}】的门店分类未设置,无法计算提成");
+ }
+
+ switch (storeCategory.Value)
+ {
+ case 1: // A类门店
+ rateBelowLifeline = 0.02m; // 2%
+ rateAboveLifeline = 0.025m; // 2.5%
+ break;
+ case 2: // B类门店
+ rateBelowLifeline = 0.025m; // 2.5%
+ rateAboveLifeline = 0.03m; // 3%
+ break;
+ case 3: // C类门店
+ rateBelowLifeline = 0.03m; // 3%
+ rateAboveLifeline = 0.035m; // 3.5%
+ break;
+ default:
+ throw new Exception($"门店【{salary.StoreName}】的门店分类值无效:{storeCategory.Value},有效值为1(A类)、2(B类)、3(C类)");
+ }
+ }
+
+ salary.CommissionRateBelowLifeline = rateBelowLifeline;
+ salary.CommissionRateAboveLifeline = rateAboveLifeline;
+
+ // 计算阶梯提成
+ if (performance <= lifeline)
+ {
+ // 业绩 ≤ 生命线:只计算≤生命线部分的提成
+ salary.CommissionAmountBelowLifeline = performance * rateBelowLifeline;
+ salary.CommissionAmountAboveLifeline = 0;
+ }
+ else
+ {
+ // 业绩 > 生命线:分别计算≤生命线部分和>生命线部分的提成
+ salary.CommissionAmountBelowLifeline = lifeline * rateBelowLifeline;
+ salary.CommissionAmountAboveLifeline = (performance - lifeline) * rateAboveLifeline;
+ }
+
+ salary.TotalCommissionAmount = salary.CommissionAmountBelowLifeline + salary.CommissionAmountAboveLifeline;
+ }
+ }
+}
+
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
index 84fb70c..9429339 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs
@@ -130,6 +130,7 @@ namespace NCC.Extend.LqKdKdjlb
output.upgradeLifeBeauty = entity.UpgradeLifeBeauty;
output.upgradeTechBeauty = entity.UpgradeTechBeauty;
output.upgradeMedicalBeauty = entity.UpgradeMedicalBeauty;
+ output.fileUrl = entity.F_FIleUrl;
if (!string.IsNullOrEmpty(entity.AppointmentId))
{
output.appointmentTime = await _db.Queryable().Where(x => x.Id == entity.AppointmentId).Select(x => x.Yysj).FirstAsync();
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqLaundryFlowService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqLaundryFlowService.cs
index 4455261..fa8160e 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqLaundryFlowService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqLaundryFlowService.cs
@@ -111,7 +111,7 @@ namespace NCC.Extend
LaundrySupplierId = input.LaundrySupplierId,
Quantity = input.Quantity,
LaundryPrice = supplier.LaundryPrice, // 记录历史价格
- TotalPrice = 0, // 送出时总费用为0
+ TotalPrice = input.Quantity * supplier.LaundryPrice, // 送出时总费用为数量 * 单价
Remark = input.Remark,
IsEffective = StatusEnum.有效.GetHashCode(),
CreateUser = _userManager.UserId,
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqReimbursementApplicationService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqReimbursementApplicationService.cs
index 8738a6b..17f1bd8 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqReimbursementApplicationService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqReimbursementApplicationService.cs
@@ -15,6 +15,9 @@ using System.Linq;
using System.Threading.Tasks;
using NCC.Extend.Entitys;
using NCC.Extend.Entitys.Dto.LqReimbursementApplication;
+using NCC.Extend.Entitys.lq_reimbursement_application_node;
+using NCC.Extend.Entitys.lq_reimbursement_application_node_user;
+using NCC.Extend.Entitys.lq_reimbursement_approval_record;
using Yitter.IdGenerator;
using NCC.Common.Helper;
using NCC.JsonSerialization;
@@ -49,16 +52,85 @@ namespace NCC.Extend.LqReimbursementApplication
}
///
- /// 获取报销申请表
+ /// 获取报销申请表详情(包含表单和流程信息)
///
- /// 参数
+ /// 申请编号
///
[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;
+
+ // 获取节点配置
+ var nodes = await _db.Queryable()
+ .Where(x => x.ApplicationId == id)
+ .OrderBy(x => x.NodeOrder)
+ .ToListAsync();
+
+ // 获取每个节点的审批人
+ var nodeUsers = await _db.Queryable()
+ .Where(x => x.ApplicationId == id)
+ .OrderBy(x => x.NodeOrder)
+ .OrderBy(x => x.SortOrder)
+ .ToListAsync();
+
+ // 获取审批历史
+ var approvalRecords = await _db.Queryable()
+ .Where(x => x.ApplicationId == id)
+ .OrderBy(x => x.NodeOrder)
+ .OrderBy(x => x.ApprovalTime)
+ .ToListAsync();
+
+ // 组装节点信息
+ var nodeList = nodes.Select(n => new
+ {
+ nodeId = n.Id,
+ nodeOrder = n.NodeOrder,
+ nodeName = n.NodeName,
+ approvalType = n.ApprovalType,
+ isRequired = n.IsRequired,
+ approvers = nodeUsers.Where(u => u.NodeId == n.Id).Select(u => new
+ {
+ userId = u.UserId,
+ userName = u.UserName,
+ sortOrder = u.SortOrder
+ }).ToList(),
+ approvalRecords = approvalRecords.Where(r => r.NodeId == n.Id).Select(r => new
+ {
+ approverName = r.ApproverName,
+ approvalResult = r.ApprovalResult,
+ approvalOpinion = r.ApprovalOpinion,
+ approvalTime = r.ApprovalTime
+ }).ToList()
+ }).ToList();
+
+ // 获取当前节点审批人
+ var currentApprovers = new List