forked from lunanting/cangku
277 lines
6.8 KiB
JavaScript
277 lines
6.8 KiB
JavaScript
'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,
|
|
};
|