@mulmoclaude/accounting-plugin 1.2.1 → 1.2.2

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/vue.js CHANGED
@@ -1,4 +1,4 @@
1
- import { A as resolveFiscalYearEnd, B as ACCOUNTING_API, C as currentFiscalYearRange, E as fiscalYearEndMonthLabel, F as ACCOUNTING_BOOKS_CHANNEL, L as bookChannel, M as errorMessage, O as previousFiscalYearRange, S as FISCAL_YEAR_END_MONTHS, V as ACCOUNTING_ACTIONS, _ as SUPPORTED_COUNTRY_CODES, a as localDateString, b as localizedCountryName, c as previousMonthString, d as formatAmountNumeric, i as lastMonthOfPreviousQuarterString, k as previousQuarterRange, l as SUPPORTED_CURRENCY_CODES, m as localizedCurrencyName, o as localMonthString, p as inputStepFor, r as decemberOfPreviousYearString, u as formatAmount, v as countryHasFeature, w as currentQuarterRange, y as isSupportedCountryCode } from "./shared-qp9j-GTD.js";
1
+ import { A as resolveFiscalYearEnd, C as currentFiscalYearRange, E as fiscalYearEndMonthLabel, F as isUnknownArray, H as ACCOUNTING_API, I as ACCOUNTING_BOOKS_CHANNEL, L as BOOK_EVENT_KINDS, M as errorMessage, O as previousFiscalYearRange, P as isRecord, R as bookChannel, S as FISCAL_YEAR_END_MONTHS, U as ACCOUNTING_ACTIONS, _ as SUPPORTED_COUNTRY_CODES, a as localDateString, b as localizedCountryName, c as previousMonthString, d as formatAmountNumeric, i as lastMonthOfPreviousQuarterString, k as previousQuarterRange, l as SUPPORTED_CURRENCY_CODES, m as localizedCurrencyName, o as localMonthString, p as inputStepFor, r as decemberOfPreviousYearString, u as formatAmount, v as countryHasFeature, w as currentQuarterRange, y as isSupportedCountryCode, z as ACCOUNT_TYPES } from "./shared-xYPtGNvH.js";
2
2
  import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, nextTick, normalizeClass, onMounted, onUnmounted, openBlock, reactive, ref, renderList, toDisplayString, unref, vModelSelect, vModelText, watch, withDirectives, withKeys, withModifiers } from "vue";
3
3
  import { createPluginI18n } from "@mulmoclaude/core/plugin-vue/i18n";
4
4
  //#region src/vue/hostContext.ts
