feat: transaction state

This commit is contained in:
2026-02-07 12:34:53 +03:30
parent 957d5407c7
commit 98872dd5e4

View File

@@ -887,6 +887,7 @@ app.post("/sep-pay-request", async (req, res) => {
token,
rawResponse: response.data,
verified: false,
isPayed: false,
refNum: null,
traceNo: null,
securePan: null,
@@ -943,6 +944,26 @@ app.post("/sepverify", async (req, res) => {
});
}
// Update isPayed in database
try {
const coll = await getSepPayCollection();
await coll.updateOne(
{ token: Token },
{
$set: {
isPayed: true,
verified: true,
refNum: RefNum || null,
traceNo: TraceNo || null,
securePan: SecurePan || null,
updatedAt: new Date(),
},
},
);
} catch (dbErr) {
console.error("sepverify: failed to update isPayed in DB", dbErr);
}
return res.redirect(redirectUrl);
}
} catch (error) {
@@ -1133,7 +1154,6 @@ app.get("/all-payments/data", requireAllPaymentsAuth, async (req, res) => {
{ provincecode: new RegExp(escapeRegex(search), "i") },
{ resNum: new RegExp(escapeRegex(search), "i") },
];
// Province name filter: match search text against province names (e.g. همدان, تست)
Object.keys(PROVINCE_NAMES).forEach((code) => {
if (PROVINCE_NAMES[code].indexOf(search) !== -1) {
filter.$or.push({ provincecode: code });
@@ -1315,6 +1335,8 @@ app.get("/all-payments", async (req, res) => {
.cell-msg { font-size: 0.75rem; margin-top: 4px; }
.cell-msg.ok { color: var(--success); }
.cell-msg.err { color: var(--danger); }
.status-paid { display: inline-block; padding: 4px 12px; border-radius: 9999px; font-size: 0.8125rem; font-weight: 600; background: #dcfce7; color: #166534; }
.status-unpaid { display: inline-block; padding: 4px 12px; border-radius: 9999px; font-size: 0.8125rem; font-weight: 600; background: #fef2f2; color: #991b1b; }
.actions-cell { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.pagination { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 16px; padding: 16px; border-top: 1px solid var(--border); }
.pagination-info { font-size: 0.8125rem; color: var(--text-muted); }
@@ -1415,7 +1437,9 @@ app.get("/all-payments", async (req, res) => {
var rowNum = (state.page - 1) * state.limit + (index + 1);
var amountVal = item.amountRaw != null ? item.amountRaw : item.amount;
var amountStr = amountVal != null ? Number(amountVal).toLocaleString('fa-IR') : '-';
return '<tr data-id="' + id + '"><td>' + rowNum + '</td><td>' + amountStr + '</td><td>' + (item.provinceName || '-') + '</td><td>' + (item.isLink ? 'بله' : 'خیر') + '</td><td>' + (item.phone || '-') + '</td><td>' + createdAt + '</td><td><div class="actions-cell"><button type="button" class="btn btn-primary btn-sm btn-send" data-id="' + id + '">ارسال به سرور</button><button type="button" class="btn btn-danger btn-sm btn-remove" data-id="' + id + '">حذف</button><div class="cell-msg" id="msg-' + id + '"></div></div></td></tr>';
var statusClass = item.isPayed ? 'status-paid' : 'status-unpaid';
var statusText = item.isPayed ? 'پرداخت شده' : 'پرداخت نشده';
return '<tr data-id="' + id + '"><td>' + rowNum + '</td><td>' + (item.provincecode || '-') + '</td><td>' + amountStr + '</td><td>' + (item.provinceName || '-') + '</td><td>' + (item.isLink ? 'بله' : 'خیر') + '</td><td>' + (item.phone || '-') + '</td><td>' + createdAt + '</td><td><span class="' + statusClass + '">' + statusText + '</span></td><td><div class="actions-cell"><button type="button" class="btn btn-primary btn-sm btn-send" data-id="' + id + '">ارسال به سرور</button><button type="button" class="btn btn-danger btn-sm btn-remove" data-id="' + id + '">حذف</button><div class="cell-msg" id="msg-' + id + '"></div></div></td></tr>';
}
function bindRowEvents(fragment) {
@@ -1494,7 +1518,7 @@ app.get("/all-payments", async (req, res) => {
paginationEl.style.display = 'none';
return;
}
var thead = '<table><thead><tr><th>ردیف</th><th>مبلغ</th><th>استان</th><th>لینک</th><th>موبایل</th><th>تاریخ</th><th>عملیات</th></tr></thead><tbody>';
var thead = '<table><thead><tr><th>ردیف</th><th>شناسه تراکنش</th><th>مبلغ</th><th>استان</th><th>لینک</th><th>موبایل</th><th>تاریخ</th><th>وضعیت</th><th>عملیات</th></tr></thead><tbody>';
var rows = list.map(function(item, i) { return renderRow(item, i); }).join('');
contentEl.innerHTML = thead + rows + '</tbody></table>';
bindRowEvents(contentEl);