paisa-mcp 0.0.16 → 0.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +58 -7
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -45732,8 +45732,39 @@ async function backfillPersons(client, crypto3, opts = {}) {
|
|
|
45732
45732
|
}
|
|
45733
45733
|
|
|
45734
45734
|
// src/tools/transactions.ts
|
|
45735
|
+
function dedupeKey(date4, description, amount, type) {
|
|
45736
|
+
return `${date4}|${description}|${amount.toFixed(2)}|${type}`;
|
|
45737
|
+
}
|
|
45735
45738
|
async function importTransactions(client, crypto3, opts) {
|
|
45736
|
-
|
|
45739
|
+
let txns = opts.txns;
|
|
45740
|
+
let duplicatesSkipped = 0;
|
|
45741
|
+
if (txns.length > 0) {
|
|
45742
|
+
const dates = txns.map((t2) => t2.date).sort();
|
|
45743
|
+
const existing = [];
|
|
45744
|
+
let cursor;
|
|
45745
|
+
for (let page = 0;page < 100; page++) {
|
|
45746
|
+
const params = {
|
|
45747
|
+
limit: 200,
|
|
45748
|
+
startDate: dates[0],
|
|
45749
|
+
endDate: dates[dates.length - 1]
|
|
45750
|
+
};
|
|
45751
|
+
if (cursor)
|
|
45752
|
+
params.cursor = cursor;
|
|
45753
|
+
const res = await client.get("/api/transactions", params);
|
|
45754
|
+
const batch = res.data ?? [];
|
|
45755
|
+
if (crypto3)
|
|
45756
|
+
await decryptTransactionFields(batch, crypto3.key);
|
|
45757
|
+
existing.push(...batch);
|
|
45758
|
+
if (!res.hasMore || !res.nextCursor || batch.length === 0)
|
|
45759
|
+
break;
|
|
45760
|
+
cursor = res.nextCursor;
|
|
45761
|
+
}
|
|
45762
|
+
const seen = new Set(existing.map((r2) => dedupeKey(String(r2.date), String(r2.description ?? ""), Number(r2.amount), String(r2.type))));
|
|
45763
|
+
const before = txns.length;
|
|
45764
|
+
txns = txns.filter((t2) => !seen.has(dedupeKey(t2.date, t2.description ?? "", t2.amount, t2.type)));
|
|
45765
|
+
duplicatesSkipped = before - txns.length;
|
|
45766
|
+
}
|
|
45767
|
+
const rows = txns.map((t2) => {
|
|
45737
45768
|
const enrichedData = settlementEnrichedData(t2.description ?? "", t2.type, opts.source);
|
|
45738
45769
|
return enrichedData ? { ...t2, enrichedData } : { ...t2 };
|
|
45739
45770
|
});
|
|
@@ -45750,7 +45781,7 @@ async function importTransactions(client, crypto3, opts) {
|
|
|
45750
45781
|
});
|
|
45751
45782
|
imported += res.imported ?? 0;
|
|
45752
45783
|
}
|
|
45753
|
-
return { imported };
|
|
45784
|
+
return { imported, duplicatesSkipped };
|
|
45754
45785
|
}
|
|
45755
45786
|
async function runRescan(client, crypto3) {
|
|
45756
45787
|
const EMPTY_BAG2 = {
|
|
@@ -45831,12 +45862,22 @@ function registerTransactionTools(server, client, crypto3) {
|
|
|
45831
45862
|
type: exports_external.enum(["debit", "credit"]).optional(),
|
|
45832
45863
|
amountMin: exports_external.number().optional(),
|
|
45833
45864
|
amountMax: exports_external.number().optional(),
|
|
45834
|
-
|
|
45835
|
-
|
|
45865
|
+
uncategorized: exports_external.boolean().optional().describe("Only transactions with no category (server-side filter)"),
|
|
45866
|
+
limit: exports_external.number().optional().describe("Max results (default 50, max 200)"),
|
|
45867
|
+
cursor: exports_external.string().optional().describe("Opaque cursor from a prior page's nextCursor")
|
|
45836
45868
|
}
|
|
45837
45869
|
}, async (params) => {
|
|
45838
|
-
const { personName, ...rest } = params;
|
|
45870
|
+
const { personName, categorySlug, ...rest } = params;
|
|
45839
45871
|
const apiParams = { ...rest };
|
|
45872
|
+
if (apiParams.uncategorized !== true)
|
|
45873
|
+
delete apiParams.uncategorized;
|
|
45874
|
+
if (categorySlug) {
|
|
45875
|
+
const cats = await client.get("/api/categories");
|
|
45876
|
+
const all2 = cats.data.flatMap((c2) => [c2, ...c2.children ?? []]);
|
|
45877
|
+
const match = all2.find((c2) => c2.slug === categorySlug);
|
|
45878
|
+
if (match)
|
|
45879
|
+
apiParams.categoryId = match.id;
|
|
45880
|
+
}
|
|
45840
45881
|
if (personName && !apiParams.personId) {
|
|
45841
45882
|
const persons = await loadDecryptedPersons(client, crypto3);
|
|
45842
45883
|
const match = resolvePersonByName(persons, personName);
|
|
@@ -45867,8 +45908,18 @@ function registerTransactionTools(server, client, crypto3) {
|
|
|
45867
45908
|
apiParams.personId = match.personId;
|
|
45868
45909
|
}
|
|
45869
45910
|
const data = await client.get("/api/transactions", Object.fromEntries(Object.entries(apiParams).filter(([, v2]) => v2 !== undefined).map(([k2, v2]) => [k2, String(v2)])));
|
|
45870
|
-
if (crypto3 && data.data)
|
|
45911
|
+
if (crypto3 && data.data) {
|
|
45871
45912
|
await decryptTransactionFields(data.data, crypto3.key);
|
|
45913
|
+
if (data.data.some((r2) => r2.personId)) {
|
|
45914
|
+
const persons = await loadDecryptedPersons(client, crypto3);
|
|
45915
|
+
const nameById = new Map(persons.map((p2) => [p2.id, p2.name]));
|
|
45916
|
+
for (const r2 of data.data) {
|
|
45917
|
+
const person = r2.person;
|
|
45918
|
+
if (person && nameById.has(person.id))
|
|
45919
|
+
person.name = nameById.get(person.id);
|
|
45920
|
+
}
|
|
45921
|
+
}
|
|
45922
|
+
}
|
|
45872
45923
|
return { content: [{ type: "text", text: JSON.stringify(data) }] };
|
|
45873
45924
|
});
|
|
45874
45925
|
server.registerTool("backfill_persons", {
|
|
@@ -46214,5 +46265,5 @@ main().catch((err) => {
|
|
|
46214
46265
|
process.exit(1);
|
|
46215
46266
|
});
|
|
46216
46267
|
|
|
46217
|
-
//# debugId=
|
|
46268
|
+
//# debugId=8B15D0182D36A5DF64756E2164756E21
|
|
46218
46269
|
//# sourceMappingURL=index.js.map
|