fix: standardize invoice partner naming and enhance sequence generation logic
Deploy Application / deploy (push) Successful in 32s
Details
Deploy Application / deploy (push) Successful in 32s
Details
This commit is contained in:
parent
faa30f3d7f
commit
e4a60acc58
|
|
@ -262,7 +262,7 @@ model rv_openitem {
|
|||
db_id String? @db.Uuid
|
||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
is_pay String? @default("N") @db.Char(1)
|
||||
invoicePartners invoicePartner[]
|
||||
invoicepartners invoicepartner[]
|
||||
}
|
||||
|
||||
model transactions {
|
||||
|
|
@ -309,20 +309,23 @@ model transactions {
|
|||
}
|
||||
|
||||
model transactions_lines {
|
||||
transaction_id String @db.Uuid
|
||||
description String? @db.VarChar(255)
|
||||
amount Decimal? @db.Decimal(20, 2)
|
||||
db_id String? @db.Uuid
|
||||
c_invoice_id Decimal? @db.Decimal(10, 0)
|
||||
created_at DateTime? @default(now()) @db.Timestamptz(6)
|
||||
updated_at DateTime? @default(now()) @db.Timestamptz(6)
|
||||
tenant_id String @db.Uuid
|
||||
line_no Int @default(1)
|
||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
c_payment_id Decimal? @db.Decimal(10, 0)
|
||||
documentno String? @db.VarChar(255)
|
||||
database database? @relation(fields: [db_id], references: [db_id], onDelete: NoAction, onUpdate: NoAction)
|
||||
transactions transactions @relation(fields: [transaction_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
|
||||
transaction_id String @db.Uuid
|
||||
description String? @db.VarChar(255)
|
||||
amount Decimal? @db.Decimal(20, 2)
|
||||
db_id String? @db.Uuid
|
||||
c_invoice_id Decimal? @db.Decimal(10, 0)
|
||||
created_at DateTime? @default(now()) @db.Timestamptz(6)
|
||||
updated_at DateTime? @default(now()) @db.Timestamptz(6)
|
||||
tenant_id String @db.Uuid
|
||||
line_no Int @default(1)
|
||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
c_payment_id Decimal? @db.Decimal(10, 0)
|
||||
date DateTime? @db.Timestamptz(6)
|
||||
invoicepartner_id String? @db.Uuid
|
||||
documentno String? @db.VarChar(255)
|
||||
invoicepartner invoicepartner? @relation(fields: [invoicepartner_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
|
||||
database database? @relation(fields: [db_id], references: [db_id], onDelete: NoAction, onUpdate: NoAction)
|
||||
transactions transactions @relation(fields: [transaction_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
|
||||
}
|
||||
|
||||
model bank_code {
|
||||
|
|
@ -335,21 +338,23 @@ model bank_code {
|
|||
banks banks[]
|
||||
}
|
||||
|
||||
model invoicePartner {
|
||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
partnerServiceId String @db.VarChar(50)
|
||||
c_bpartner_id Decimal? @db.Decimal(10, 0)
|
||||
db_id String? @db.Uuid
|
||||
c_invoice_id Decimal? @db.Decimal(10, 0)
|
||||
invoiceAmount Decimal? @db.Decimal(20, 2)
|
||||
payedAmount Decimal? @db.Decimal(20, 2)
|
||||
amount Decimal? @db.Decimal(20, 2)
|
||||
is_active Boolean @default(true)
|
||||
is_pay Boolean @default(false)
|
||||
rv_openitem_id String? @db.Uuid
|
||||
created_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
updated_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
rv_openitem rv_openitem? @relation(fields: [rv_openitem_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
|
||||
model invoicepartner {
|
||||
id String @id(map: "invoicePartner_pkey") @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
costumerno String @db.VarChar(50)
|
||||
c_bpartner_id Decimal? @db.Decimal(10, 0)
|
||||
documentno String? @db.VarChar(30)
|
||||
db_id String? @db.Uuid
|
||||
c_invoice_id Decimal? @db.Decimal(10, 0)
|
||||
is_active Boolean @default(true)
|
||||
created_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
updated_at DateTime @default(now()) @db.Timestamptz(6)
|
||||
is_pay Boolean @default(false)
|
||||
grandtotal Decimal? @db.Decimal(20, 2)
|
||||
amount Decimal? @db.Decimal(20, 2)
|
||||
rv_openitem_id String? @db.Uuid
|
||||
rv_openitem rv_openitem? @relation(fields: [rv_openitem_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "invoicePartner_rv_openitem_id_fkey")
|
||||
transactionsLines transactions_lines[]
|
||||
invoiceLines invoice_lines[]
|
||||
}
|
||||
|
||||
model invoice {
|
||||
|
|
@ -381,21 +386,23 @@ model invoice {
|
|||
}
|
||||
|
||||
model invoice_lines {
|
||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
description String? @db.VarChar(255)
|
||||
amount Decimal? @db.Decimal(20, 2)
|
||||
c_invoice_id Decimal? @db.Decimal(10, 0)
|
||||
invoice_id String? @db.Uuid
|
||||
db_id String? @db.Uuid
|
||||
created_at DateTime? @default(now()) @db.Timestamptz(6)
|
||||
updated_at DateTime? @default(now()) @db.Timestamptz(6)
|
||||
bank_id String @db.Uuid
|
||||
tenant_id String @db.Uuid
|
||||
line_no Int @default(1)
|
||||
billcode String? @db.VarChar(10)
|
||||
billname String? @db.VarChar(50)
|
||||
database database? @relation(fields: [db_id], references: [db_id], onDelete: NoAction, onUpdate: NoAction)
|
||||
invoice invoice? @relation(fields: [invoice_id], references: [id])
|
||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
description String? @db.VarChar(255)
|
||||
amount Decimal? @db.Decimal(20, 2)
|
||||
c_invoice_id Decimal? @db.Decimal(10, 0)
|
||||
invoicepartner_id String? @db.Uuid
|
||||
invoice_id String? @db.Uuid
|
||||
db_id String? @db.Uuid
|
||||
created_at DateTime? @default(now()) @db.Timestamptz(6)
|
||||
updated_at DateTime? @default(now()) @db.Timestamptz(6)
|
||||
bank_id String @db.Uuid
|
||||
tenant_id String @db.Uuid
|
||||
line_no Int @default(1)
|
||||
billcode String? @db.VarChar(10)
|
||||
billname String? @db.VarChar(50)
|
||||
invoicepartner invoicepartner? @relation(fields: [invoicepartner_id], references: [id])
|
||||
database database? @relation(fields: [db_id], references: [db_id], onDelete: NoAction, onUpdate: NoAction)
|
||||
invoice invoice? @relation(fields: [invoice_id], references: [id])
|
||||
}
|
||||
|
||||
model sequences {
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ export async function MidsuitPayment(req: Request, res: Response) {
|
|||
tenant_id: user.tenant_id,
|
||||
bank_id: get(bankTo, "bank_id") as any,
|
||||
bankto_id: get(bankFrom, "bank_id") as any,
|
||||
external_id: external_id,
|
||||
external_id: getParameter(user, "external_id"),
|
||||
partnerReferenceNo: partnerReferenceNo,
|
||||
amount: get(data, "amount"),
|
||||
description: `Payment for ${get(data, "documentno")}`,
|
||||
|
|
|
|||
|
|
@ -159,10 +159,9 @@ export default async function ({
|
|||
indonesia: "Belum Lunas",
|
||||
});
|
||||
refTransaksi.push({
|
||||
english: get(item, "documentno"),
|
||||
indonesia: get(item, "documentno"),
|
||||
english: get(inv, "documentno"),
|
||||
indonesia: get(inv, "documentno"),
|
||||
});
|
||||
|
||||
billDetails.push({
|
||||
billCode: twoDigits(index + 1),
|
||||
billName: get(item, "documentno"),
|
||||
|
|
@ -174,6 +173,7 @@ export default async function ({
|
|||
transactions.push(
|
||||
db.invoice_lines.create({
|
||||
data: {
|
||||
invoicepartner_id: inv.id,
|
||||
invoice_id: invoice.id,
|
||||
description: get(item, "description"),
|
||||
billcode: twoDigits(index + 1),
|
||||
|
|
@ -221,6 +221,6 @@ export default async function ({
|
|||
keterangan,
|
||||
jatuhTempo,
|
||||
status,
|
||||
refTransaksi,
|
||||
// refTransaksi,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
import db from "../../../db";
|
||||
import sequence from "../../sequence";
|
||||
|
||||
export default async function ({ data }: { data: any }) {
|
||||
const partnerServiceId = data.partnerServiceId;
|
||||
const costumerno = data.partnerServiceId;
|
||||
const db_id = data.db_id;
|
||||
const invoices: any[] = data.invoices || [];
|
||||
const invoiceExists = await db.invoicePartner.findMany({
|
||||
const invoiceExists = await db.invoicepartner.findMany({
|
||||
where: {
|
||||
partnerServiceId,
|
||||
costumerno,
|
||||
db_id,
|
||||
is_pay: false,
|
||||
},
|
||||
|
|
@ -29,16 +30,26 @@ export default async function ({ data }: { data: any }) {
|
|||
);
|
||||
});
|
||||
const transactions = [] as any[];
|
||||
const documentno = await sequence(
|
||||
"invoicePartner",
|
||||
10,
|
||||
invoicePartnerCreate.length
|
||||
);
|
||||
let idx = 0;
|
||||
if (invoicePartnerCreate.length > 0)
|
||||
for (const inv of invoicePartnerCreate) {
|
||||
const docno = documentno[idx];
|
||||
idx++;
|
||||
transactions.push(
|
||||
db.invoicePartner.create({
|
||||
db.invoicepartner.create({
|
||||
data: {
|
||||
partnerServiceId,
|
||||
costumerno,
|
||||
documentno: docno,
|
||||
db_id,
|
||||
c_bpartner_id: inv.c_bpartner_id,
|
||||
c_invoice_id: inv.c_invoice_id,
|
||||
amount: Number(inv.grandtotal) || 0,
|
||||
grandtotal: Number(inv.grandtotal) || 0,
|
||||
rv_openitem_id: inv.id,
|
||||
},
|
||||
})
|
||||
|
|
@ -47,20 +58,20 @@ export default async function ({ data }: { data: any }) {
|
|||
if (transactions.length > 0) {
|
||||
await db.$transaction(transactions);
|
||||
}
|
||||
const sumAmount = await db.invoicePartner.aggregate({
|
||||
const sumAmount = await db.invoicepartner.aggregate({
|
||||
_sum: {
|
||||
amount: true,
|
||||
},
|
||||
where: {
|
||||
db_id,
|
||||
partnerServiceId,
|
||||
costumerno,
|
||||
is_pay: false,
|
||||
},
|
||||
});
|
||||
const invoice = await db.invoicePartner.findMany({
|
||||
const invoice = await db.invoicepartner.findMany({
|
||||
where: {
|
||||
db_id,
|
||||
partnerServiceId,
|
||||
costumerno,
|
||||
is_pay: false,
|
||||
},
|
||||
include: {
|
||||
|
|
|
|||
|
|
@ -1,30 +1,87 @@
|
|||
import db from "../../../db";
|
||||
import { formatMoney } from "./getInvoiceVirtualAccount";
|
||||
|
||||
export default async function ({ data }: { data: any }) {
|
||||
const partnerServiceId = data.partnerServiceId;
|
||||
const costumerno = data.costumerno;
|
||||
let paymentAmount = data.paymentAmount;
|
||||
const db_id = data.db_id;
|
||||
const invoices: any[] = data.invoices || [];
|
||||
const invoiceExists = await db.invoicePartner.findMany({
|
||||
const invoiceExists = await db.invoicepartner.findMany({
|
||||
where: {
|
||||
partnerServiceId,
|
||||
c_invoice_id: {
|
||||
in: invoices.map((inv) => inv.c_invoice_id),
|
||||
},
|
||||
costumerno,
|
||||
db_id,
|
||||
is_pay: false,
|
||||
amount: {
|
||||
gt: 0,
|
||||
},
|
||||
},
|
||||
include: {
|
||||
rv_openitem: true,
|
||||
},
|
||||
});
|
||||
const transactions = [] as any[];
|
||||
const payment = [] as any[];
|
||||
const unpaid = [] as any[];
|
||||
if (paymentAmount > 0) {
|
||||
const invoiceByAmount = await db.invoicepartner.findFirst({
|
||||
where: {
|
||||
c_invoice_id: {
|
||||
in: invoices.map((inv) => inv.c_invoice_id),
|
||||
},
|
||||
amount: paymentAmount,
|
||||
is_pay: false,
|
||||
costumerno,
|
||||
db_id,
|
||||
AND: [
|
||||
{
|
||||
amount: {
|
||||
gt: 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
invoiceExists.map((inv) => {
|
||||
if (paymentAmount > 0) {
|
||||
if (invoiceByAmount) {
|
||||
if (invoiceByAmount.id !== inv.id) {
|
||||
payment.push({
|
||||
id: inv.id,
|
||||
c_invoice_id: inv.c_invoice_id,
|
||||
costumerno,
|
||||
c_bpartner_id: inv.c_bpartner_id,
|
||||
amount: 0,
|
||||
remainingAmount: formatMoney(inv.amount),
|
||||
grandtotal: formatMoney(inv.amount),
|
||||
rv_openitem: inv.rv_openitem,
|
||||
status: "unpaid",
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
let sisaInvoice = Number(inv.amount) || 0;
|
||||
sisaInvoice =
|
||||
paymentAmount > sisaInvoice ? 0 : sisaInvoice - paymentAmount;
|
||||
const amountInvoice = Number(inv.amount) || 0;
|
||||
payment.push({
|
||||
id: inv.id,
|
||||
c_invoice_id: inv.c_invoice_id,
|
||||
costumerno,
|
||||
c_bpartner_id: inv.c_bpartner_id,
|
||||
amount:
|
||||
sisaInvoice <= 0
|
||||
? formatMoney(paymentAmount)
|
||||
: formatMoney(amountInvoice - sisaInvoice),
|
||||
remainingAmount: formatMoney(sisaInvoice),
|
||||
grandtotal: formatMoney(inv.amount),
|
||||
status: sisaInvoice <= 0 ? "paid" : "unpaid",
|
||||
rv_openitem: inv.rv_openitem,
|
||||
});
|
||||
transactions.push(
|
||||
db.invoicePartner.update({
|
||||
db.invoicepartner.update({
|
||||
where: {
|
||||
id: inv.id,
|
||||
},
|
||||
|
|
@ -33,29 +90,41 @@ export default async function ({ data }: { data: any }) {
|
|||
},
|
||||
})
|
||||
);
|
||||
if (sisaInvoice <= 0) {
|
||||
transactions.push(
|
||||
db.rv_openitem.updateMany({
|
||||
where: {
|
||||
c_invoice_id: inv.c_invoice_id,
|
||||
db_id,
|
||||
},
|
||||
data: { is_pay: "Y" },
|
||||
})
|
||||
);
|
||||
}
|
||||
if (paymentAmount >= amountInvoice) {
|
||||
paymentAmount -= amountInvoice;
|
||||
} else {
|
||||
paymentAmount = 0;
|
||||
}
|
||||
} else {
|
||||
payment.push({
|
||||
id: inv.id,
|
||||
c_invoice_id: inv.c_invoice_id,
|
||||
costumerno,
|
||||
c_bpartner_id: inv.c_bpartner_id,
|
||||
amount: 0,
|
||||
remainingAmount: formatMoney(inv.amount),
|
||||
grandtotal: formatMoney(inv.amount),
|
||||
status: "unpaid",
|
||||
rv_openitem: inv.rv_openitem,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
await db.$transaction(transactions);
|
||||
const sumAmount = await db.invoicePartner.aggregate({
|
||||
_sum: { amount: true },
|
||||
});
|
||||
if (!sumAmount._sum.amount) {
|
||||
await db.invoicePartner.updateMany({
|
||||
where: {
|
||||
partnerServiceId,
|
||||
},
|
||||
data: {
|
||||
is_pay: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
return {
|
||||
totalUnpaid: sumAmount._sum.amount || 0,
|
||||
transactions,
|
||||
payment,
|
||||
paid: payment.filter((p) => p.amount > 0),
|
||||
unpaid: payment.filter((p) => p.amount === 0),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import db from "../../../db";
|
|||
import lo from "../../lodash";
|
||||
import Decimal from "decimal.js";
|
||||
import completeTransaction from "../../completeTransaction";
|
||||
import invoicePartnerPayment from "./invoicePartnerPayment";
|
||||
import sequence from "../../sequence";
|
||||
const twoDigits = (n: number) => String(n).padStart(2, "0");
|
||||
export const formatMoney = (v: any) => {
|
||||
const d = new Decimal(v ?? 0);
|
||||
|
|
@ -32,59 +34,91 @@ export default async function ({
|
|||
}
|
||||
console.log("invoice.amount:", invoice.amount);
|
||||
console.log("paidAmount.value:", get(data, "paidAmount.value"));
|
||||
if (formatMoney(invoice.amount) !== get(data, "paidAmount.value")) {
|
||||
if (
|
||||
Number(get(data, "paidAmount.value")) <= 0 ||
|
||||
Number(get(data, "paidAmount.value")) > Number(get(invoice, "amount", 0))
|
||||
) {
|
||||
throw new Error("Paid amount does not match invoice amount");
|
||||
}
|
||||
|
||||
if (!user.database) throw new Error("User database information is missing");
|
||||
|
||||
const lines = get(invoice, "invoice_lines", []);
|
||||
const paymentInvoicePartner = await invoicePartnerPayment({
|
||||
data: {
|
||||
costumerno: get(data, "customerNo"),
|
||||
paymentAmount: Number(get(data, "paidAmount.value")),
|
||||
db_id: get(user, "database.db_id"),
|
||||
invoices: get(invoice, "invoice_lines", []),
|
||||
},
|
||||
});
|
||||
const lines = get(paymentInvoicePartner, "paid", []);
|
||||
const flagAdvise = get(data, "flagAdvise") === "Y" ? true : false;
|
||||
if (!flagAdvise) {
|
||||
const transaction = await db.transactions.create({
|
||||
data: {
|
||||
tenant_id: user.tenant_id,
|
||||
bank_id: user.bank_id,
|
||||
amount: invoice.amount as any,
|
||||
user_id: user.user_id,
|
||||
description: `Payment for Virtual Account ${invoice.inquiryRequestId}`,
|
||||
status: "DRAFT",
|
||||
c_bpartner_id: get(invoice, "c_bpartner_id"),
|
||||
paymentRequestId: get(data, "paymentRequestId"),
|
||||
paidBills: get(data, "paidBills"),
|
||||
hashedSourceAccountNo: get(data, "hashedSourceAccountNo"),
|
||||
flagAdvise: get(data, "flagAdvise"),
|
||||
partnerServiceId: get(data, "partnerServiceId"),
|
||||
customerNo: get(data, "customerNo"),
|
||||
virtualAccountNo: get(data, "virtualAccountNo"),
|
||||
referenceNo: get(data, "referenceNo"),
|
||||
channelCode: get(data, "channelCode"),
|
||||
db_id: get(user, "database.db_id"),
|
||||
trxDateTime: get(data, "trxDateTime")
|
||||
? new Date(get(data, "trxDateTime"))
|
||||
: null,
|
||||
},
|
||||
const deskripsi: any[] = [];
|
||||
const keterangan: any[] = [];
|
||||
const status: any[] = [];
|
||||
const refTransaksi: any[] = [];
|
||||
const transaction = await db.transactions.create({
|
||||
data: {
|
||||
tenant_id: user.tenant_id,
|
||||
bank_id: user.bank_id,
|
||||
amount: get(data, "paidAmount.value") as any,
|
||||
user_id: user.user_id,
|
||||
description: `Payment for Virtual Account ${invoice.inquiryRequestId}`,
|
||||
status: "DRAFT",
|
||||
c_bpartner_id: get(invoice, "c_bpartner_id"),
|
||||
paymentRequestId: get(data, "paymentRequestId"),
|
||||
paidBills: get(data, "paidBills"),
|
||||
hashedSourceAccountNo: get(data, "hashedSourceAccountNo"),
|
||||
flagAdvise: get(data, "flagAdvise"),
|
||||
partnerServiceId: get(data, "partnerServiceId"),
|
||||
customerNo: get(data, "customerNo"),
|
||||
virtualAccountNo: get(data, "virtualAccountNo"),
|
||||
referenceNo: get(data, "referenceNo"),
|
||||
channelCode: get(data, "channelCode"),
|
||||
db_id: get(user, "database.db_id"),
|
||||
trxDateTime: get(data, "trxDateTime")
|
||||
? new Date(get(data, "trxDateTime"))
|
||||
: null,
|
||||
},
|
||||
});
|
||||
if (!transaction) throw new Error("Failed to create invoice record");
|
||||
const documentnoLine = await sequence("transactionLines", 10, lines.length);
|
||||
const transactions: any[] = [];
|
||||
lines.map((item, index) => {
|
||||
const inv = item.rv_openitem;
|
||||
keterangan.push({
|
||||
english: get(inv, "description"),
|
||||
indonesia: get(inv, "description"),
|
||||
});
|
||||
if (!transaction) throw new Error("Failed to create invoice record");
|
||||
const transactions: any[] = [];
|
||||
lines.map((item, index) => {
|
||||
transactions.push(
|
||||
db.transactions_lines.create({
|
||||
data: {
|
||||
transaction_id: transaction.id,
|
||||
description: get(item, "description"),
|
||||
line_no: get(item, "line_no"),
|
||||
amount: lo.get(item, "grandtotal", 0),
|
||||
c_invoice_id: get(item, "c_invoice_id"),
|
||||
db_id: lo.get(user, "database.db_id"),
|
||||
tenant_id: get(user, "tenant_id"),
|
||||
},
|
||||
})
|
||||
);
|
||||
deskripsi.push({
|
||||
english: `Invoice ${get(inv, "documentno")}`,
|
||||
indonesia: `Faktur ${get(inv, "documentno")}`,
|
||||
});
|
||||
if (transactions.length > 0) await db.$transaction(transactions);
|
||||
await completeTransaction(transaction.id);
|
||||
}
|
||||
status.push({
|
||||
english: "Received",
|
||||
indonesia: "Diterima",
|
||||
});
|
||||
refTransaksi.push({
|
||||
english: documentnoLine[index],
|
||||
indonesia: documentnoLine[index],
|
||||
});
|
||||
transactions.push(
|
||||
db.transactions_lines.create({
|
||||
data: {
|
||||
transaction_id: transaction.id,
|
||||
invoicepartner_id: get(item, "id"),
|
||||
documentno: documentnoLine[index],
|
||||
line_no: index + 1,
|
||||
amount: lo.get(item, "amount", 0),
|
||||
c_invoice_id: get(item, "c_invoice_id"),
|
||||
db_id: lo.get(user, "database.db_id"),
|
||||
tenant_id: get(user, "tenant_id"),
|
||||
},
|
||||
})
|
||||
);
|
||||
});
|
||||
if (transactions.length > 0) await db.$transaction(transactions);
|
||||
await completeTransaction(transaction.id);
|
||||
await db.$transaction(get(paymentInvoicePartner, "transactions", []));
|
||||
|
||||
return {
|
||||
paymentFlagStatus: "00",
|
||||
|
|
@ -98,9 +132,13 @@ export default async function ({
|
|||
virtualAccountNo: get(data, "virtualAccountNo"),
|
||||
virtualAccountName: get(invoice, "virtualAccountName"),
|
||||
totalAmount: {
|
||||
value: formatMoney(invoice.amount),
|
||||
value: formatMoney(get(data, "paidAmount.value")),
|
||||
currency: "IDR",
|
||||
},
|
||||
trxDateTime: get(data, "trxDateTime"),
|
||||
refTransaksi,
|
||||
deskripsi,
|
||||
keterangan,
|
||||
status,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,22 +17,22 @@ export default async function (transaction_id: string) {
|
|||
data: { status: "COMPLETED" },
|
||||
})
|
||||
);
|
||||
const results = await db.transactions_lines.findMany({
|
||||
where: { transaction_id: transaction_id },
|
||||
});
|
||||
if (results.length > 0) {
|
||||
results.map((item: any) => {
|
||||
transactions.push(
|
||||
db.rv_openitem.updateMany({
|
||||
where: {
|
||||
c_invoice_id: item.c_invoice_id,
|
||||
db_id: item.db_id,
|
||||
},
|
||||
data: { is_pay: "Y" },
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
// const results = await db.transactions_lines.findMany({
|
||||
// where: { transaction_id: transaction_id },
|
||||
// });
|
||||
// if (results.length > 0) {
|
||||
// results.map((item: any) => {
|
||||
// transactions.push(
|
||||
// db.rv_openitem.updateMany({
|
||||
// where: {
|
||||
// c_invoice_id: item.c_invoice_id,
|
||||
// db_id: item.db_id,
|
||||
// },
|
||||
// data: { is_pay: "Y" },
|
||||
// })
|
||||
// );
|
||||
// });
|
||||
// }
|
||||
await db.$transaction(transactions);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,42 +5,60 @@ import db from "../db";
|
|||
// atomic increment (updateMany) and falling back to create. If create races
|
||||
// with another process, we catch the unique-constraint error and retry a few
|
||||
// times. This avoids unsafe find-then-create/update patterns.
|
||||
export default async function (name: string, padStartLength = 10) {
|
||||
export default async function (name: string, padStartLength = 10, count = 1) {
|
||||
const yyyymmdd = new Date().toISOString().slice(0, 10).replace(/-/g, "");
|
||||
const results: string[] = [];
|
||||
|
||||
// Try a few times to handle races when many processes call concurrently.
|
||||
const maxAttempts = 5;
|
||||
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
||||
// If a row already exists, this updateMany will atomically increment it.
|
||||
const updateResult = await db.sequences.updateMany({
|
||||
where: { name, yyyymmdd },
|
||||
data: { value: { increment: 1 }, updated_at: new Date() },
|
||||
});
|
||||
|
||||
if (updateResult.count && updateResult.count > 0) {
|
||||
// Read back the new value and return it.
|
||||
const sequence = await db.sequences.findFirst({
|
||||
try {
|
||||
// If a row already exists, this updateMany will atomically increment it by count
|
||||
const updateResult = await db.sequences.updateMany({
|
||||
where: { name, yyyymmdd },
|
||||
data: { value: { increment: count }, updated_at: new Date() },
|
||||
});
|
||||
if (sequence) {
|
||||
return `${yyyymmdd}${String(sequence.value).padStart(
|
||||
|
||||
if (updateResult.count && updateResult.count > 0) {
|
||||
// Read back the new value and return it.
|
||||
const sequence = await db.sequences.findFirst({
|
||||
where: { name, yyyymmdd },
|
||||
});
|
||||
if (sequence) {
|
||||
// Generate sequences for the requested count
|
||||
for (let i = 0; i < count; i++) {
|
||||
const currentValue = sequence.value - count + i + 1;
|
||||
const sequenceString = `${yyyymmdd}${String(currentValue).padStart(
|
||||
padStartLength,
|
||||
"0"
|
||||
)}`;
|
||||
results.push(sequenceString);
|
||||
}
|
||||
|
||||
// Return object for single sequence, array for multiple
|
||||
return count === 1 ? results[0] : results;
|
||||
}
|
||||
// If for some reason the row disappeared, loop and retry.
|
||||
continue;
|
||||
}
|
||||
|
||||
// No existing row — try to create it with initial value equal to count
|
||||
const created = await db.sequences.create({
|
||||
data: { name, yyyymmdd, value: count },
|
||||
});
|
||||
|
||||
// Generate sequences for the requested count starting from 1
|
||||
for (let i = 0; i < count; i++) {
|
||||
const currentValue = i + 1;
|
||||
const sequenceString = `${yyyymmdd}${String(currentValue).padStart(
|
||||
padStartLength,
|
||||
"0"
|
||||
)}`;
|
||||
results.push(sequenceString);
|
||||
}
|
||||
// If for some reason the row disappeared, loop and retry.
|
||||
continue;
|
||||
}
|
||||
|
||||
// No existing row — try to create it with initial value 1.
|
||||
try {
|
||||
const created = await db.sequences.create({
|
||||
data: { name, yyyymmdd, value: 1 },
|
||||
});
|
||||
return `${yyyymmdd}${String(created.value).padStart(
|
||||
padStartLength,
|
||||
"0"
|
||||
)}`;
|
||||
// Return object for single sequence, array for multiple
|
||||
return count === 1 ? results[0] : results;
|
||||
} catch (err: any) {
|
||||
// Prisma unique-constraint error code P2002 indicates another process
|
||||
// created the row in the meantime; retry the loop. Re-throw unexpected errors.
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ export const setRoutes = () => {
|
|||
if (!seqName) {
|
||||
return res.status(400).json({ error: "Sequence name is required" });
|
||||
}
|
||||
const seqValue = await sequence(seqName);
|
||||
const seqValue = await sequence(seqName, 10, 2);
|
||||
return res.json({ result: seqValue });
|
||||
} catch (err) {
|
||||
console.error("Get sequence error", err);
|
||||
|
|
|
|||
Loading…
Reference in New Issue