fix: refactor paymentStatus to improve error handling and response structure
Deploy Application / deploy (push) Successful in 38s
Details
Deploy Application / deploy (push) Successful in 38s
Details
This commit is contained in:
parent
a19933a06e
commit
e09b2517e1
|
|
@ -82,20 +82,11 @@ function mapRowToRvOpenitem(row: any) {
|
|||
};
|
||||
}
|
||||
|
||||
export default class SyncController {
|
||||
static async syncRvOpenitem(req: Request, res: Response) {
|
||||
try {
|
||||
const databases = await db.database.findMany({
|
||||
where: {
|
||||
is_synced: "Y",
|
||||
},
|
||||
});
|
||||
// sinkron per db satu per satu (each database work is wrapped in a transaction)
|
||||
let totalInserted = 0;
|
||||
let totalUpdated = 0;
|
||||
for (const database of databases) {
|
||||
// Function to process a single database sync
|
||||
async function processDatabaseSync(database: any) {
|
||||
const pool = await getPoolForDbId(database.db_id);
|
||||
const q = "SELECT * FROM rv_openitem";
|
||||
|
||||
// Set timeout to 1 hour for sync operations
|
||||
const client = await pool.connect();
|
||||
let result;
|
||||
|
|
@ -104,53 +95,83 @@ export default class SyncController {
|
|||
} finally {
|
||||
client.release();
|
||||
}
|
||||
|
||||
const rows = result.rows || [];
|
||||
console.log(
|
||||
`Syncing rv_openitem for database ${database.name} (${database.db_id}): fetched ${rows.length} rows`
|
||||
);
|
||||
|
||||
const freshDB = await db.rv_openitem.count({
|
||||
where: { db_id: database.db_id },
|
||||
});
|
||||
// perform upserts in smaller transactions (per-batch) to avoid long-lived transactions
|
||||
|
||||
let dbInserted = 0;
|
||||
let dbUpdated = 0;
|
||||
const batchSize = 200;
|
||||
const transactions = [];
|
||||
|
||||
// Process in batches to avoid memory issues
|
||||
for (let i = 0; i < rows.length; i += batchSize) {
|
||||
const batch = rows.slice(i, i + batchSize);
|
||||
const ops = batch.map((r: any) => mapRowToRvOpenitem(r));
|
||||
for (const op of ops) {
|
||||
|
||||
let transactions = [];
|
||||
|
||||
if (freshDB === 0) {
|
||||
transactions.push(
|
||||
// Fresh DB - just insert all records
|
||||
transactions = ops.map((op) =>
|
||||
db.rv_openitem.create({
|
||||
data: { ...op, db_id: database.db_id },
|
||||
})
|
||||
);
|
||||
totalInserted++;
|
||||
dbInserted += ops.length;
|
||||
} else {
|
||||
const existing = await db.rv_openitem.findFirst({
|
||||
where: { c_invoice_id: op.c_invoice_id },
|
||||
// Check existing records in bulk instead of one by one
|
||||
const invoiceIds = ops.map((op) => op.c_invoice_id).filter(Boolean);
|
||||
const existingRecords = await db.rv_openitem.findMany({
|
||||
where: {
|
||||
c_invoice_id: { in: invoiceIds },
|
||||
db_id: database.db_id,
|
||||
},
|
||||
select: { id: true, c_invoice_id: true },
|
||||
});
|
||||
if (existing) {
|
||||
|
||||
const existingMap = new Map(
|
||||
existingRecords.map((record) => [record.c_invoice_id, record.id])
|
||||
);
|
||||
|
||||
for (const op of ops) {
|
||||
const existingId = existingMap.get(op.c_invoice_id);
|
||||
if (existingId) {
|
||||
transactions.push(
|
||||
db.rv_openitem.update({
|
||||
where: { id: existing.id },
|
||||
where: { id: existingId },
|
||||
data: op,
|
||||
})
|
||||
);
|
||||
totalUpdated++;
|
||||
dbUpdated++;
|
||||
} else {
|
||||
transactions.push(
|
||||
db.rv_openitem.create({
|
||||
data: { ...op, db_id: database.db_id },
|
||||
})
|
||||
);
|
||||
totalInserted++;
|
||||
}
|
||||
dbInserted++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// cleanup: mark local records as not paid if they no longer exist in source
|
||||
// Execute batch transaction
|
||||
if (transactions.length > 0) {
|
||||
await db.$transaction(transactions);
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup: mark local records as not paid if they no longer exist in source
|
||||
if (freshDB > 0) {
|
||||
const existingIds = rows
|
||||
.map((r: any) => r.c_invoice_id)
|
||||
.filter((v: any) => v !== undefined && v !== null);
|
||||
|
||||
if (existingIds.length > 0) {
|
||||
const toUpdate = await db.rv_openitem.findMany({
|
||||
where: {
|
||||
|
|
@ -158,19 +179,46 @@ export default class SyncController {
|
|||
c_invoice_id: { notIn: existingIds },
|
||||
},
|
||||
});
|
||||
for (const item of toUpdate) {
|
||||
transactions.push(
|
||||
|
||||
if (toUpdate.length > 0) {
|
||||
const updateTransactions = toUpdate.map((item) =>
|
||||
db.rv_openitem.update({
|
||||
where: { id: item.id },
|
||||
data: { is_pay: "N" },
|
||||
})
|
||||
);
|
||||
await db.$transaction(updateTransactions);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (transactions.length > 0) await db.$transaction(transactions);
|
||||
|
||||
return { inserted: dbInserted, updated: dbUpdated };
|
||||
}
|
||||
|
||||
export default class SyncController {
|
||||
static async syncRvOpenitem(req: Request, res: Response) {
|
||||
try {
|
||||
const databases = await db.database.findMany({
|
||||
where: {
|
||||
is_synced: "Y",
|
||||
},
|
||||
});
|
||||
|
||||
// Process all databases in parallel using Promise.all
|
||||
const results = await Promise.all(
|
||||
databases.map((database) => processDatabaseSync(database))
|
||||
);
|
||||
|
||||
// Sum up results from all databases
|
||||
const totalInserted = results.reduce(
|
||||
(sum, result) => sum + result.inserted,
|
||||
0
|
||||
);
|
||||
const totalUpdated = results.reduce(
|
||||
(sum, result) => sum + result.updated,
|
||||
0
|
||||
);
|
||||
|
||||
return res.json({
|
||||
status: "success",
|
||||
inserted: totalInserted,
|
||||
|
|
|
|||
|
|
@ -446,9 +446,7 @@ export async function paymentStatus(req: Request, res: Response) {
|
|||
const where: any = {};
|
||||
if (startdate || enddate) {
|
||||
if (!startdate || !enddate) {
|
||||
return res
|
||||
.status(400)
|
||||
.json({
|
||||
return res.status(400).json({
|
||||
error: "startdate and enddate are required when filtering by date",
|
||||
});
|
||||
}
|
||||
|
|
@ -489,21 +487,12 @@ export async function paymentStatus(req: Request, res: Response) {
|
|||
include: { transactions: true },
|
||||
orderBy: { created_at: "desc" },
|
||||
});
|
||||
if (rows.length === 0) {
|
||||
return res
|
||||
.status(404)
|
||||
.json({ responseCode: "404", responseMessage: "no payment found" });
|
||||
}
|
||||
return res.json({ count: rows.length, data: rows });
|
||||
|
||||
const result = rows.map((r: any) => ({
|
||||
id: r.id,
|
||||
transaction_id: r.transaction_id,
|
||||
amount: r.amount,
|
||||
documentno: r.documentno,
|
||||
c_invoice_id: r.c_invoice_id,
|
||||
created_at: r.created_at,
|
||||
tenant_id: r.tenant_id,
|
||||
transaction_status: r.transactions ? r.transactions.status : null,
|
||||
transaction_reference: r.transactions ? r.transactions.referenceNo : null,
|
||||
}));
|
||||
|
||||
return res.json({ count: result.length, data: result });
|
||||
} catch (err) {
|
||||
console.error("paymentStatus error", err);
|
||||
return res.status(500).json({
|
||||
|
|
|
|||
Loading…
Reference in New Issue