Initial import of AbelBirdNest Stock
This commit is contained in:
234
scripts/backfill-purchase-realization.mjs
Normal file
234
scripts/backfill-purchase-realization.mjs
Normal file
@ -0,0 +1,234 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
const OPENING_EVENT_TYPES = new Set(["OPENING_COST"]);
|
||||
const SALE_EVENT_TYPES = new Set(["SALE_REVENUE", "CONSIGNMENT_REVENUE"]);
|
||||
const RETURN_EVENT_TYPES = new Set(["SALE_RETURN", "CONSIGNMENT_RETURN"]);
|
||||
const COST_ADDITIONAL_EVENT_TYPES = new Set([
|
||||
"WASHING_COST",
|
||||
"WASHING_SHRINKAGE",
|
||||
"TRANSFORMATION_SHRINKAGE",
|
||||
"SALE_SHRINKAGE",
|
||||
"CONSIGNMENT_SHRINKAGE",
|
||||
"STOCK_ADJUSTMENT_LOSS",
|
||||
"MANUAL_ADJUSTMENT"
|
||||
]);
|
||||
|
||||
const roundQty = (value) => Number(value.toFixed(3));
|
||||
const roundAmount = (value) => Number(value.toFixed(2));
|
||||
|
||||
async function recalcSummary(purchaseId, agentSharePercent) {
|
||||
const entries = await prisma.purchaseRealizationEntry.findMany({
|
||||
where: { purchaseId }
|
||||
});
|
||||
|
||||
const aggregate = entries.reduce(
|
||||
(state, entry) => {
|
||||
const qtyIn = entry.qtyIn.toNumber();
|
||||
const qtyOut = entry.qtyOut.toNumber();
|
||||
const qtyShrinkage = entry.qtyShrinkage.toNumber();
|
||||
const amountCost = entry.amountCost.toNumber();
|
||||
const amountRevenue = entry.amountRevenue.toNumber();
|
||||
const amountExpense = entry.amountExpense.toNumber();
|
||||
const agentAmount = entry.agentAmount.toNumber();
|
||||
|
||||
state.qtyRemaining += qtyIn - qtyOut - qtyShrinkage;
|
||||
state.profitLossTotal += amountRevenue - amountCost - amountExpense;
|
||||
state.agentProfitTotal += agentAmount;
|
||||
|
||||
if (OPENING_EVENT_TYPES.has(entry.eventType)) {
|
||||
state.qtyOpening += qtyIn;
|
||||
state.costOpeningTotal += amountCost;
|
||||
}
|
||||
if (SALE_EVENT_TYPES.has(entry.eventType)) {
|
||||
state.qtySold += qtyOut;
|
||||
state.revenueTotal += amountRevenue;
|
||||
}
|
||||
if (RETURN_EVENT_TYPES.has(entry.eventType)) {
|
||||
state.qtyReturned += qtyIn;
|
||||
}
|
||||
if (COST_ADDITIONAL_EVENT_TYPES.has(entry.eventType)) {
|
||||
state.costAdditionalTotal += amountCost + amountExpense;
|
||||
}
|
||||
state.qtyShrinkage += qtyShrinkage;
|
||||
return state;
|
||||
},
|
||||
{
|
||||
qtyOpening: 0,
|
||||
qtyRemaining: 0,
|
||||
qtySold: 0,
|
||||
qtyReturned: 0,
|
||||
qtyShrinkage: 0,
|
||||
costOpeningTotal: 0,
|
||||
costAdditionalTotal: 0,
|
||||
revenueTotal: 0,
|
||||
profitLossTotal: 0,
|
||||
agentProfitTotal: 0
|
||||
}
|
||||
);
|
||||
|
||||
const status =
|
||||
aggregate.qtyOpening <= 0
|
||||
? "OPEN"
|
||||
: aggregate.qtyRemaining <= 0
|
||||
? "READY_TO_CLOSE"
|
||||
: aggregate.qtySold > 0 || aggregate.qtyShrinkage > 0
|
||||
? "PARTIAL"
|
||||
: "OPEN";
|
||||
|
||||
await prisma.purchaseRealizationSummary.upsert({
|
||||
where: { purchaseId },
|
||||
update: {
|
||||
status,
|
||||
qtyOpening: roundQty(aggregate.qtyOpening),
|
||||
qtyRemaining: roundQty(aggregate.qtyRemaining),
|
||||
qtySold: roundQty(aggregate.qtySold),
|
||||
qtyReturned: roundQty(aggregate.qtyReturned),
|
||||
qtyShrinkage: roundQty(aggregate.qtyShrinkage),
|
||||
costOpeningTotal: roundAmount(aggregate.costOpeningTotal),
|
||||
costAdditionalTotal: roundAmount(aggregate.costAdditionalTotal),
|
||||
revenueTotal: roundAmount(aggregate.revenueTotal),
|
||||
profitLossTotal: roundAmount(aggregate.profitLossTotal),
|
||||
agentSharePercent,
|
||||
agentProfitTotal: roundAmount(aggregate.agentProfitTotal),
|
||||
closedAt: null
|
||||
},
|
||||
create: {
|
||||
purchaseId,
|
||||
status,
|
||||
qtyOpening: roundQty(aggregate.qtyOpening),
|
||||
qtyRemaining: roundQty(aggregate.qtyRemaining),
|
||||
qtySold: roundQty(aggregate.qtySold),
|
||||
qtyReturned: roundQty(aggregate.qtyReturned),
|
||||
qtyShrinkage: roundQty(aggregate.qtyShrinkage),
|
||||
costOpeningTotal: roundAmount(aggregate.costOpeningTotal),
|
||||
costAdditionalTotal: roundAmount(aggregate.costAdditionalTotal),
|
||||
revenueTotal: roundAmount(aggregate.revenueTotal),
|
||||
profitLossTotal: roundAmount(aggregate.profitLossTotal),
|
||||
agentSharePercent,
|
||||
agentProfitTotal: roundAmount(aggregate.agentProfitTotal),
|
||||
closedAt: null
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const purchases = await prisma.purchase.findMany({
|
||||
where: {
|
||||
status: "SUBMITTED",
|
||||
purchaseType: {
|
||||
in: ["REGULAR", "OFFICE_BUYOUT"]
|
||||
}
|
||||
},
|
||||
include: {
|
||||
profitShareScheme: {
|
||||
select: {
|
||||
shareAgent: true
|
||||
}
|
||||
},
|
||||
lots: true
|
||||
},
|
||||
orderBy: { id: "asc" }
|
||||
});
|
||||
|
||||
let allocationsCreated = 0;
|
||||
let entriesCreated = 0;
|
||||
|
||||
for (const purchase of purchases) {
|
||||
for (const lot of purchase.lots) {
|
||||
const allocationCount = await prisma.lotPurchaseAllocation.count({
|
||||
where: {
|
||||
lotId: lot.id,
|
||||
purchaseId: purchase.id
|
||||
}
|
||||
});
|
||||
|
||||
if (allocationCount === 0) {
|
||||
await prisma.lotPurchaseAllocation.create({
|
||||
data: {
|
||||
lotId: lot.id,
|
||||
purchaseId: purchase.id,
|
||||
purchaseLineId: lot.purchaseLineId,
|
||||
sourceType: lot.sourceType,
|
||||
sourceRefId: lot.sourceRefId,
|
||||
agentIdSnapshot: purchase.agentId,
|
||||
profitShareSchemeIdSnapshot: purchase.profitShareSchemeId,
|
||||
qtyAllocated: lot.availableQty,
|
||||
costTotalAllocated: roundAmount(lot.availableQty.toNumber() * lot.unitCost.toNumber()),
|
||||
unitCostSnapshot: lot.unitCost,
|
||||
notes: "Backfill opening allocation"
|
||||
}
|
||||
});
|
||||
allocationsCreated += 1;
|
||||
}
|
||||
|
||||
const openingCount = await prisma.purchaseRealizationEntry.count({
|
||||
where: {
|
||||
purchaseId: purchase.id,
|
||||
lotId: lot.id,
|
||||
eventType: "OPENING_COST"
|
||||
}
|
||||
});
|
||||
|
||||
if (openingCount === 0) {
|
||||
const allocation = await prisma.lotPurchaseAllocation.findFirst({
|
||||
where: {
|
||||
lotId: lot.id,
|
||||
purchaseId: purchase.id
|
||||
},
|
||||
orderBy: { id: "asc" }
|
||||
});
|
||||
|
||||
await prisma.purchaseRealizationEntry.create({
|
||||
data: {
|
||||
purchaseId: purchase.id,
|
||||
lotId: lot.id,
|
||||
allocationId: allocation?.id ?? null,
|
||||
eventType: "OPENING_COST",
|
||||
referenceType: "PURCHASE",
|
||||
referenceId: purchase.id,
|
||||
occurredAt: lot.receivedAt,
|
||||
qtyIn: lot.originalQty,
|
||||
qtyOut: 0,
|
||||
qtyShrinkage: 0,
|
||||
amountCost: roundAmount(lot.originalQty.toNumber() * lot.unitCost.toNumber()),
|
||||
amountRevenue: 0,
|
||||
amountExpense: 0,
|
||||
amountProfit: 0,
|
||||
agentSharePercentSnapshot: purchase.profitShareScheme?.shareAgent ?? null,
|
||||
agentAmount: 0,
|
||||
notes: "Backfill opening realization"
|
||||
}
|
||||
});
|
||||
entriesCreated += 1;
|
||||
}
|
||||
}
|
||||
|
||||
await recalcSummary(
|
||||
purchase.id,
|
||||
purchase.profitShareScheme?.shareAgent?.toNumber() ?? null
|
||||
);
|
||||
}
|
||||
|
||||
console.log(
|
||||
JSON.stringify(
|
||||
{
|
||||
purchases: purchases.length,
|
||||
allocations_created: allocationsCreated,
|
||||
entries_created: entriesCreated
|
||||
},
|
||||
null,
|
||||
2
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exitCode = 1;
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect();
|
||||
});
|
||||
222
scripts/seed-banks-indonesia.mjs
Normal file
222
scripts/seed-banks-indonesia.mjs
Normal file
@ -0,0 +1,222 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
const banks = [
|
||||
["002", "Bank Rakyat Indonesia (Persero) Tbk"],
|
||||
["008", "Bank Mandiri (Persero) Tbk"],
|
||||
["009", "Bank Negara Indonesia (Persero) Tbk"],
|
||||
["014", "Bank Central Asia Tbk"],
|
||||
["019", "Bank Panin Tbk"],
|
||||
["022", "Bank CIMB Niaga Tbk"],
|
||||
["023", "Bank UOB Indonesia"],
|
||||
["026", "Bank Lippo"],
|
||||
["028", "Bank OCBC NISP Tbk"],
|
||||
["030", "American Express Bank"],
|
||||
["031", "Citibank N.A."],
|
||||
["032", "JP. Morgan Chase Bank NA"],
|
||||
["033", "Bank of America N.A."],
|
||||
["034", "ING Indonesia Bank"],
|
||||
["036", "Bank Ekspor Indonesia"],
|
||||
["037", "Bank Artha Graha Int'l"],
|
||||
["039", "Bank Credit Agricole Indosuez"],
|
||||
["040", "The Bank of Hongkong & Shanghai B.C. (Hongkong)"],
|
||||
["041", "The Bank of Tokyo Mitsubishi UFJ"],
|
||||
["042", "Bank Sumitomo Mitsui Indonesia"],
|
||||
["045", "Bank Sumitomo Mitsui Indonesia"],
|
||||
["046", "Bank DBS Indonesia"],
|
||||
["047", "Bank Resona Perdania"],
|
||||
["048", "Bank Mizuho Indonesia"],
|
||||
["050", "Standard Chartered Bank"],
|
||||
["052", "Bank ABN Amro"],
|
||||
["053", "Bank Keppel Tatlee Buana"],
|
||||
["054", "Bank Capital Indonesia"],
|
||||
["057", "Bank BNP Paribas Indonesia"],
|
||||
["059", "Korea Exchange Bank Danamon"],
|
||||
["061", "ANZ Indonesia"],
|
||||
["067", "Deutsche Bank AG"],
|
||||
["068", "Bank Woori Indonesia"],
|
||||
["069", "Bank of China"],
|
||||
["076", "Bank Bumi Arta"],
|
||||
["089", "Bank IFI"],
|
||||
["093", "Bank Jtrust"],
|
||||
["097", "Bank Haja"],
|
||||
["110", "Bank Jabar Banten (BJB)"],
|
||||
["111", "Bank DKI"],
|
||||
["112", "Bank Pembangunan Daerah Daerah Istimewa Yogyakarta"],
|
||||
["113", "Bank Jateng"],
|
||||
["114", "Bank Jatim"],
|
||||
["115", "Bank Jambi"],
|
||||
["116", "Bank Aceh"],
|
||||
["117", "Bank Sumut"],
|
||||
["118", "Bank Nagari"],
|
||||
["119", "Bank Riau Kepri"],
|
||||
["120", "Bank Sumsel Babel"],
|
||||
["121", "Bank Lampung"],
|
||||
["122", "Bank Kalsel"],
|
||||
["123", "Bank Kaltimtara"],
|
||||
["124", "Bank Kaltim & Utara"],
|
||||
["125", "Bank Kalteng"],
|
||||
["126", "Bank Sulselbar"],
|
||||
["127", "Bank SulutGo"],
|
||||
["128", "Bank NTB Syariah"],
|
||||
["129", "Bank Bali"],
|
||||
["130", "Bank NTT"],
|
||||
["131", "Bank Maluku Malut"],
|
||||
["132", "Bank Papua"],
|
||||
["133", "Bank Bengkulu"],
|
||||
["134", "Bank Sulselbar"],
|
||||
["135", "Bank Sultra"],
|
||||
["136", "Bank Sulawesi Tenggara"],
|
||||
["137", "Bank Sulawesi Tengah"],
|
||||
["138", "Bank Sulawesi Selatan"],
|
||||
["139", "Bank Sulawesi Utara"],
|
||||
["141", "Bank Kalteng (Kaltimtara)"],
|
||||
["147", "Bank Muamalat Indonesia"],
|
||||
["145", "Bank Nusantara Parahyangan"],
|
||||
["146", "Bank of India Indonesia"],
|
||||
["151", "Bank Mestika Dharma"],
|
||||
["152", "Shinhan Bank Indonesia (Metro Express)"],
|
||||
["153", "Bank Sinarmas"],
|
||||
["157", "Bank Maspion"],
|
||||
["159", "Bank Hagakita"],
|
||||
["161", "Bank Ganesha"],
|
||||
["162", "Bank Windu Kentjana"],
|
||||
["166", "Bank ICBC Indonesia (Halim Indonesia Bank)"],
|
||||
["167", "Bank QNB Indonesia (QNB Kesawan)"],
|
||||
["171", "Bank of Tokyo Mitsubishi UFJ Indonesia"],
|
||||
["176", "Bank QNB Indonesia"],
|
||||
["186", "Bank Agris"],
|
||||
["213", "Bank Tabungan Pensiunan Nasional (BTPN)"],
|
||||
["200", "Bank Tabungan Negara (BTN)"],
|
||||
["203", "Bank Bumi Arta"],
|
||||
["213", "BTPN/Jenius BTPN"],
|
||||
["216", "Bank Artha Graha International"],
|
||||
["240", "Bank Victoria International"],
|
||||
["244", "Bank Index Selindo"],
|
||||
["245", "Bank Kesejahteraan Ekonomi"],
|
||||
["246", "Bank Harfa"],
|
||||
["247", "Bank Artos Indonesia"],
|
||||
["251", "Prima Master Bank"],
|
||||
["252", "Bank Persyarikatan Indonesia"],
|
||||
["253", "Liman International Bank"],
|
||||
["254", "Bank Dipo International (Sahabat Sampoerna)"],
|
||||
["255", "Bank Fama Internasional"],
|
||||
["256", "Bank Kesehatan Bumi Arta"],
|
||||
["257", "Bank Mayora Indonesia"],
|
||||
["258", "Bank Royal Indonesia"],
|
||||
["259", "Centratama Nasional Bank"],
|
||||
["261", "Bank Indonesia"],
|
||||
["262", "Bank Multika"],
|
||||
["263", "Bank Permata"],
|
||||
["267", "Bank Raya Indonesia"],
|
||||
["273", "Bank Nusantara Parahyangan Syariah"],
|
||||
["274", "Bank Jasa Jakarta"],
|
||||
["275", "Bank Alfindo"],
|
||||
["282", "Bank Yudha Bhakti"],
|
||||
["283", "Bank MNC"],
|
||||
["285", "Bank Bintang Manunggal"],
|
||||
["286", "Bank Haga"],
|
||||
["287", "Bank Mega"],
|
||||
["294", "Bank Bisnis Internasional"],
|
||||
["295", "Bank Sri Partha"],
|
||||
["422", "BRI Syariah (migrasi ke BSI)"],
|
||||
["423", "BCA Syariah"],
|
||||
["425", "Bank BJB Syariah"],
|
||||
["426", "Bank Mega"],
|
||||
["427", "Bank Syariah Mandiri / BNI Syariah"],
|
||||
["431", "Bank BTPN Syariah"],
|
||||
["451", "Bank Syariah Indonesia"],
|
||||
["453", "Bank BPD Kaltim"],
|
||||
["454", "Bank Jatim Syariah"],
|
||||
["456", "Bank Nusantara Parahyangan Syariah"],
|
||||
["503", "Bank Agris"],
|
||||
["506", "Bank Sinarmas Syariah"],
|
||||
["510", "Prima Master Bank"],
|
||||
["513", "Bank Ina Perdana"],
|
||||
["517", "Bank Harfa"],
|
||||
["521", "Bank Akita"],
|
||||
["526", "Liman International Bank"],
|
||||
["531", "Anglomas Internasional Bank"],
|
||||
["535", "Bank Kesejahteraan"],
|
||||
["536", "BCA Syariah"],
|
||||
["542", "Artos Indonesia Bank"],
|
||||
["547", "Bank Purba Danarta"],
|
||||
["548", "Bank Multi Arta Sentosa"],
|
||||
["550", "Bank Andara"],
|
||||
["553", "Mayora Bank"],
|
||||
["555", "Bank Victoria International"],
|
||||
["562", "Bank Fama International"],
|
||||
["564", "Bank Mandiri Taspen Pos"],
|
||||
["566", "Bank Victoria International"],
|
||||
["567", "Bank Harda"],
|
||||
["688", "BPR KS"],
|
||||
["761", "Bank Rakyat Indonesia"],
|
||||
["789", "Indosat Dompetku"],
|
||||
["811", "BPR Bank Indonesia"],
|
||||
["836", "Bank OCBC NISP"],
|
||||
["911", "Link Aja"],
|
||||
["949", "Bank CTBC (China Trust) Indonesia"],
|
||||
["950", "Bank Commonwealth"],
|
||||
["956", "Bank Merincorp"],
|
||||
["957", "Bank Diners Club"],
|
||||
["985", "The Royal Bank"],
|
||||
["988", "Bank Swaguna"],
|
||||
["989", "Bank QNB Indonesia"],
|
||||
["990", "Bank Swaguna"],
|
||||
["992", "Bank Himpunan Saudara"],
|
||||
["993", "Bank Jasa Jakarta"],
|
||||
["994", "Bank Swaguna"]
|
||||
];
|
||||
|
||||
function toRecords(list) {
|
||||
const byCode = new Map();
|
||||
const byName = new Set();
|
||||
|
||||
for (const [code, name] of list) {
|
||||
const trimmedCode = String(code).trim().padStart(3, "0");
|
||||
const trimmedName = String(name).trim();
|
||||
if (!trimmedCode || !trimmedName) continue;
|
||||
const normalizedName = trimmedName.toUpperCase();
|
||||
|
||||
if (!byCode.has(trimmedCode) && !byName.has(normalizedName)) {
|
||||
byCode.set(trimmedCode, trimmedName);
|
||||
byName.add(normalizedName);
|
||||
}
|
||||
}
|
||||
return [...byCode.entries()].map(([code, name]) => ({ code, name, address: "Indonesia" }));
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const records = toRecords(banks);
|
||||
let created = 0;
|
||||
let updated = 0;
|
||||
|
||||
for (const record of records) {
|
||||
const current = await prisma.bank.findUnique({ where: { code: record.code } });
|
||||
if (current) {
|
||||
await prisma.bank.update({
|
||||
where: { code: record.code },
|
||||
data: { name: record.name, address: record.address, status: "ACTIVE" }
|
||||
});
|
||||
updated += 1;
|
||||
} else {
|
||||
await prisma.bank.create({
|
||||
data: { code: record.code, name: record.name, address: record.address, status: "ACTIVE" }
|
||||
});
|
||||
created += 1;
|
||||
}
|
||||
}
|
||||
|
||||
const total = await prisma.bank.count();
|
||||
console.log(`Seeded banks: created=${created}, updated=${updated}, total=${total}`);
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exitCode = 1;
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect();
|
||||
});
|
||||
77
scripts/seed-global-currencies.mjs
Normal file
77
scripts/seed-global-currencies.mjs
Normal file
@ -0,0 +1,77 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
const globalCurrencies = [
|
||||
["IDR", "Indonesian Rupiah", "Mata uang default sistem."],
|
||||
["USD", "US Dollar", "Mata uang internasional umum."],
|
||||
["EUR", "Euro", "Mata uang utama kawasan Euro."],
|
||||
["GBP", "British Pound Sterling", "Mata uang utama Inggris."],
|
||||
["JPY", "Japanese Yen", "Mata uang utama Jepang."],
|
||||
["CNY", "Chinese Yuan Renminbi", "Mata uang utama Tiongkok."],
|
||||
["HKD", "Hong Kong Dollar", "Mata uang utama Hong Kong."],
|
||||
["SGD", "Singapore Dollar", "Mata uang regional umum."],
|
||||
["AUD", "Australian Dollar", "Mata uang utama Australia."],
|
||||
["NZD", "New Zealand Dollar", "Mata uang utama Selandia Baru."],
|
||||
["CAD", "Canadian Dollar", "Mata uang utama Kanada."],
|
||||
["CHF", "Swiss Franc", "Mata uang utama Swiss."],
|
||||
["SEK", "Swedish Krona", "Mata uang utama Swedia."],
|
||||
["NOK", "Norwegian Krone", "Mata uang utama Norwegia."],
|
||||
["DKK", "Danish Krone", "Mata uang utama Denmark."],
|
||||
["PLN", "Polish Zloty", "Mata uang utama Polandia."],
|
||||
["CZK", "Czech Koruna", "Mata uang utama Ceko."],
|
||||
["HUF", "Hungarian Forint", "Mata uang utama Hungaria."],
|
||||
["AED", "UAE Dirham", "Mata uang utama Uni Emirat Arab."],
|
||||
["SAR", "Saudi Riyal", "Mata uang utama Arab Saudi."],
|
||||
["QAR", "Qatari Riyal", "Mata uang utama Qatar."],
|
||||
["KWD", "Kuwaiti Dinar", "Mata uang utama Kuwait."],
|
||||
["BHD", "Bahraini Dinar", "Mata uang utama Bahrain."],
|
||||
["OMR", "Omani Rial", "Mata uang utama Oman."],
|
||||
["INR", "Indian Rupee", "Mata uang utama India."],
|
||||
["PKR", "Pakistani Rupee", "Mata uang utama Pakistan."],
|
||||
["BDT", "Bangladeshi Taka", "Mata uang utama Bangladesh."],
|
||||
["KRW", "South Korean Won", "Mata uang utama Korea Selatan."],
|
||||
["TWD", "New Taiwan Dollar", "Mata uang utama Taiwan."],
|
||||
["THB", "Thai Baht", "Mata uang utama Thailand."],
|
||||
["MYR", "Malaysian Ringgit", "Mata uang utama Malaysia."],
|
||||
["PHP", "Philippine Peso", "Mata uang utama Filipina."],
|
||||
["VND", "Vietnamese Dong", "Mata uang utama Vietnam."],
|
||||
["KHR", "Cambodian Riel", "Mata uang utama Kamboja."],
|
||||
["LAK", "Lao Kip", "Mata uang utama Laos."],
|
||||
["MMK", "Myanmar Kyat", "Mata uang utama Myanmar."],
|
||||
["ZAR", "South African Rand", "Mata uang utama Afrika Selatan."],
|
||||
["NGN", "Nigerian Naira", "Mata uang utama Nigeria."],
|
||||
["EGP", "Egyptian Pound", "Mata uang utama Mesir."],
|
||||
["KES", "Kenyan Shilling", "Mata uang utama Kenya."],
|
||||
["TRY", "Turkish Lira", "Mata uang utama Turki."],
|
||||
["ILS", "Israeli New Shekel", "Mata uang utama Israel."],
|
||||
["MXN", "Mexican Peso", "Mata uang utama Meksiko."],
|
||||
["BRL", "Brazilian Real", "Mata uang utama Brasil."],
|
||||
["ARS", "Argentine Peso", "Mata uang utama Argentina."],
|
||||
["CLP", "Chilean Peso", "Mata uang utama Chili."],
|
||||
["COP", "Colombian Peso", "Mata uang utama Kolombia."],
|
||||
["PEN", "Peruvian Sol", "Mata uang utama Peru."]
|
||||
];
|
||||
|
||||
async function main() {
|
||||
const result = await prisma.currency.createMany({
|
||||
data: globalCurrencies.map(([code, name, description]) => ({
|
||||
code,
|
||||
name,
|
||||
description,
|
||||
status: "ACTIVE"
|
||||
})),
|
||||
skipDuplicates: true
|
||||
});
|
||||
|
||||
console.log(JSON.stringify({ inserted: result.count, total_candidates: globalCurrencies.length }, null, 2));
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exitCode = 1;
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect();
|
||||
});
|
||||
67
scripts/seed-grades-from-xls.mjs
Normal file
67
scripts/seed-grades-from-xls.mjs
Normal file
@ -0,0 +1,67 @@
|
||||
import path from "node:path";
|
||||
|
||||
import XLSX from "xlsx";
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
const sourcePath =
|
||||
process.argv[2] ?? "/Users/wirabasalamah/work/abelbirdnest/data gudang/Grade.xls";
|
||||
|
||||
function formatCode(prefix, sequence) {
|
||||
return `${prefix}${String(sequence).padStart(5, "0")}`;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const workbook = XLSX.readFile(sourcePath);
|
||||
const sheetName = workbook.SheetNames[0];
|
||||
const rows = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName], { defval: "" });
|
||||
|
||||
let mangkokSequence = 1;
|
||||
let nonMangkokSequence = 1;
|
||||
|
||||
for (const row of rows) {
|
||||
const legacyCode = String(row.Code || "").trim();
|
||||
const name = String(row.Name || "").trim();
|
||||
const description = String(row.Description || "").trim();
|
||||
const isMangkok = String(row.Mangkok || "").trim().toLowerCase() === "yes";
|
||||
|
||||
if (!name) continue;
|
||||
|
||||
const prefix = isMangkok ? "MGK" : "GRD";
|
||||
const code = isMangkok
|
||||
? formatCode(prefix, mangkokSequence++)
|
||||
: formatCode(prefix, nonMangkokSequence++);
|
||||
|
||||
await prisma.grade.upsert({
|
||||
where: { legacyCode: legacyCode || "__missing__" },
|
||||
update: {
|
||||
code,
|
||||
isMangkok,
|
||||
name,
|
||||
description: description || null,
|
||||
status: "ACTIVE"
|
||||
},
|
||||
create: {
|
||||
code,
|
||||
legacyCode: legacyCode || null,
|
||||
isMangkok,
|
||||
name,
|
||||
description: description || null,
|
||||
status: "ACTIVE"
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const count = await prisma.grade.count();
|
||||
console.log(`Seeded grades: ${count} from ${path.basename(sourcePath)}`);
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exitCode = 1;
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect();
|
||||
});
|
||||
Reference in New Issue
Block a user