feat(watcher): add BRI QRIS parsing and rules
Implement parsing for BRI QRIS transactions, including direct and forwarded message handling. Update rules to recognize QRIS success messages and adjust spending record mapping accordingly. Enhance tests to cover new functionality.
This commit is contained in:
@@ -1,13 +1,16 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { describe, it } from "node:test";
|
||||
import { parseBriTransfer } from "../src/parsers/bri.js";
|
||||
import { parseBriQris, parseBriTransfer } from "../src/parsers/bri.js";
|
||||
import { parseGrabReceipt, extractGrabTripTimesFromHtml } from "../src/parsers/grab.js";
|
||||
import { parseLivinReceipt, splitMerchantLocation } from "../src/parsers/livin.js";
|
||||
import { toSpendingRecord, toPocketBaseDate } from "../src/pocketbase/map.js";
|
||||
import { briQris } from "../src/rules/bri-qris.js";
|
||||
import { briTransfer } from "../src/rules/bri-transfer.js";
|
||||
import { livinQrPayment } from "../src/rules/livin-qr-payment.js";
|
||||
import { grabEreceipt } from "../src/rules/grab-ereceipt.js";
|
||||
import {
|
||||
briQrisDirectBody,
|
||||
briQrisForwardedBody,
|
||||
briTransferDirectBody,
|
||||
briTransferForwardedBody,
|
||||
grabBody,
|
||||
@@ -177,6 +180,56 @@ describe("parseBriTransfer", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("parseBriQris", () => {
|
||||
it("parses direct BRImo QRIS body", () => {
|
||||
const r = parseBriQris(briQrisDirectBody);
|
||||
assert.ok(r);
|
||||
assert.equal(r.amount, 674500);
|
||||
assert.equal(r.reference, "185794483464");
|
||||
assert.equal(r.occurredAt, "2026-07-30T19:21:34+07:00");
|
||||
assert.equal(r.details.payerName, "NASYAROBBY NUGRAHA PUTRA");
|
||||
assert.equal(r.details.merchant, "Shopee Indonesia");
|
||||
assert.equal(r.details.location, "KOTA JAKARTA");
|
||||
assert.equal(r.details.jenisTransaksi, "QRIS Bayar");
|
||||
assert.equal(r.details.acquirer, "Shopeepay");
|
||||
assert.equal(r.details.issuer, "BRI");
|
||||
assert.equal(r.details.customerPan, "9360000210106600585");
|
||||
assert.equal(r.details.merchantPan, "936009180021573212");
|
||||
assert.equal(r.details.terminalId, "21573212");
|
||||
assert.equal(r.details.biayaAdmin, 0);
|
||||
assert.equal(
|
||||
r.details.fundingSource,
|
||||
"NASYAROBBY NUGRAHA PUTRA 0121 **** **** 500",
|
||||
);
|
||||
});
|
||||
|
||||
it("parses forwarded BRImo QRIS body", () => {
|
||||
const r = parseBriQris(briQrisForwardedBody);
|
||||
assert.ok(r);
|
||||
assert.equal(r.amount, 674500);
|
||||
assert.equal(r.reference, "185794483464");
|
||||
assert.equal(r.details.merchant, "Shopee Indonesia");
|
||||
});
|
||||
|
||||
it("falls back to Total Transaksi when Nominal missing", () => {
|
||||
const body = `Halo FOO,
|
||||
Total Transaksi
|
||||
12.500
|
||||
Nomor Referensi 999
|
||||
Tanggal Transaksi 1 Jan 2026, 10:00:00 WIB
|
||||
Nama Merchant Cafe
|
||||
`;
|
||||
const r = parseBriQris(body);
|
||||
assert.ok(r);
|
||||
assert.equal(r.amount, 12500);
|
||||
assert.equal(r.reference, "999");
|
||||
});
|
||||
|
||||
it("returns null without amount/reference", () => {
|
||||
assert.equal(parseBriQris("Halo someone\nNama Merchant Foo"), null);
|
||||
});
|
||||
});
|
||||
|
||||
describe("toSpendingRecord", () => {
|
||||
it("maps Livin envelope to spendings fields", () => {
|
||||
const parsed = {
|
||||
@@ -273,4 +326,24 @@ describe("toSpendingRecord", () => {
|
||||
assert.equal(rec.trx_date, toPocketBaseDate(parsed.occurredAt));
|
||||
assert.deepEqual(rec.parsed, parsed);
|
||||
});
|
||||
|
||||
it("maps BRI QRIS envelope to spendings fields", () => {
|
||||
const parsed = {
|
||||
kind: "bri.qris.success",
|
||||
messageId: "1a09b9031c233407",
|
||||
amount: 674500,
|
||||
reference: "185794483464",
|
||||
occurredAt: "2026-07-30T19:21:34+07:00",
|
||||
details: {
|
||||
merchant: "Shopee Indonesia",
|
||||
location: "KOTA JAKARTA",
|
||||
},
|
||||
};
|
||||
const rec = toSpendingRecord(parsed, briQris);
|
||||
assert.equal(rec.invoice_id, "185794483464");
|
||||
assert.equal(rec.amount, 674500);
|
||||
assert.equal(rec.source, "bri");
|
||||
assert.equal(rec.description, "Shopee Indonesia");
|
||||
assert.equal(rec.trx_date, toPocketBaseDate(parsed.occurredAt));
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user