Commit db08ff8c22d0617ed83b80b40eaa75b8a715d0c9

Authored by “wangming”
1 parent c1bcfb6c

修复店长工资产品物料查询逻辑并添加成本字段显示

1. 修复产品物料查询逻辑:
   - 修改所有工资服务中的产品物料查询逻辑
   - 从'11月特殊规则'改为'计算本月工资时使用上月数据'
   - 支持跨年处理(1月工资使用上一年12月数据)

2. 添加成本信息字段显示:
   - 在店长工资列表页面添加成本信息分组(销售业绩、产品物料、合作项目成本、店内支出、洗毛巾费用)
   - 在店长工资详情页面添加成本信息部分
   - 在导出功能中添加成本相关字段
   - 在导入功能中添加成本相关字段的处理逻辑

3. 修改的文件:
   - LqStoreManagerSalaryService.cs(店长工资服务)
   - LqDirectorSalaryService.cs(主任工资服务)
   - LqBusinessUnitManagerSalaryService.cs(事业部总经理/经理工资服务)
   - shop.vue(店长工资列表页面)
   - shop-detail-dialog.vue(店长工资详情页面)
   - LqBusinessUnitManagerSalaryStatisticsEntity.cs(实体类注释)
antis-ncc-admin/src/views/wageManagement/shop-detail-dialog.vue
... ... @@ -131,6 +131,38 @@
131 131 </div>
132 132 </div>
133 133  
  134 + <!-- 成本信息 -->
  135 + <div class="detail-section">
  136 + <div class="section-title">
  137 + <i class="el-icon-data-line"></i>
  138 + <span>成本信息</span>
  139 + </div>
  140 + <div class="section-content">
  141 + <div class="info-row">
  142 + <div class="info-item">
  143 + <span class="label">销售业绩:</span>
  144 + <span class="value">{{ formatMoney(detailData.SalesPerformance) }}</span>
  145 + </div>
  146 + <div class="info-item">
  147 + <span class="label">产品物料:</span>
  148 + <span class="value">{{ formatMoney(detailData.ProductMaterial) }}</span>
  149 + </div>
  150 + <div class="info-item">
  151 + <span class="label">合作项目成本:</span>
  152 + <span class="value">{{ formatMoney(detailData.CooperationCost) }}</span>
  153 + </div>
  154 + <div class="info-item">
  155 + <span class="label">店内支出:</span>
  156 + <span class="value">{{ formatMoney(detailData.StoreExpense) }}</span>
  157 + </div>
  158 + <div class="info-item">
  159 + <span class="label">洗毛巾费用:</span>
  160 + <span class="value">{{ formatMoney(detailData.LaundryCost) }}</span>
  161 + </div>
  162 + </div>
  163 + </div>
  164 + </div>
  165 +
134 166 <!-- 提成信息 -->
135 167 <div class="detail-section">
136 168 <div class="section-title">
... ...
antis-ncc-admin/src/views/wageManagement/shop.vue
... ... @@ -229,6 +229,35 @@
229 229 </el-table-column>
230 230 </el-table-column>
231 231  
  232 + <!-- 成本信息 -->
  233 + <el-table-column label="成本信息" align="center">
  234 + <el-table-column prop="SalesPerformance" label="销售业绩" width="120" align="center">
  235 + <template slot-scope="scope">
  236 + <span>{{ formatMoney(scope.row.SalesPerformance) }}</span>
  237 + </template>
  238 + </el-table-column>
  239 + <el-table-column prop="ProductMaterial" label="产品物料" width="120" align="center">
  240 + <template slot-scope="scope">
  241 + <span>{{ formatMoney(scope.row.ProductMaterial) }}</span>
  242 + </template>
  243 + </el-table-column>
  244 + <el-table-column prop="CooperationCost" label="合作项目成本" width="140" align="center">
  245 + <template slot-scope="scope">
  246 + <span>{{ formatMoney(scope.row.CooperationCost) }}</span>
  247 + </template>
  248 + </el-table-column>
  249 + <el-table-column prop="StoreExpense" label="店内支出" width="120" align="center">
  250 + <template slot-scope="scope">
  251 + <span>{{ formatMoney(scope.row.StoreExpense) }}</span>
  252 + </template>
  253 + </el-table-column>
  254 + <el-table-column prop="LaundryCost" label="洗毛巾费用" width="120" align="center">
  255 + <template slot-scope="scope">
  256 + <span>{{ formatMoney(scope.row.LaundryCost) }}</span>
  257 + </template>
  258 + </el-table-column>
  259 + </el-table-column>
  260 +
