fix(pricing): 统一将计价计算从向下取整改为四舍五入

统一修复所有计价相关模块的取整逻辑:将Lua计价函数中的直接返回改为四舍五入取整,同时将前后端代码中的Math.floor替换为Math.round,确保全链路的票价计算采用标准四舍五入规则,避免出现不合理的定价偏差。
This commit is contained in:
2026-07-09 23:40:08 +08:00
parent e07536e8c0
commit b3fdf36f84
6 changed files with 27 additions and 8 deletions
+15 -3
View File
@@ -8,6 +8,12 @@ const io = require('../io');
// Helper to get IP
const getIp = (req) => (req.headers['x-forwarded-for'] || '').toString().split(',')[0].trim() || req.ip || req.connection?.remoteAddress || '';
const resolveStationName = (code) => {
if (!code) return '';
const s = (DataService.getStations?.() || []).find(x => String(x.code).trim().toLowerCase() === String(code).trim().toLowerCase());
return s ? (s.name || s.cn_name || code) : code;
};
const normalizeTicketId = (v) => {
const s0 = String(v || '').replace(/\s+/g, '');
if (!s0) return '';
@@ -829,6 +835,7 @@ router.post('/ic-cards/:id/sync', async (req, res) => {
result: patch.last_result,
reason: patch.last_reason || undefined,
station_code: station_code || undefined,
station_name: resolveStationName(station_code),
entry_station: card.entry_station || undefined,
exit_station: card.exit_station || undefined,
fare: patch.last_fare,
@@ -916,6 +923,7 @@ router.post('/cards/open', async (req, res) => {
card_id: card.card_id,
order_code: voucher_code,
station_code,
station_name: resolveStationName(station_code),
device,
balance,
deposit,
@@ -1067,6 +1075,7 @@ router.post('/cards/check', async (req, res) => {
action,
result: 'pass',
station_code,
station_name: resolveStationName(station_code),
entry_station: station_code,
device,
balance: toMoney(card.balance)
@@ -1130,6 +1139,7 @@ router.post('/cards/check', async (req, res) => {
action,
result: 'pass',
station_code,
station_name: resolveStationName(station_code),
entry_station,
exit_station: station_code,
fare,
@@ -1186,6 +1196,7 @@ router.post('/tickets/sale', async (req, res) => {
train_type,
cost: cost || 0,
station_code: station_code || '',
station_name: resolveStationName(station_code),
device: device || 'unknown',
trips_total: tTotal,
trips_remaining: tRemain
@@ -1277,7 +1288,7 @@ router.post('/tickets/check', async (req, res) => {
const cur = idx[ticket_id];
const deny = async (reason) => {
const ev = { ts, type: 'check', ticket_id, action, result: 'deny', reason, station_code: station_code_raw || '', device };
const ev = { ts, type: 'check', ticket_id, action, result: 'deny', reason, station_code: station_code_raw || '', station_name: resolveStationName(station_code_raw), device };
await DataService.appendTicketEvent(ev);
await DataService.upsertTicketIndex({
ticket_id,
@@ -1329,7 +1340,7 @@ router.post('/tickets/check', async (req, res) => {
if (!matchesStation(start)) return deny('wrong_station');
if (entered && !exited) return deny('already_entered');
const ev = { ts, type: 'check', ticket_id, action, result: 'pass', station_code: start, device };
const ev = { ts, type: 'check', ticket_id, action, result: 'pass', station_code: start, station_name: resolveStationName(start), device };
await DataService.appendTicketEvent(ev);
await DataService.upsertTicketIndex({
ticket_id,
@@ -1355,7 +1366,7 @@ router.post('/tickets/check', async (req, res) => {
const newTripsRemaining = Math.max(0, (Number(tripsRemainEffective) || 0) - 1);
const shouldSetUsed = newTripsRemaining <= 0;
const ev = { ts, type: 'check', ticket_id, action, result: 'pass', station_code: terminal, device, trips_remaining: newTripsRemaining };
const ev = { ts, type: 'check', ticket_id, action, result: 'pass', station_code: terminal, station_name: resolveStationName(terminal), device, trips_remaining: newTripsRemaining };
await DataService.appendTicketEvent(ev);
await DataService.upsertTicketIndex({
ticket_id,
@@ -1399,6 +1410,7 @@ router.post('/tickets/status', async (req, res) => {
result,
reason,
station_code: station_code || '',
station_name: resolveStationName(station_code),
device: device || 'unknown',
trips_remaining,
rides_remaining