@mulmoclaude/accounting-plugin 0.2.0 → 0.3.0
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/server/io.d.ts.map +1 -1
- package/dist/server/router.d.ts.map +1 -1
- package/dist/server/service.d.ts +2 -2
- package/dist/server/service.d.ts.map +1 -1
- package/dist/server/types.d.ts +7 -6
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server.cjs +38 -10
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +39 -11
- package/dist/server.js.map +1 -1
- package/dist/shared/fiscalYear.d.ts +19 -8
- package/dist/shared/fiscalYear.d.ts.map +1 -1
- package/dist/shared.cjs +55 -17
- package/dist/shared.cjs.map +1 -1
- package/dist/shared.js +54 -17
- package/dist/shared.js.map +1 -1
- package/dist/style.css +1 -1
- package/dist/vue/api.d.ts +10 -10
- package/dist/vue/api.d.ts.map +1 -1
- package/dist/vue/components/BookSettings.vue.d.ts.map +1 -1
- package/dist/vue/components/NewBookForm.vue.d.ts.map +1 -1
- package/dist/vue/lang/de.d.ts.map +1 -1
- package/dist/vue/lang/en.d.ts +0 -4
- package/dist/vue/lang/en.d.ts.map +1 -1
- package/dist/vue/lang/es.d.ts.map +1 -1
- package/dist/vue/lang/fr.d.ts.map +1 -1
- package/dist/vue/lang/index.d.ts +0 -4
- package/dist/vue/lang/index.d.ts.map +1 -1
- package/dist/vue/lang/ja.d.ts.map +1 -1
- package/dist/vue/lang/ko.d.ts.map +1 -1
- package/dist/vue/lang/ptBR.d.ts.map +1 -1
- package/dist/vue/lang/zh.d.ts.map +1 -1
- package/dist/vue.cjs +16 -48
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.js +17 -49
- package/dist/vue.js.map +1 -1
- package/package.json +3 -3
package/dist/server.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ACCOUNTING_ACTIONS, ACCOUNTING_API, ACCOUNTING_BOOKS_CHANNEL, ACCOUNTING_DIRS, BOOK_EVENT_KINDS,
|
|
1
|
+
import { ACCOUNTING_ACTIONS, ACCOUNTING_API, ACCOUNTING_BOOKS_CHANNEL, ACCOUNTING_DIRS, BOOK_EVENT_KINDS, FISCAL_YEAR_END_MONTHS, SUPPORTED_COUNTRY_CODES, TIME_SERIES_GRANULARITIES, TIME_SERIES_METRICS, bookChannel, errorMessage, fiscalYearEndMonth, isFiscalYearEnd, isSupportedCountryCode, resolveFiscalYearEnd } from "./shared.js";
|
|
2
2
|
import { Router } from "express";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
4
|
import { promises } from "node:fs";
|
|
@@ -142,8 +142,27 @@ async function readJsonStrict(filePath) {
|
|
|
142
142
|
throw err;
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
|
+
/** Migrate a legacy calendar-quarter `fiscalYearEnd` token ("Q1".."Q4")
|
|
146
|
+
* to its closing-month number in memory so every downstream consumer
|
|
147
|
+
* (reports, time-series, the UI selects) sees one shape. Absent stays
|
|
148
|
+
* absent — the field is optional and resolves to the default on read;
|
|
149
|
+
* we don't stamp an explicit December onto a book that never chose one.
|
|
150
|
+
* Nothing is written back here (no auto-migrate on disk). */
|
|
151
|
+
function normalizeBookFiscalYearEnd(book) {
|
|
152
|
+
if (book.fiscalYearEnd === void 0) return book;
|
|
153
|
+
const resolved = resolveFiscalYearEnd(book.fiscalYearEnd);
|
|
154
|
+
return book.fiscalYearEnd === resolved ? book : {
|
|
155
|
+
...book,
|
|
156
|
+
fiscalYearEnd: resolved
|
|
157
|
+
};
|
|
158
|
+
}
|
|
145
159
|
async function readConfig(workspaceRoot) {
|
|
146
|
-
|
|
160
|
+
const config = await readJsonStrict(configPath(workspaceRoot));
|
|
161
|
+
if (!config) return null;
|
|
162
|
+
return {
|
|
163
|
+
...config,
|
|
164
|
+
books: config.books.map(normalizeBookFiscalYearEnd)
|
|
165
|
+
};
|
|
147
166
|
}
|
|
148
167
|
async function writeConfig(config, workspaceRoot) {
|
|
149
168
|
await writeJsonAtomic(configPath(workspaceRoot), config);
|
|
@@ -1464,13 +1483,13 @@ function unsupportedCountryError(received) {
|
|
|
1464
1483
|
return new AccountingError(400, `unsupported country code ${JSON.stringify(received)} — must be one of: ${SUPPORTED_COUNTRY_CODES.join(", ")}`);
|
|
1465
1484
|
}
|
|
1466
1485
|
function unsupportedFiscalYearEndError(received) {
|
|
1467
|
-
return new AccountingError(400, `unsupported fiscalYearEnd ${JSON.stringify(received)} — must be
|
|
1486
|
+
return new AccountingError(400, `unsupported fiscalYearEnd ${JSON.stringify(received)} — must be a closing-month number ${FISCAL_YEAR_END_MONTHS.join(", ")} (1 = January … 12 = December)`);
|
|
1468
1487
|
}
|
|
1469
|
-
/** Narrow a free-form `fiscalYearEnd` input.
|
|
1488
|
+
/** Narrow a free-form `fiscalYearEnd` input. Absent → default
|
|
1470
1489
|
* (back-compat with old callers and pre-field on-disk books); any
|
|
1471
|
-
* other value must
|
|
1490
|
+
* other value must be a month number 1-12 or 400. */
|
|
1472
1491
|
function narrowFiscalYearEnd(raw) {
|
|
1473
|
-
if (raw === void 0
|
|
1492
|
+
if (raw === void 0) return 12;
|
|
1474
1493
|
if (!isFiscalYearEnd(raw)) throw unsupportedFiscalYearEndError(raw);
|
|
1475
1494
|
return raw;
|
|
1476
1495
|
}
|
|
@@ -1481,7 +1500,7 @@ function narrowFiscalYearEnd(raw) {
|
|
|
1481
1500
|
function validateUpdateBookInput(input) {
|
|
1482
1501
|
if (input.name !== void 0 && (typeof input.name !== "string" || input.name.trim() === "")) throw new AccountingError(400, "name must be a non-empty string when supplied");
|
|
1483
1502
|
if (input.country !== void 0 && input.country !== "" && !isSupportedCountryCode(input.country)) throw unsupportedCountryError(input.country);
|
|
1484
|
-
if (input.fiscalYearEnd !== void 0 &&
|
|
1503
|
+
if (input.fiscalYearEnd !== void 0 && !isFiscalYearEnd(input.fiscalYearEnd)) throw unsupportedFiscalYearEndError(input.fiscalYearEnd);
|
|
1485
1504
|
}
|
|
1486
1505
|
async function createBook(input, workspaceRoot) {
|
|
1487
1506
|
if (typeof input.name !== "string" || input.name.trim() === "") throw new AccountingError(400, "name is required");
|
|
@@ -1515,7 +1534,7 @@ async function updateBook(input, workspaceRoot) {
|
|
|
1515
1534
|
...target,
|
|
1516
1535
|
...input.name !== void 0 ? { name: input.name } : {},
|
|
1517
1536
|
...input.country !== void 0 && input.country !== "" ? { country: input.country } : {},
|
|
1518
|
-
...input.fiscalYearEnd !== void 0
|
|
1537
|
+
...input.fiscalYearEnd !== void 0 ? { fiscalYearEnd: input.fiscalYearEnd } : {}
|
|
1519
1538
|
};
|
|
1520
1539
|
if (input.country === "") delete next.country;
|
|
1521
1540
|
await writeConfig({ books: config.books.map((book) => book.id === input.bookId ? next : book) }, workspaceRoot);
|
|
@@ -1800,7 +1819,7 @@ async function loadTimeSeriesBookContext(requestedBookId, workspaceRoot) {
|
|
|
1800
1819
|
const bookId = resolveBookId(config, requestedBookId);
|
|
1801
1820
|
return {
|
|
1802
1821
|
bookId,
|
|
1803
|
-
fiscalYearEnd: findBook(config, bookId)?.fiscalYearEnd
|
|
1822
|
+
fiscalYearEnd: resolveFiscalYearEnd(findBook(config, bookId)?.fiscalYearEnd),
|
|
1804
1823
|
accounts: await readAccounts(bookId, workspaceRoot)
|
|
1805
1824
|
};
|
|
1806
1825
|
}
|
|
@@ -1863,6 +1882,15 @@ function asyncHandler(namespace, fallbackMessage, handler) {
|
|
|
1863
1882
|
}
|
|
1864
1883
|
//#endregion
|
|
1865
1884
|
//#region src/server/router.ts
|
|
1885
|
+
/** Coerce an inbound `fiscalYearEnd` to a number. The UI select and
|
|
1886
|
+
* the LLM tool (JSON-schema `number` enum) both send a number, but a
|
|
1887
|
+
* numeric string ("8") from a hand-rolled client is accepted too so
|
|
1888
|
+
* it isn't silently dropped to `undefined` (→ the December default).
|
|
1889
|
+
* Range validation stays authoritative in the service layer. */
|
|
1890
|
+
function coerceFiscalYearEnd(raw) {
|
|
1891
|
+
if (typeof raw === "number") return raw;
|
|
1892
|
+
if (typeof raw === "string" && raw.trim() !== "" && Number.isInteger(Number(raw))) return Number(raw);
|
|
1893
|
+
}
|
|
1866
1894
|
async function handleOpenBook(rest) {
|
|
1867
1895
|
if (typeof rest.bookId !== "string" || rest.bookId === "") throw new AccountingError(400, "openBook: bookId is required. Call 'getBooks' to enumerate, or 'createBook' first on a fresh workspace.");
|
|
1868
1896
|
const list = await listBooks();
|
|
@@ -1911,7 +1939,7 @@ var ACTION_HANDLERS = {
|
|
|
1911
1939
|
name: String(rest.name ?? ""),
|
|
1912
1940
|
currency: typeof rest.currency === "string" ? rest.currency : void 0,
|
|
1913
1941
|
country: typeof rest.country === "string" ? rest.country : void 0,
|
|
1914
|
-
fiscalYearEnd:
|
|
1942
|
+
fiscalYearEnd: coerceFiscalYearEnd(rest.fiscalYearEnd)
|
|
1915
1943
|
});
|
|
1916
1944
|
return {
|
|
1917
1945
|
bookId: result.book.id,
|
|
@@ -1923,7 +1951,7 @@ var ACTION_HANDLERS = {
|
|
|
1923
1951
|
bookId: String(rest.bookId ?? ""),
|
|
1924
1952
|
name: typeof rest.name === "string" ? rest.name : void 0,
|
|
1925
1953
|
country: typeof rest.country === "string" ? rest.country : void 0,
|
|
1926
|
-
fiscalYearEnd:
|
|
1954
|
+
fiscalYearEnd: coerceFiscalYearEnd(rest.fiscalYearEnd)
|
|
1927
1955
|
});
|
|
1928
1956
|
return {
|
|
1929
1957
|
bookId: result.book.id,
|