'use strict'; const dataSource = require('../config/database'); const localDb = dataSource.local; const RESULT_TABLE = 'op_JxBarcodeChannelDecisionResult'; function buildStockSelectionWhereClause({ statDate, poolType, ruleCode, barcode, }) { const whereParts = [ 'r.`statDate` = ?' ]; const params = [ statDate ]; if (poolType) { whereParts.push('r.`poolType` = ?'); params.push(poolType); } if (ruleCode) { whereParts.push('r.`ruleCode` = ?'); params.push(ruleCode); } if (barcode) { whereParts.push('CAST(r.`barcode` AS CHAR) LIKE ?'); params.push(`%${barcode}%`); } return { whereSql: `WHERE ${whereParts.join(' AND ')}`, params, }; } async function getLatestJxStockSelectionStatDate() { const rows = await localDb.query( `SELECT MAX(statDate) AS latestStatDate FROM \`${RESULT_TABLE}\`` ); return rows?.[0]?.latestStatDate || null; } async function getJxStockSelectionDataDates() { const rows = await localDb.query( ` SELECT statDate FROM \`${RESULT_TABLE}\` GROUP BY statDate ORDER BY statDate DESC LIMIT 30 ` ); return (rows || []).map((row) => ({ statDate: row.statDate, })); } async function getJxStockSelectionOverview({ statDate, poolType, ruleCode, barcode, }) { const latestStatDate = statDate || await getLatestJxStockSelectionStatDate(); if (!latestStatDate) { return { statDate: null, totals: { totalCount: 0, pickPoolCount: 0, goodPickPoolCount: 0, clearPoolCount: 0, banPoolCount: 0, reviewPoolCount: 0, naCount: 0, }, poolDistribution: [], ruleDistribution: [], summaryRows: [], ruleOptions: [], poolOptions: [], }; } const { whereSql, params } = buildStockSelectionWhereClause({ statDate: latestStatDate, poolType, ruleCode, barcode, }); const totalsRows = await localDb.query( ` SELECT ? AS statDate, COUNT(1) AS totalCount, SUM(CASE WHEN r.\`poolType\` = '选品待选池' THEN 1 ELSE 0 END) AS pickPoolCount, SUM(CASE WHEN r.\`poolType\` = '优质选品待选池' THEN 1 ELSE 0 END) AS goodPickPoolCount, SUM(CASE WHEN r.\`poolType\` = '清货待选池' THEN 1 ELSE 0 END) AS clearPoolCount, SUM(CASE WHEN r.\`poolType\` = '禁止选品' THEN 1 ELSE 0 END) AS banPoolCount, SUM(CASE WHEN r.\`poolType\` = '企划复盘' THEN 1 ELSE 0 END) AS reviewPoolCount, SUM(CASE WHEN r.\`ruleCode\` = 'NA' THEN 1 ELSE 0 END) AS naCount FROM \`${RESULT_TABLE}\` r ${whereSql} `, [latestStatDate, ...params] ); const poolDistribution = await localDb.query( ` SELECT r.\`poolType\` AS name, COUNT(1) AS value FROM \`${RESULT_TABLE}\` r ${whereSql} GROUP BY r.\`poolType\` ORDER BY COUNT(1) DESC, r.\`poolType\` `, params ); const ruleDistribution = await localDb.query( ` SELECT r.\`ruleCode\` AS name, COUNT(1) AS value FROM \`${RESULT_TABLE}\` r ${whereSql} GROUP BY r.\`ruleCode\` ORDER BY COUNT(1) DESC, r.\`ruleCode\` `, params ); const summaryRowsRaw = await localDb.query( ` SELECT r.\`ruleCode\` AS ruleCode, r.\`poolType\` AS poolType, MAX(r.\`ruleTag\`) AS ruleTag, COUNT(1) AS hitCount FROM \`${RESULT_TABLE}\` r ${whereSql} GROUP BY r.\`ruleCode\`, r.\`poolType\` ORDER BY COUNT(1) DESC, r.\`ruleCode\`, r.\`poolType\` `, params ); const ruleOptionsRows = await localDb.query( ` SELECT DISTINCT r.\`ruleCode\` AS ruleCode FROM \`${RESULT_TABLE}\` r WHERE r.\`statDate\` = ? ORDER BY r.\`ruleCode\` `, [latestStatDate] ); const poolOptionsRows = await localDb.query( ` SELECT DISTINCT r.\`poolType\` AS poolType FROM \`${RESULT_TABLE}\` r WHERE r.\`statDate\` = ? ORDER BY r.\`poolType\` `, [latestStatDate] ); const totals = totalsRows?.[0] || {}; const ruleOptions = (ruleOptionsRows || []).map((row) => row.ruleCode).filter(Boolean); const poolOptions = (poolOptionsRows || []).map((row) => row.poolType).filter(Boolean); const totalCount = Number(totals.totalCount || 0); const summaryRows = summaryRowsRaw.map((row, index) => ({ key: `${row.ruleCode || 'NA'}-${row.poolType || 'NA'}-${index}`, ruleCode: row.ruleCode, poolType: row.poolType, ruleTag: row.ruleTag, hitCount: Number(row.hitCount || 0), hitRate: totalCount > 0 ? Number(row.hitCount || 0) / totalCount : 0, })); return { statDate: latestStatDate, totals: { totalCount: Number(totals.totalCount || 0), pickPoolCount: Number(totals.pickPoolCount || 0), goodPickPoolCount: Number(totals.goodPickPoolCount || 0), clearPoolCount: Number(totals.clearPoolCount || 0), banPoolCount: Number(totals.banPoolCount || 0), reviewPoolCount: Number(totals.reviewPoolCount || 0), naCount: Number(totals.naCount || 0), }, poolDistribution: poolDistribution.map((row) => ({ name: row.name || '未分类', value: Number(row.value || 0) })), ruleDistribution: ruleDistribution.map((row) => ({ name: row.name || 'NA', value: Number(row.value || 0) })), summaryRows, ruleOptions, poolOptions, }; } async function getJxStockSelectionList({ statDate, poolType, ruleCode, barcode, page = 1, pageSize = 20, }) { const latestStatDate = statDate || await getLatestJxStockSelectionStatDate(); if (!latestStatDate) { return { statDate: null, page, pageSize, total: 0, rows: [], }; } const { whereSql, params } = buildStockSelectionWhereClause({ statDate: latestStatDate, poolType, ruleCode, barcode, }); const totalRows = await localDb.query( ` SELECT COUNT(1) AS total FROM \`${RESULT_TABLE}\` r ${whereSql} `, params ); const total = Number(totalRows?.[0]?.total || 0); const rows = total > 0 ? await localDb.query( ` SELECT r.\`statDate\` AS statDate, r.\`channelName\` AS channelName, r.\`barcode\` AS barcode, r.\`ruleCode\` AS ruleCode, r.\`poolType\` AS poolType, r.\`ruleTag\` AS ruleTag, r.\`ruleExplain\` AS ruleExplain FROM \`${RESULT_TABLE}\` r ${whereSql} ORDER BY CASE WHEN r.\`ruleCode\` = 'NA' THEN 1 ELSE 0 END, r.\`poolType\` ASC, r.\`ruleCode\` ASC, r.\`barcode\` ASC LIMIT ? OFFSET ? `, [ ...params, pageSize, (page - 1) * pageSize ] ) : []; return { statDate: latestStatDate, page, pageSize, total, rows: rows || [], }; } module.exports = { getLatestJxStockSelectionStatDate, getJxStockSelectionDataDates, getJxStockSelectionOverview, getJxStockSelectionList, };