232 261 <!-- 提成信息 -->
233 262 <el-table-column label="提成信息" align="center">
234 263 <el-table-column prop="GrossProfit" label="毛利" width="120" align="center">
... ... @@ -799,6 +828,11 @@ export default {
799 828 '消耗是否达标',
800 829 '未达标指标数',
801 830 '考核扣款',
  831 + '销售业绩',
  832 + '产品物料',
  833 + '合作项目成本',
  834 + '店内支出',
  835 + '洗毛巾费用',
802 836 '毛利',
803 837 '提成比例',
804 838 '提成金额',
... ... @@ -859,6 +893,11 @@ export default {
859 893 item.ConsumeReached || '否',
860 894 item.UnreachedIndicatorCount || '0',
861 895 this.formatMoney(item.AssessmentDeduction),
  896 + this.formatMoney(item.SalesPerformance),
  897 + this.formatMoney(item.ProductMaterial),
  898 + this.formatMoney(item.CooperationCost),
  899 + this.formatMoney(item.StoreExpense),
  900 + this.formatMoney(item.LaundryCost),
862 901 this.formatMoney(item.GrossProfit),
863 902 this.formatPercent(item.CommissionRate),
864 903 this.formatMoney(item.CommissionAmount),
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Entity/lq_business_unit_manager_salary_statistics/LqBusinessUnitManagerSalaryStatisticsEntity.cs
... ... @@ -78,7 +78,7 @@ namespace NCC.Extend.Entitys.lq_business_unit_manager_salary_statistics
78 78 public decimal SalesPerformance { get; set; }
79 79  
80 80 /// <summary>
81   - /// 产品物料(仓库领用金额,注意11月特殊规则:11月工资算10月数据)
  81 + /// 产品物料(仓库领用金额,使用上月数据:计算本月工资时使用上月数据)
82 82 /// </summary>
83 83 [SugarColumn(ColumnName = "F_ProductMaterial")]
84 84 public decimal ProductMaterial { get; set; }
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqBusinessUnitManagerSalaryService.cs
... ... @@ -272,12 +272,18 @@ namespace NCC.Extend
272 272 .GroupBy(x => x.Md)
273 273 .ToDictionary(g => g.Key, g => g.Sum(x => x.ActualRefundAmount ?? x.Tkje ?? 0));
274 274  
275   - // 1.7 产品物料统计(仓库领用金额,注意11月特殊规则)
  275 + // 1.7 产品物料统计(仓库领用金额,使用上月数据)
  276 + // 计算本月工资时,使用上月数据(如:计算12月工资,使用11月数据)
276 277 var queryMonth = monthStr;
277   - if (month == 11)
  278 + if (month == 1)
278 279 {
279   - // 11月工资算10月数据
280   - queryMonth = $"{year}10";
  280 + // 1月工资使用上一年12月数据
  281 + queryMonth = $"{year - 1}12";
  282 + }
  283 + else
  284 + {
  285 + // 其他月份使用上一个月数据
  286 + queryMonth = $"{year}{(month - 1):D2}";
281 287 }
282 288 var productMaterialSql = $@"
283 289 SELECT
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqDirectorSalaryService.cs
... ... @@ -360,12 +360,18 @@ namespace NCC.Extend
360 360 .ToListAsync();
361 361 var attendanceDict = attendanceList.ToDictionary(x => x.UserId, x => x);
362 362  
363   - // 1.9 产品物料统计(仓库领用金额,注意11月特殊规则)
  363 + // 1.9 产品物料统计(仓库领用金额,使用上月数据)
  364 + // 计算本月工资时,使用上月数据(如:计算12月工资,使用11月数据)
364 365 var queryMonth = monthStr;
365   - if (month == 11)
  366 + if (month == 1)
366 367 {
367   - // 11月工资算10月数据
368   - queryMonth = $"{year}10";
  368 + // 1月工资使用上一年12月数据
  369 + queryMonth = $"{year - 1}12";
  370 + }
  371 + else
  372 + {
  373 + // 其他月份使用上一个月数据
  374 + queryMonth = $"{year}{(month - 1):D2}";
369 375 }
370 376 var productMaterialSql = $@"
371 377 SELECT
... ... @@ -520,7 +526,7 @@ namespace NCC.Extend
520 526 salary.SalesPerformance = billing - refund;
521 527  
522 528 // 2.5 统计各项成本
523   - // 产品物料(注意11月特殊规则已在查询时处理
  529 + // 产品物料(使用上月数据
524 530 salary.ProductMaterial = productMaterialDict.ContainsKey(storeId) ? productMaterialDict[storeId] : 0;
525 531  
526 532 // 合作项目成本
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqStoreManagerSalaryService.cs
... ... @@ -314,12 +314,18 @@ namespace NCC.Extend
314 314 .ToListAsync();
315 315 var attendanceDict = attendanceList.ToDictionary(x => x.UserId, x => x);
316 316  
317   - // 1.9 产品物料统计(仓库领用金额,注意11月特殊规则)
  317 + // 1.9 产品物料统计(仓库领用金额,使用上月数据)
  318 + // 计算本月工资时,使用上月数据(如:计算12月工资,使用11月数据)
318 319 var queryMonth = monthStr;
319   - if (month == 11)
  320 + if (month == 1)
320 321 {
321   - // 11月工资算10月数据
322   - queryMonth = $"{year}10";
  322 + // 1月工资使用上一年12月数据
  323 + queryMonth = $"{year - 1}12";
  324 + }
  325 + else
  326 + {
  327 + // 其他月份使用上一个月数据
  328 + queryMonth = $"{year}{(month - 1):D2}";
323 329 }
324 330 var productMaterialSql = $@"
325 331 SELECT
... ... @@ -543,7 +549,7 @@ namespace NCC.Extend
543 549 // 销售业绩 = 开单业绩 - 退款业绩
544 550 salary.SalesPerformance = salary.StoreTotalPerformance;
545 551  
546   - // 产品物料(注意11月特殊规则已在查询时处理
  552 + // 产品物料(使用上月数据
547 553 salary.ProductMaterial = productMaterialDict.ContainsKey(storeId) ? productMaterialDict[storeId] : 0;
548 554  
549 555 // 合作项目成本
... ... @@ -946,11 +952,11 @@ namespace NCC.Extend
946 952 // 批量更新
947 953 if (lockedCount > 0 || unlockedCount > 0)
948 954 {
949   - var salariesToUpdate = salaries.Where(s =>
950   - (input.IsLocked && s.IsLocked == 0) ||
  955 + var salariesToUpdate = salaries.Where(s =>
  956 + (input.IsLocked && s.IsLocked == 0) ||
951 957 (!input.IsLocked && s.IsLocked == 1 && s.EmployeeConfirmStatus != 1)
952 958 ).ToList();
953   -
  959 +
954 960 if (salariesToUpdate.Any())
955 961 {
956 962 await _db.Updateable(salariesToUpdate)
... ... @@ -962,10 +968,10 @@ namespace NCC.Extend
962 968 var action = input.IsLocked ? "锁定" : "解锁";
963 969 var count = input.IsLocked ? lockedCount : unlockedCount;
964 970 var message = $"{action}成功:{count}条";
965   -
  971 +
966 972 if (alreadyLockedCount > 0)
967 973 message += $",跳过{alreadyLockedCount}条(已是{action}状态)";
968   -
  974 +
969 975 if (skippedCount > 0)
970 976 message += $",跳过{skippedCount}条(已确认的记录不能解锁)";
971 977  
... ... @@ -1004,7 +1010,7 @@ namespace NCC.Extend
1004 1010 {
1005 1011 if (file == null || file.Length == 0)
1006 1012 throw NCCException.Oh("请选择要上传的Excel文件");
1007   -
  1013 +
1008 1014 var allowedExtensions = new[] { ".xlsx", ".xls" };
1009 1015 var fileExtension = Path.GetExtension(file.FileName).ToLowerInvariant();
1010 1016 if (!allowedExtensions.Contains(fileExtension))
... ... @@ -1054,7 +1060,7 @@ namespace NCC.Extend
1054 1060  
1055 1061 var firstColumnValue = GetColumnValue(0);
1056 1062 bool isOldFormat = !string.IsNullOrWhiteSpace(firstColumnValue) && (firstColumnValue == "门店名称" || (!long.TryParse(firstColumnValue, out _) && firstColumnValue.Length > 20));
1057   -
  1063 +
1058 1064 int storeNameIndex = isOldFormat ? 0 : 1;
1059 1065 int employeeNameIndex = isOldFormat ? 1 : 2;
1060 1066 int offset = isOldFormat ? 0 : 1;
... ... @@ -1088,7 +1094,7 @@ namespace NCC.Extend
1088 1094 {
1089 1095 existing = await _db.Queryable<LqStoreManagerSalaryStatisticsEntity>()
1090 1096 .Where(x => x.Id == id).FirstAsync();
1091   -
  1097 +
1092 1098 if (existing != null && (existing.IsLocked == 1 || existing.EmployeeConfirmStatus == 1))
1093 1099 {
1094 1100 skippedCount++;
... ... @@ -1124,50 +1130,55 @@ namespace NCC.Extend
1124 1130 entity.ConsumeReached = GetColumnValue(14 + offset);
1125 1131 entity.UnreachedIndicatorCount = ParseInt(GetColumnValue(15 + offset));
1126 1132 entity.AssessmentDeduction = ParseDecimal(GetColumnValue(16 + offset));
1127   - entity.GrossProfit = ParseDecimal(GetColumnValue(17 + offset));
1128   - entity.CommissionRate = ParseDecimal(GetColumnValue(18 + offset));
1129   - entity.CommissionAmount = ParseDecimal(GetColumnValue(19 + offset));
1130   - entity.BaseSalary = ParseDecimal(GetColumnValue(20 + offset));
1131   - entity.ActualBaseSalary = ParseDecimal(GetColumnValue(21 + offset));
1132   - entity.GrossSalary = ParseDecimal(GetColumnValue(22 + offset));
1133   - entity.WorkingDays = ParseInt(GetColumnValue(23 + offset));
1134   - entity.LeaveDays = ParseInt(GetColumnValue(24 + offset));
1135   - // Excel中的车补(25)、少休费(26)、全勤奖(27)字段在实体类中没有对应字段,跳过
1136   - entity.MonthlyTrainingSubsidy = ParseDecimal(GetColumnValue(28 + offset));
1137   - entity.MonthlyTransportSubsidy = ParseDecimal(GetColumnValue(29 + offset));
1138   - entity.LastMonthTrainingSubsidy = ParseDecimal(GetColumnValue(30 + offset));
1139   - entity.LastMonthTransportSubsidy = ParseDecimal(GetColumnValue(31 + offset));
1140   - entity.TotalSubsidy = ParseDecimal(GetColumnValue(32 + offset));
1141   - entity.MissingCard = ParseDecimal(GetColumnValue(33 + offset));
1142   - entity.LateArrival = ParseDecimal(GetColumnValue(34 + offset));
1143   - entity.LeaveDeduction = ParseDecimal(GetColumnValue(35 + offset));
1144   - entity.SocialInsuranceDeduction = ParseDecimal(GetColumnValue(36 + offset));
1145   - entity.RewardDeduction = ParseDecimal(GetColumnValue(37 + offset));
1146   - entity.AccommodationDeduction = ParseDecimal(GetColumnValue(38 + offset));
1147   - entity.StudyPeriodDeduction = ParseDecimal(GetColumnValue(39 + offset));
1148   - entity.WorkClothesDeduction = ParseDecimal(GetColumnValue(40 + offset));
1149   - entity.TotalDeduction = ParseDecimal(GetColumnValue(41 + offset));
1150   - entity.Bonus = ParseDecimal(GetColumnValue(42 + offset));
1151   - entity.ReturnPhoneDeposit = ParseDecimal(GetColumnValue(43 + offset));
1152   - entity.ReturnAccommodationDeposit = ParseDecimal(GetColumnValue(44 + offset));
1153   - entity.LastMonthSupplement = ParseDecimal(GetColumnValue(45 + offset));
1154   - entity.ActualSalary = ParseDecimal(GetColumnValue(46 + offset));
1155   - entity.MonthlyPaymentStatus = GetColumnValue(47 + offset);
1156   - entity.PaidAmount = ParseDecimal(GetColumnValue(48 + offset));
1157   - entity.PendingAmount = ParseDecimal(GetColumnValue(49 + offset));
1158   - entity.MonthlyTotalPayment = ParseDecimal(GetColumnValue(50 + offset));
  1133 + entity.SalesPerformance = ParseDecimal(GetColumnValue(17 + offset));
  1134 + entity.ProductMaterial = ParseDecimal(GetColumnValue(18 + offset));
  1135 + entity.CooperationCost = ParseDecimal(GetColumnValue(19 + offset));
  1136 + entity.StoreExpense = ParseDecimal(GetColumnValue(20 + offset));
  1137 + entity.LaundryCost = ParseDecimal(GetColumnValue(21 + offset));
  1138 + entity.GrossProfit = ParseDecimal(GetColumnValue(22 + offset));
  1139 + entity.CommissionRate = ParseDecimal(GetColumnValue(23 + offset));
  1140 + entity.CommissionAmount = ParseDecimal(GetColumnValue(24 + offset));
  1141 + entity.BaseSalary = ParseDecimal(GetColumnValue(25 + offset));
  1142 + entity.ActualBaseSalary = ParseDecimal(GetColumnValue(26 + offset));
  1143 + entity.GrossSalary = ParseDecimal(GetColumnValue(27 + offset));
  1144 + entity.WorkingDays = ParseInt(GetColumnValue(28 + offset));
  1145 + entity.LeaveDays = ParseInt(GetColumnValue(29 + offset));
  1146 + // Excel中的车补(30)、少休费(31)、全勤奖(32)字段在实体类中没有对应字段,跳过
  1147 + entity.MonthlyTrainingSubsidy = ParseDecimal(GetColumnValue(33 + offset));
  1148 + entity.MonthlyTransportSubsidy = ParseDecimal(GetColumnValue(34 + offset));
  1149 + entity.LastMonthTrainingSubsidy = ParseDecimal(GetColumnValue(35 + offset));
  1150 + entity.LastMonthTransportSubsidy = ParseDecimal(GetColumnValue(36 + offset));
  1151 + entity.TotalSubsidy = ParseDecimal(GetColumnValue(37 + offset));
  1152 + entity.MissingCard = ParseDecimal(GetColumnValue(38 + offset));
  1153 + entity.LateArrival = ParseDecimal(GetColumnValue(39 + offset));
  1154 + entity.LeaveDeduction = ParseDecimal(GetColumnValue(40 + offset));
  1155 + entity.SocialInsuranceDeduction = ParseDecimal(GetColumnValue(41 + offset));
  1156 + entity.RewardDeduction = ParseDecimal(GetColumnValue(42 + offset));
  1157 + entity.AccommodationDeduction = ParseDecimal(GetColumnValue(43 + offset));
  1158 + entity.StudyPeriodDeduction = ParseDecimal(GetColumnValue(44 + offset));
  1159 + entity.WorkClothesDeduction = ParseDecimal(GetColumnValue(45 + offset));
  1160 + entity.TotalDeduction = ParseDecimal(GetColumnValue(46 + offset));
  1161 + entity.Bonus = ParseDecimal(GetColumnValue(47 + offset));
  1162 + entity.ReturnPhoneDeposit = ParseDecimal(GetColumnValue(48 + offset));
  1163 + entity.ReturnAccommodationDeposit = ParseDecimal(GetColumnValue(49 + offset));
  1164 + entity.LastMonthSupplement = ParseDecimal(GetColumnValue(50 + offset));
  1165 + entity.ActualSalary = ParseDecimal(GetColumnValue(51 + offset));
  1166 + entity.MonthlyPaymentStatus = GetColumnValue(52 + offset);
  1167 + entity.PaidAmount = ParseDecimal(GetColumnValue(53 + offset));
  1168 + entity.PendingAmount = ParseDecimal(GetColumnValue(54 + offset));
  1169 + entity.MonthlyTotalPayment = ParseDecimal(GetColumnValue(55 + offset));
1159 1170 // 处理门店分类(Excel中可能是"A类"、"B类"、"C类")
1160   - var storeCategoryStr = GetColumnValue(51 + offset);
  1171 + var storeCategoryStr = GetColumnValue(56 + offset);
1161 1172 if (!string.IsNullOrWhiteSpace(storeCategoryStr))
1162 1173 {
1163 1174 if (storeCategoryStr.Contains("A") || storeCategoryStr == "1") entity.StoreCategory = 1;
1164 1175 else if (storeCategoryStr.Contains("B") || storeCategoryStr == "2") entity.StoreCategory = 2;
1165 1176 else if (storeCategoryStr.Contains("C") || storeCategoryStr == "3") entity.StoreCategory = 3;
1166 1177 }
1167   - entity.IsNewStore = GetColumnValue(52 + offset) == "是" ? "是" : "否";
1168   - entity.NewStoreProtectionStage = ParseInt(GetColumnValue(53 + offset));
1169   - // 处理锁定状态(第55列,索引54)
1170   - var isLockedStr = GetColumnValue(54 + offset);
  1178 + entity.IsNewStore = GetColumnValue(57 + offset) == "是" ? "是" : "否";
  1179 + entity.NewStoreProtectionStage = ParseInt(GetColumnValue(58 + offset));
  1180 + // 处理锁定状态(第60列,索引59)
  1181 + var isLockedStr = GetColumnValue(59 + offset);
1171 1182 if (isLockedStr == "已锁定" || isLockedStr == "1") entity.IsLocked = 1;
1172 1183 else entity.IsLocked = 0;
1173 1184  
... ... @@ -1189,7 +1200,7 @@ namespace NCC.Extend
1189 1200 if (!string.IsNullOrEmpty(user.Mdid) && string.IsNullOrWhiteSpace(storeName))
1190 1201 entity.StoreId = user.Mdid;
1191 1202 }
1192   -
  1203 +
1193 1204 if (!string.IsNullOrWhiteSpace(storeName) && string.IsNullOrEmpty(entity.StoreId))
1194 1205 {
1195 1206 var store = await _db.Queryable<LqMdxxEntity>()
... ... @@ -1198,7 +1209,7 @@ namespace NCC.Extend
1198 1209 }
1199 1210 }
1200 1211 }
1201   -
  1212 +
1202 1213 entity.UpdateTime = DateTime.Now;
1203 1214 if (existing != null) recordsToUpdate.Add(entity);
1204 1215 else recordsToInsert.Add(entity);
... ...