@@ -1844,7 +1844,7 @@ var NewBookForm_default = /* @__PURE__ */ defineComponent({
1844
1844
  function regionFromLocaleTag(tag) {
1845
1845
  try {
1846
1846
  const { region } = new Intl.Locale(tag).maximize();
1847
- if (region && SUPPORTED_COUNTRY_CODES.includes(region)) return region;
1847
+ if (isSupportedCountryCode(region)) return region;
1848
1848
  } catch {}
1849
1849
  return "";
1850
1850
  }
@@ -2015,7 +2015,8 @@ var BookSwitcher_default = /* @__PURE__ */ defineComponent({
2015
2015
  return `${book.name} (${suffix})`;
2016
2016
  }
2017
2017
  function onSelect(event) {
2018
- const target = event.target;
2018
+ const { target } = event;
2019
+ if (!(target instanceof HTMLSelectElement)) return;
2019
2020
  const bookId = target.value;
2020
2021
  if (bookId === NEW_BOOK_SENTINEL) {
2021
2022
  target.value = props.modelValue;
@@ -2139,7 +2140,10 @@ var DateRangePicker_default = /* @__PURE__ */ defineComponent({
2139
2140
  if (rangesEqual(value, UNBOUNDED_RANGE)) return "all";
2140
2141
  return "";
2141
2142
  });
2142
- function onShortcutChange(raw) {
2143
+ function onShortcutChange(event) {
2144
+ const { target } = event;
2145
+ if (!(target instanceof HTMLSelectElement)) return;
2146
+ const raw = target.value;
2143
2147
  const today = /* @__PURE__ */ new Date();
2144
2148
  if (raw === "currentQuarter") emit("update:modelValue", currentQuarterRange(props.fiscalYearEnd, today));
2145
2149
  else if (raw === "previousQuarter") emit("update:modelValue", previousQuarterRange(props.fiscalYearEnd, today));
@@ -2150,16 +2154,20 @@ var DateRangePicker_default = /* @__PURE__ */ defineComponent({
2150
2154
  if (lifetime) emit("update:modelValue", lifetime);
2151
2155
  } else if (raw === "all") emit("update:modelValue", UNBOUNDED_RANGE);
2152
2156
  }
2153
- function onFromChange(value) {
2157
+ function onFromChange(event) {
2158
+ const { target } = event;
2159
+ if (!(target instanceof HTMLInputElement)) return;
2154
2160
  emit("update:modelValue", {
2155
- from: value,
2161
+ from: target.value,
2156
2162
  to: props.modelValue.to
2157
2163
  });
2158
2164
  }
2159
- function onToChange(value) {
2165
+ function onToChange(event) {
2166
+ const { target } = event;
2167
+ if (!(target instanceof HTMLInputElement)) return;
2160
2168
  emit("update:modelValue", {
2161
2169
  from: props.modelValue.from,
2162
- to: value
2170
+ to: target.value
2163
2171
  });
2164
2172
  }
2165
2173
  return (_ctx, _cache) => {
@@ -2168,9 +2176,9 @@ var DateRangePicker_default = /* @__PURE__ */ defineComponent({
2168
2176
  value: selectedShortcut.value,
2169
2177
  class: "h-8 px-2 rounded border border-gray-300 text-sm bg-white",
2170
2178
  "data-testid": "accounting-daterange-shortcut",
2171
- onChange: _cache[0] || (_cache[0] = ($event) => onShortcutChange($event.target.value))
2179
+ onChange: onShortcutChange
2172
2180
  }, [
2173
- _cache[3] || (_cache[3] = createElementVNode("option", {
2181
+ _cache[0] || (_cache[0] = createElementVNode("option", {
2174
2182
  value: "",
2175
2183
  hidden: ""
2176
2184
  }, null, -1)),
@@ -2186,14 +2194,14 @@ var DateRangePicker_default = /* @__PURE__ */ defineComponent({
2186
2194
  type: "date",
2187
2195
  class: "h-8 px-2 rounded border border-gray-300 text-sm",
2188
2196
  "data-testid": "accounting-daterange-from",
2189
- onInput: _cache[1] || (_cache[1] = ($event) => onFromChange($event.target.value))
2197
+ onInput: onFromChange
2190
2198
  }, null, 40, _hoisted_11$9)]),
2191
2199
  createElementVNode("label", _hoisted_12$9, [createTextVNode(toDisplayString(unref(t)("pluginAccounting.dateRange.toLabel")) + " ", 1), createElementVNode("input", {
2192
2200
  value: __props.modelValue.to,
2193
2201
  type: "date",
2194
2202
  class: "h-8 px-2 rounded border border-gray-300 text-sm",
2195
2203
  "data-testid": "accounting-daterange-to",
2196
- onInput: _cache[2] || (_cache[2] = ($event) => onToChange($event.target.value))
2204
+ onInput: onToChange
2197
2205
  }, null, 40, _hoisted_13$9)])
2198
2206
  ]);
2199
2207
  };
@@ -2227,8 +2235,7 @@ function isValidAccountCode(code) {
2227
2235
  function typeForCode(code) {
2228
2236
  if (!isValidAccountCode(code)) return null;
2229
2237
  const leading = Number.parseInt(code[0], 10);
2230
- for (const [type, prefix] of Object.entries(ACCOUNT_TYPE_PREFIX)) if (prefix === leading) return type;
2231
- return null;
2238
+ return ACCOUNT_TYPES.find((type) => ACCOUNT_TYPE_PREFIX[type] === leading) ?? null;
2232
2239
  }
2233
2240
  function codeMatchesType(code, type) {
2234
2241
  return typeForCode(code) === type;
@@ -2640,7 +2647,7 @@ var AccountsModal_default = /* @__PURE__ */ defineComponent({
2640
2647
  }
2641
2648
  function bindNewEditor(node, sectionType) {
2642
2649
  if (sectionType !== draft.value.type) return;
2643
- newEditorWrapper.value = node ?? null;
2650
+ newEditorWrapper.value = node instanceof HTMLDivElement ? node : null;
2644
2651
  }
2645
2652
  function onEdit(account) {
2646
2653
  addingNew.value = false;
@@ -3778,12 +3785,13 @@ var OpeningBalancesForm_default = /*#__PURE__*/ _plugin_vue_export_helper_defaul
3778
3785
  for (const account of bsAccounts.value) {
3779
3786
  const row = rows.value[account.code];
3780
3787
  if (!row) continue;
3781
- const debitOk = isPositiveAmount(row.debit);
3782
- const creditOk = isPositiveAmount(row.credit);
3788
+ const { debit, credit } = row;
3789
+ const debitOk = isPositiveAmount(debit);
3790
+ const creditOk = isPositiveAmount(credit);
3783
3791
  if (!debitOk && !creditOk) continue;
3784
3792
  const line = { accountCode: account.code };
3785
- if (debitOk) line.debit = row.debit;
3786
- if (creditOk) line.credit = row.credit;
3793
+ if (debitOk) line.debit = debit;
3794
+ if (creditOk) line.credit = credit;
3787
3795
  out.push(line);
3788
3796
  }
3789
3797
  return out;
@@ -3933,7 +3941,7 @@ var OpeningBalancesForm_default = /*#__PURE__*/ _plugin_vue_export_helper_defaul
3933
3941
  }, null, 8, ["book-id", "accounts"])) : createCommentVNode("", true)], 64);
3934
3942
  };
3935
3943
  }
3936
- }), [["__scopeId", "data-v-530643ac"]]);
3944
+ }), [["__scopeId", "data-v-60e71a73"]]);
3937
3945
  //#endregion
3938
3946
  //#region src/vue/components/AccountsList.vue?vue&type=script&setup=true&lang.ts
3939
3947
  var _hoisted_1$6 = {
@@ -4316,7 +4324,10 @@ var BalanceSheet_default = /* @__PURE__ */ defineComponent({
4316
4324
  if (value === decemberOfPreviousYearString(now)) return "lastYear";
4317
4325
  return "";
4318
4326
  });
4319
- function onShortcutChange(raw) {
4327
+ function onShortcutChange(event) {
4328
+ const { target } = event;
4329
+ if (!(target instanceof HTMLSelectElement)) return;
4330
+ const raw = target.value;
4320
4331
  const now = /* @__PURE__ */ new Date();
4321
4332
  if (raw === "thisMonth") period.value = localMonthString(now);
4322
4333
  else if (raw === "lastMonth") period.value = previousMonthString(now);
@@ -4354,9 +4365,9 @@ var BalanceSheet_default = /* @__PURE__ */ defineComponent({
4354
4365
  value: selectedShortcut.value,
4355
4366
  class: "h-8 px-2 rounded border border-gray-300 text-sm bg-white",
4356
4367
  "data-testid": "accounting-bs-shortcut",
4357
- onChange: _cache[0] || (_cache[0] = ($event) => onShortcutChange($event.target.value))
4368
+ onChange: onShortcutChange
4358
4369
  }, [
4359
- _cache[2] || (_cache[2] = createElementVNode("option", {
4370
+ _cache[1] || (_cache[1] = createElementVNode("option", {
4360
4371
  value: "",
4361
4372
  hidden: ""
4362
4373
  }, null, -1)),
@@ -4366,7 +4377,7 @@ var BalanceSheet_default = /* @__PURE__ */ defineComponent({
4366
4377
  createElementVNode("option", _hoisted_8$3, toDisplayString(unref(t)("pluginAccounting.balanceSheet.lastYear")), 1)
4367
4378
  ], 40, _hoisted_4$3)]),
4368
4379
  createElementVNode("label", _hoisted_9$3, [createTextVNode(toDisplayString(unref(t)("pluginAccounting.balanceSheet.asOfLabel")) + " ", 1), withDirectives(createElementVNode("input", {
4369
- "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => period.value = $event),
4380
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => period.value = $event),
4370
4381
  type: "month",
4371
4382
  class: "h-8 px-2 rounded border border-gray-300 text-sm",
4372
4383
  "data-testid": "accounting-bs-period"
@@ -4374,7 +4385,7 @@ var BalanceSheet_default = /* @__PURE__ */ defineComponent({
4374
4385
  createElementVNode("button", {
4375
4386
  class: "h-8 px-2.5 rounded border border-gray-300 text-sm text-gray-600 hover:bg-gray-50",
4376
4387
  onClick: refresh
4377
- }, [..._cache[3] || (_cache[3] = [createElementVNode("span", { class: "material-icons text-base align-middle" }, "refresh", -1)])])
4388
+ }, [..._cache[2] || (_cache[2] = [createElementVNode("span", { class: "material-icons text-base align-middle" }, "refresh", -1)])])
4378
4389
  ]), loading.value ? (openBlock(), createElementBlock("p", _hoisted_10$3, toDisplayString(unref(t)("pluginAccounting.common.loading")), 1)) : error.value ? (openBlock(), createElementBlock("p", _hoisted_11$3, toDisplayString(unref(t)("pluginAccounting.common.error", { error: error.value })), 1)) : balanceSheet.value ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [createElementVNode("div", _hoisted_12$3, [(openBlock(true), createElementBlock(Fragment, null, renderList(balanceSheet.value.sections, (section) => {
4379
4390
  return openBlock(), createElementBlock("section", {
4380
4391
  key: section.type,
@@ -4827,6 +4838,19 @@ var BookSettings_default = /* @__PURE__ */ defineComponent({
4827
4838
  });
4828
4839
  //#endregion
4829
4840
  //#region src/vue/useAccountingChannel.ts
4841
+ var BOOK_EVENT_KIND_VALUES = Object.values(BOOK_EVENT_KINDS);
4842
+ /** The host hands subscribers an `unknown`, so rebuild the payload from
4843
+ * the fields we can prove rather than trusting the publisher's type. */
4844
+ function toBookChannelPayload(data) {
4845
+ if (typeof data !== "object" || data === null || !("kind" in data)) return null;
4846
+ const kind = BOOK_EVENT_KIND_VALUES.find((candidate) => candidate === data.kind);
4847
+ if (kind === void 0) return null;
4848
+ const period = "period" in data && typeof data.period === "string" ? data.period : void 0;
4849
+ return period === void 0 ? { kind } : {
4850
+ kind,
4851
+ period
4852
+ };
4853
+ }
4830
4854
  function useAccountingChannel(bookId, onPayload) {
4831
4855
  const version = ref(0);
4832
4856
  let unsubscribe = null;
@@ -4836,9 +4860,9 @@ function useAccountingChannel(bookId, onPayload) {
4836
4860
  version.value = 0;
4837
4861
  if (!nextBookId) return;
4838
4862
  unsubscribe = hostSubscribe(bookChannel(nextBookId), (data) => {
4839
- const event = data;
4840
4863
  version.value += 1;
4841
- onPayload?.(event);
4864
+ const event = toBookChannelPayload(data);
4865
+ if (event) onPayload?.(event);
4842
4866
  });
4843
4867
  }
4844
4868
  watch(bookId, bind, { immediate: true });
@@ -4954,7 +4978,7 @@ var View_default = /* @__PURE__ */ defineComponent({
4954
4978
  }
4955
4979
  ];
4956
4980
  function isTabKey(value) {
4957
- return typeof value === "string" && TAB_KEYS.includes(value);
4981
+ return TAB_KEYS.some((key) => key === value);
4958
4982
  }
4959
4983
  const initialPayload = computed(() => props.selectedResult?.data ?? props.selectedResult?.jsonData ?? {});
4960
4984
  const currentTab = ref(computed(() => isTabKey(initialPayload.value.initialTab) ? initialPayload.value.initialTab : "journal").value);
@@ -5259,6 +5283,73 @@ var View_default = /* @__PURE__ */ defineComponent({
5259
5283
  }
5260
5284
  });
5261
5285
  //#endregion
5286
+ //#region src/vue/previewSummary.ts
5287
+ var optionalString = (value) => typeof value === "string" ? value : void 0;
5288
+ var optionalNumber = (value) => typeof value === "number" ? value : void 0;
5289
+ function summariseError(json, translate) {
5290
+ const error = optionalString(json.error);
5291
+ if (error === void 0) return null;
5292
+ return translate("pluginAccounting.previewError", { error });
5293
+ }
5294
+ function summariseEntry(json, translate) {
5295
+ const [first] = isUnknownArray(json.entries) ? json.entries : [];
5296
+ const entry = isRecord(first) ? first : void 0;
5297
+ const entryId = optionalString(entry?.id);
5298
+ const date = optionalString(entry?.date);
5299
+ if (!entryId || !date) return null;
5300
+ return translate("pluginAccounting.preview.entry", { date });
5301
+ }
5302
+ function summarisePl(json, translate) {
5303
+ const { profitLoss } = json;
5304
+ if (!isRecord(profitLoss)) return null;
5305
+ const netIncome = optionalNumber(profitLoss.netIncome);
5306
+ if (netIncome === void 0) return null;
5307
+ return translate("pluginAccounting.preview.pl", {
5308
+ from: optionalString(profitLoss.from) ?? "?",
5309
+ to: optionalString(profitLoss.to) ?? "?",
5310
+ net: formatAmountNumeric(netIncome)
5311
+ });
5312
+ }
5313
+ function summariseBs(json, translate) {
5314
+ const { balanceSheet } = json;
5315
+ if (!isRecord(balanceSheet)) return null;
5316
+ const date = optionalString(balanceSheet.asOf);
5317
+ const sections = isUnknownArray(balanceSheet.sections) ? balanceSheet.sections : void 0;
5318
+ if (!date || !sections) return null;
5319
+ const assets = sections.find((section) => isRecord(section) && section.type === "asset");
5320
+ return translate("pluginAccounting.preview.bs", {
5321
+ date,
5322
+ assets: isRecord(assets) ? formatAmountNumeric(optionalNumber(assets.total) ?? 0) : "?"
5323
+ });
5324
+ }
5325
+ function summariseBook(json, translate) {
5326
+ const { book } = json;
5327
+ if (!isRecord(book)) return null;
5328
+ const bookId = optionalString(book.id);
5329
+ const name = optionalString(book.name);
5330
+ if (!bookId || !name) return null;
5331
+ return translate("pluginAccounting.preview.bookCreated", {
5332
+ name,
5333
+ id: bookId
5334
+ });
5335
+ }
5336
+ function summariseFallback(json, translate) {
5337
+ const bookId = optionalString(json.bookId);
5338
+ if (bookId !== void 0) return translate("pluginAccounting.previewSummary", { bookId });
5339
+ return translate("pluginAccounting.previewGeneric");
5340
+ }
5341
+ /** Merge the two props a host might carry the payload on. `isRecord` rejects
5342
+ * arrays, which the old `typeof value === "object"` check spread into the
5343
+ * payload. */
5344
+ var asPayload = (value) => isRecord(value) ? value : {};
5345
+ function summarisePreview(data, jsonData, translate) {
5346
+ const json = {
5347
+ ...asPayload(data),
5348
+ ...asPayload(jsonData)
5349
+ };
5350
+ return summariseError(json, translate) ?? summariseEntry(json, translate) ?? summarisePl(json, translate) ?? summariseBs(json, translate) ?? summariseBook(json, translate) ?? summariseFallback(json, translate);
5351
+ }
5352
+ //#endregion
5262
5353
  //#region src/vue/Preview.vue?vue&type=script&setup=true&lang.ts
5263
5354
  var _hoisted_1 = {
5264
5355
  class: "text-sm text-gray-700",
@@ -5275,59 +5366,7 @@ var Preview_default = /* @__PURE__ */ defineComponent({
5275
5366
  setup(__props) {
5276
5367
  const { t } = useAccountingI18n();
5277
5368
  const props = __props;
5278
- function summariseError(json) {
5279
- const { error } = json;
5280
- if (typeof error !== "string") return null;
5281
- return t("pluginAccounting.previewError", { error });
5282
- }
5283
- function summariseEntry(json) {
5284
- const { entries } = json;
5285
- if (!Array.isArray(entries) || entries.length === 0) return null;
5286
- const [first] = entries;
5287
- if (!first?.id || !first?.date) return null;
5288
- return t("pluginAccounting.preview.entry", { date: first.date });
5289
- }
5290
- function summarisePl(json) {
5291
- const { profitLoss } = json;
5292
- if (!profitLoss || typeof profitLoss.netIncome !== "number") return null;
5293
- return t("pluginAccounting.preview.pl", {
5294
- from: profitLoss.from ?? "?",
5295
- to: profitLoss.to ?? "?",
5296
- net: formatAmountNumeric(profitLoss.netIncome)
5297
- });
5298
- }
5299
- function summariseBs(json) {
5300
- const { balanceSheet } = json;
5301
- if (!balanceSheet?.asOf || !balanceSheet.sections) return null;
5302
- const assets = balanceSheet.sections.find((section) => section.type === "asset");
5303
- return t("pluginAccounting.preview.bs", {
5304
- date: balanceSheet.asOf,
5305
- assets: assets ? formatAmountNumeric(assets.total ?? 0) : "?"
5306
- });
5307
- }
5308
- function summariseBook(json) {
5309
- const { book } = json;
5310
- if (!book?.id || !book?.name) return null;
5311
- return t("pluginAccounting.preview.bookCreated", {
5312
- name: book.name,
5313
- id: book.id
5314
- });
5315
- }
5316
- function summariseFallback(json) {
5317
- const { bookId } = json;
5318
- if (typeof bookId === "string") return t("pluginAccounting.previewSummary", { bookId });
5319
- return t("pluginAccounting.previewGeneric");
5320
- }
5321
- function asObject(value) {
5322
- return value && typeof value === "object" ? value : {};
5323
- }
5324
- const summary = computed(() => {
5325
- const json = {
5326
- ...asObject(props.data),
5327
- ...asObject(props.jsonData)
5328
- };
5329
- return summariseError(json) ?? summariseEntry(json) ?? summarisePl(json) ?? summariseBs(json) ?? summariseBook(json) ?? summariseFallback(json);
5330
- });
5369
+ const summary = computed(() => summarisePreview(props.data, props.jsonData, t));
5331
5370
  return (_ctx, _cache) => {
5332
5371
  return openBlock(), createElementBlock("div", _hoisted_1, [_cache[0] || (_cache[0] = createElementVNode("span", { class: "material-icons text-base align-middle mr-1" }, "account_balance", -1)), createElementVNode("span", null, toDisplayString(summary.value), 1)]);
5333
5372
  };