feat: transaction state
This commit is contained in:
30
index.js
30
index.js
@@ -887,6 +887,7 @@ app.post("/sep-pay-request", async (req, res) => {
|
|||||||
token,
|
token,
|
||||||
rawResponse: response.data,
|
rawResponse: response.data,
|
||||||
verified: false,
|
verified: false,
|
||||||
|
isPayed: false,
|
||||||
refNum: null,
|
refNum: null,
|
||||||
traceNo: null,
|
traceNo: null,
|
||||||
securePan: 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);
|
return res.redirect(redirectUrl);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -1133,7 +1154,6 @@ app.get("/all-payments/data", requireAllPaymentsAuth, async (req, res) => {
|
|||||||
{ provincecode: new RegExp(escapeRegex(search), "i") },
|
{ provincecode: new RegExp(escapeRegex(search), "i") },
|
||||||
{ resNum: 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) => {
|
Object.keys(PROVINCE_NAMES).forEach((code) => {
|
||||||
if (PROVINCE_NAMES[code].indexOf(search) !== -1) {
|
if (PROVINCE_NAMES[code].indexOf(search) !== -1) {
|
||||||
filter.$or.push({ provincecode: code });
|
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 { font-size: 0.75rem; margin-top: 4px; }
|
||||||
.cell-msg.ok { color: var(--success); }
|
.cell-msg.ok { color: var(--success); }
|
||||||
.cell-msg.err { color: var(--danger); }
|
.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; }
|
.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 { 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); }
|
.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 rowNum = (state.page - 1) * state.limit + (index + 1);
|
||||||
var amountVal = item.amountRaw != null ? item.amountRaw : item.amount;
|
var amountVal = item.amountRaw != null ? item.amountRaw : item.amount;
|
||||||
var amountStr = amountVal != null ? Number(amountVal).toLocaleString('fa-IR') : '-';
|
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) {
|
function bindRowEvents(fragment) {
|
||||||
@@ -1494,7 +1518,7 @@ app.get("/all-payments", async (req, res) => {
|
|||||||
paginationEl.style.display = 'none';
|
paginationEl.style.display = 'none';
|
||||||
return;
|
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('');
|
var rows = list.map(function(item, i) { return renderRow(item, i); }).join('');
|
||||||
contentEl.innerHTML = thead + rows + '</tbody></table>';
|
contentEl.innerHTML = thead + rows + '</tbody></table>';
|
||||||
bindRowEvents(contentEl);
|
bindRowEvents(contentEl);
|
||||||
|
|||||||
Reference in New Issue
Block a user