|
|
|
@@ -792,7 +792,7 @@ router.post('/ic-cards/:id/sync', async (req, res) => {
|
|
|
|
|
const syncTypeRaw = String(body.type || body.event_type || body.last_event || 'sync').trim().toLowerCase();
|
|
|
|
|
const syncType = syncTypeRaw === 'refill' ? 'topup' : (syncTypeRaw || 'sync');
|
|
|
|
|
const action = String(body.action || body.last_action || '').trim().toLowerCase();
|
|
|
|
|
const device = String(body.device || body.source || 'device').trim() || 'device';
|
|
|
|
|
const device = String(body.machine_id || body.machineId || body.device || body.source || 'device').trim() || 'device';
|
|
|
|
|
const station_code = resolveCurrentStationCode(body, resolveStation);
|
|
|
|
|
const entry_station = resolveStation(body.entry_station || body.start_station || current.entry_station || '');
|
|
|
|
|
const exit_station = resolveStation(body.exit_station || current.exit_station || '');
|
|
|
|
@@ -859,7 +859,7 @@ router.post('/cards/open', async (req, res) => {
|
|
|
|
|
const body = req.body || {};
|
|
|
|
|
const now = Date.now();
|
|
|
|
|
const voucher_code = normalizeOrderCode(body.voucher_code || body.order_code || body.code);
|
|
|
|
|
const device = String(body.device || 'ticket_machine').trim() || 'ticket_machine';
|
|
|
|
|
const device = String(body.machine_id || body.machineId || body.device || 'ticket_machine').trim() || 'ticket_machine';
|
|
|
|
|
const station_code = String(body.station_code || '').trim();
|
|
|
|
|
const holder_name = String(body.holder_name || '').trim();
|
|
|
|
|
const note = String(body.note || '').trim();
|
|
|
|
@@ -1004,7 +1004,7 @@ router.post('/cards/check', async (req, res) => {
|
|
|
|
|
const body = req.body || {};
|
|
|
|
|
const card_id = normalizeIcCardId(body.card_id);
|
|
|
|
|
const action = String(body.action || '').trim().toLowerCase();
|
|
|
|
|
const device = String(body.device || 'gate').trim() || 'gate';
|
|
|
|
|
const device = String(body.machine_id || body.machineId || body.device || 'gate').trim() || 'gate';
|
|
|
|
|
const ts = toFiniteNumberOrUndef(body.ts) ?? Date.now();
|
|
|
|
|
if (!card_id || !action) return res.status(400).json({ ok: false, error: 'card_id and action required' });
|
|
|
|
|
if (action !== 'entry' && action !== 'exit') return res.status(400).json({ ok: false, error: 'action must be entry/exit' });
|
|
|
|
@@ -1240,7 +1240,7 @@ router.post('/tickets/check', async (req, res) => {
|
|
|
|
|
const body = req.body || {};
|
|
|
|
|
const ticket_id = normalizeTicketId(body.ticket_id);
|
|
|
|
|
const action = String(body.action || '').trim().toLowerCase();
|
|
|
|
|
const device = String(body.device || 'gate');
|
|
|
|
|
const device = String(body.machine_id || body.machineId || body.device || 'gate');
|
|
|
|
|
const tsIn = Number(body.ts);
|
|
|
|
|
const ts = Number.isFinite(tsIn) ? tsIn : Date.now();
|
|
|
|
|
const hintTripsTotal = body.trips_total;
|
|
|
|
@@ -1378,7 +1378,7 @@ router.post('/tickets/check', async (req, res) => {
|
|
|
|
|
if (!entered) return deny('not_entered');
|
|
|
|
|
if (exited) return deny('already_exited');
|
|
|
|
|
|
|
|
|
|
const newTripsRemaining = Math.max(0, (Number(tripsRemainEffective) || 0) - 1);
|
|
|
|
|
const newTripsRemaining = isSingleTicket ? 0 : Math.max(0, (Number(tripsRemainEffective) || 0) - 1);
|
|
|
|
|
const shouldSetUsed = isSingleTicket ? true : (newTripsRemaining <= 0);
|
|
|
|
|
const ev = { ts, type: 'check', ticket_id, action, result: 'pass', station_code: exitCode, station_name: resolveStationName(exitCode), device, trips_remaining: newTripsRemaining };
|
|
|
|
|
await DataService.appendTicketEvent(ev);
|
|
|
|
|