| | |
| | | // 3. 内存聚合核心:定义支持动态键名累加的对象字典 |
| | | const siteAggMap = new Map<string, any>(); |
| | | |
| | | // 映射表:将明细里的 garbageType 映射到你 Entity 里的字段后缀 |
| | | // 源数据 garbageType 为大写 SW62001…SW62007,没有单独的 SW62 流水。 |
| | | // 先按 7 个子类分别累计,再把重量/碳排/销售额汇总进 SW62。 |
| | | const SW62_SUB_CODES = [ |
| | | 'SW62001', 'SW62002', 'SW62003', 'SW62004', |
| | | 'SW62005', 'SW62006', 'SW62007', |
| | | ]; |
| | | const SW62_SUB_SUFFIXES = SW62_SUB_CODES.map(code => `Sw${code.slice(2)}`); |
| | | const typeSuffixes = [ |
| | | 'Sw60', 'Sw61', 'Sw62', 'Sw63', 'Sw64', |
| | | ...SW62_SUB_SUFFIXES, |
| | | ]; |
| | | const typeKeyMap: Record<string, string> = { |
| | | 'SW60': 'Sw60', 'SW61': 'Sw61', 'SW62': 'Sw62', 'SW63': 'Sw63', 'SW64': 'Sw64', |
| | | 'Sw62001': 'Sw62001', 'Sw62002': 'Sw62002', 'Sw62003': 'Sw62003', |
| | | 'Sw62004': 'Sw62004', 'Sw62005': 'Sw62005', 'Sw62006': 'Sw62006', 'Sw62007': 'Sw62007' |
| | | SW60: 'Sw60', |
| | | SW61: 'Sw61', |
| | | SW63: 'Sw63', |
| | | SW64: 'Sw64', |
| | | }; |
| | | |
| | | for (const code of SW62_SUB_CODES) { |
| | | const suffix = `Sw${code.slice(2)}`; |
| | | typeKeyMap[code] = suffix; |
| | | typeKeyMap[suffix] = suffix; |
| | | } |
| | | |
| | | for (const row of rawDetails) { |
| | | const siteId = row.siteId; |
| | | const weight = Number(row.weight) || 0; |
| | | const gType = row.garbageType || 'SW64'; |
| | | const gType = String(row.garbageType || 'SW64').trim().toUpperCase(); |
| | | const fieldSuffix = typeKeyMap[gType]; |
| | | |
| | | // 初始化该站点的聚合结构 |
| | |
| | | weightTotal: 0, timeTotal: 0, carbonTotal: 0 |
| | | }; |
| | | // 动态初始化宽表里各子类型的 0 值 |
| | | Object.values(typeKeyMap).forEach(suffix => { |
| | | typeSuffixes.forEach(suffix => { |
| | | initData[`weight${suffix}`] = 0; |
| | | initData[`time${suffix}`] = 0; |
| | | initData[`carbon${suffix}`] = 0; |
| | |
| | | } |
| | | } |
| | | |
| | | // SW62 没有独立流水,用 7 个子类重量/碳排/销售额加总写入父类字段 |
| | | for (const agg of siteAggMap.values()) { |
| | | let weightSw62 = 0; |
| | | let carbonSw62 = 0; |
| | | let salesSw62 = 0; |
| | | let timeSw62 = 0; |
| | | for (const suffix of SW62_SUB_SUFFIXES) { |
| | | weightSw62 += Number(agg[`weight${suffix}`]) || 0; |
| | | carbonSw62 += Number(agg[`carbon${suffix}`]) || 0; |
| | | salesSw62 += Number(agg[`estimatedSales${suffix}`]) || 0; |
| | | timeSw62 = Math.max(timeSw62, Number(agg[`time${suffix}`]) || 0); |
| | | } |
| | | agg.weightSw62 = weightSw62; |
| | | agg.carbonSw62 = carbonSw62; |
| | | agg.estimatedSalesSw62 = salesSw62; |
| | | agg.timeSw62 = timeSw62; |
| | | } |
| | | |
| | | // 4. 高性能写入:转换为数组,利用批量插入 + ON DUPLICATE KEY UPDATE 提交给 MySQL |
| | | const finalRecords = Array.from(siteAggMap.values()).map(item => { |
| | | // 浮点数防精度丢失处理,保留两位小数 |