@things-factory/accounting 10.1.134 → 10.1.135

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.
Files changed (234) hide show
  1. package/dist-client/route.d.ts +1 -1
  2. package/dist-client/route.js +0 -12
  3. package/dist-client/route.js.map +1 -1
  4. package/dist-client/tsconfig.tsbuildinfo +1 -1
  5. package/dist-server/index.d.ts +0 -1
  6. package/dist-server/index.js +0 -1
  7. package/dist-server/index.js.map +1 -1
  8. package/dist-server/service/account/account-history.d.ts +13 -6
  9. package/dist-server/service/account/account-history.js +44 -17
  10. package/dist-server/service/account/account-history.js.map +1 -1
  11. package/dist-server/service/account/account-mutation.js +2 -2
  12. package/dist-server/service/account/account-mutation.js.map +1 -1
  13. package/dist-server/service/account/account-type.d.ts +16 -0
  14. package/dist-server/service/account/account-type.js +71 -13
  15. package/dist-server/service/account/account-type.js.map +1 -1
  16. package/dist-server/service/account/account.d.ts +9 -3
  17. package/dist-server/service/account/account.js +34 -8
  18. package/dist-server/service/account/account.js.map +1 -1
  19. package/dist-server/service/accounting-category/accounting-category-mutation.js +2 -2
  20. package/dist-server/service/accounting-category/accounting-category-mutation.js.map +1 -1
  21. package/dist-server/service/accounting-document/accounting-document-mutation.js +12 -3
  22. package/dist-server/service/accounting-document/accounting-document-mutation.js.map +1 -1
  23. package/dist-server/service/accounting-document/accounting-document-query.js +2 -0
  24. package/dist-server/service/accounting-document/accounting-document-query.js.map +1 -1
  25. package/dist-server/service/bank-account/bank-account-history.d.ts +11 -14
  26. package/dist-server/service/bank-account/bank-account-history.js +46 -59
  27. package/dist-server/service/bank-account/bank-account-history.js.map +1 -1
  28. package/dist-server/service/bank-account/bank-account-mutation.d.ts +1 -2
  29. package/dist-server/service/bank-account/bank-account-mutation.js +25 -69
  30. package/dist-server/service/bank-account/bank-account-mutation.js.map +1 -1
  31. package/dist-server/service/bank-account/bank-account-query.js +2 -0
  32. package/dist-server/service/bank-account/bank-account-query.js.map +1 -1
  33. package/dist-server/service/bank-account/bank-account-service.d.ts +5 -0
  34. package/dist-server/service/bank-account/bank-account-service.js +21 -0
  35. package/dist-server/service/bank-account/bank-account-service.js.map +1 -0
  36. package/dist-server/service/bank-account/bank-account-type.d.ts +13 -19
  37. package/dist-server/service/bank-account/bank-account-type.js +45 -69
  38. package/dist-server/service/bank-account/bank-account-type.js.map +1 -1
  39. package/dist-server/service/bank-account/bank-account.d.ts +14 -17
  40. package/dist-server/service/bank-account/bank-account.js +45 -57
  41. package/dist-server/service/bank-account/bank-account.js.map +1 -1
  42. package/dist-server/service/bank-statement/bank-statement-query.d.ts +14 -0
  43. package/dist-server/service/bank-statement/bank-statement-query.js +92 -0
  44. package/dist-server/service/bank-statement/bank-statement-query.js.map +1 -0
  45. package/dist-server/service/bank-statement/bank-statement.d.ts +26 -0
  46. package/dist-server/service/bank-statement/bank-statement.js +109 -0
  47. package/dist-server/service/bank-statement/bank-statement.js.map +1 -0
  48. package/dist-server/service/bank-statement/index.d.ts +5 -0
  49. package/dist-server/service/bank-statement/index.js +9 -0
  50. package/dist-server/service/bank-statement/index.js.map +1 -0
  51. package/dist-server/service/cash-flow-type.d.ts +5 -0
  52. package/dist-server/service/cash-flow-type.js +15 -0
  53. package/dist-server/service/cash-flow-type.js.map +1 -0
  54. package/dist-server/service/financial-institution/financial-institution-mutation.js +10 -1
  55. package/dist-server/service/financial-institution/financial-institution-mutation.js.map +1 -1
  56. package/dist-server/service/financial-institution/financial-institution-query.js +14 -6
  57. package/dist-server/service/financial-institution/financial-institution-query.js.map +1 -1
  58. package/dist-server/service/financial-institution/index.d.ts +1 -1
  59. package/dist-server/service/financial-statement/financial-statement-history.d.ts +11 -9
  60. package/dist-server/service/financial-statement/financial-statement-history.js +47 -36
  61. package/dist-server/service/financial-statement/financial-statement-history.js.map +1 -1
  62. package/dist-server/service/financial-statement/financial-statement-line.d.ts +24 -0
  63. package/dist-server/service/financial-statement/financial-statement-line.js +108 -0
  64. package/dist-server/service/financial-statement/financial-statement-line.js.map +1 -0
  65. package/dist-server/service/financial-statement/financial-statement-mutation.d.ts +1 -8
  66. package/dist-server/service/financial-statement/financial-statement-mutation.js +10 -135
  67. package/dist-server/service/financial-statement/financial-statement-mutation.js.map +1 -1
  68. package/dist-server/service/financial-statement/financial-statement-query.d.ts +8 -7
  69. package/dist-server/service/financial-statement/financial-statement-query.js +40 -30
  70. package/dist-server/service/financial-statement/financial-statement-query.js.map +1 -1
  71. package/dist-server/service/financial-statement/financial-statement-service.d.ts +33 -0
  72. package/dist-server/service/financial-statement/financial-statement-service.js +44 -0
  73. package/dist-server/service/financial-statement/financial-statement-service.js.map +1 -0
  74. package/dist-server/service/financial-statement/financial-statement.d.ts +19 -11
  75. package/dist-server/service/financial-statement/financial-statement.js +73 -65
  76. package/dist-server/service/financial-statement/financial-statement.js.map +1 -1
  77. package/dist-server/service/financial-statement/index.d.ts +3 -2
  78. package/dist-server/service/financial-statement/index.js +2 -2
  79. package/dist-server/service/financial-statement/index.js.map +1 -1
  80. package/dist-server/service/index.d.ts +15 -3
  81. package/dist-server/service/index.js +30 -13
  82. package/dist-server/service/index.js.map +1 -1
  83. package/dist-server/service/payment/index.d.ts +1 -0
  84. package/dist-server/service/payment/index.js +1 -0
  85. package/dist-server/service/payment/index.js.map +1 -1
  86. package/dist-server/service/payment/payment-history.d.ts +9 -16
  87. package/dist-server/service/payment/payment-history.js +36 -70
  88. package/dist-server/service/payment/payment-history.js.map +1 -1
  89. package/dist-server/service/payment/payment-mutation.d.ts +0 -1
  90. package/dist-server/service/payment/payment-mutation.js +14 -79
  91. package/dist-server/service/payment/payment-mutation.js.map +1 -1
  92. package/dist-server/service/payment/payment-query.d.ts +3 -0
  93. package/dist-server/service/payment/payment-query.js +30 -1
  94. package/dist-server/service/payment/payment-query.js.map +1 -1
  95. package/dist-server/service/payment/payment-service.d.ts +16 -0
  96. package/dist-server/service/payment/payment-service.js +140 -0
  97. package/dist-server/service/payment/payment-service.js.map +1 -0
  98. package/dist-server/service/payment/payment-targets.d.ts +31 -0
  99. package/dist-server/service/payment/payment-targets.js +19 -0
  100. package/dist-server/service/payment/payment-targets.js.map +1 -0
  101. package/dist-server/service/payment/payment-type.d.ts +13 -17
  102. package/dist-server/service/payment/payment-type.js +35 -51
  103. package/dist-server/service/payment/payment-type.js.map +1 -1
  104. package/dist-server/service/payment/payment.d.ts +23 -22
  105. package/dist-server/service/payment/payment.js +66 -94
  106. package/dist-server/service/payment/payment.js.map +1 -1
  107. package/dist-server/service/payment/transfer-target.d.ts +1 -0
  108. package/dist-server/service/payment/transfer-target.js +43 -0
  109. package/dist-server/service/payment/transfer-target.js.map +1 -0
  110. package/dist-server/service/recurring-cash-item/index.d.ts +6 -0
  111. package/dist-server/service/recurring-cash-item/index.js +10 -0
  112. package/dist-server/service/recurring-cash-item/index.js.map +1 -0
  113. package/dist-server/service/recurring-cash-item/recurring-cash-item-mutation.d.ts +7 -0
  114. package/dist-server/service/recurring-cash-item/recurring-cash-item-mutation.js +63 -0
  115. package/dist-server/service/recurring-cash-item/recurring-cash-item-mutation.js.map +1 -0
  116. package/dist-server/service/recurring-cash-item/recurring-cash-item-query.d.ts +15 -0
  117. package/dist-server/service/recurring-cash-item/recurring-cash-item-query.js +101 -0
  118. package/dist-server/service/recurring-cash-item/recurring-cash-item-query.js.map +1 -0
  119. package/dist-server/service/recurring-cash-item/recurring-cash-item-service.d.ts +23 -0
  120. package/dist-server/service/recurring-cash-item/recurring-cash-item-service.js +91 -0
  121. package/dist-server/service/recurring-cash-item/recurring-cash-item-service.js.map +1 -0
  122. package/dist-server/service/recurring-cash-item/recurring-cash-item-type.d.ts +23 -0
  123. package/dist-server/service/recurring-cash-item/recurring-cash-item-type.js +85 -0
  124. package/dist-server/service/recurring-cash-item/recurring-cash-item-type.js.map +1 -0
  125. package/dist-server/service/recurring-cash-item/recurring-cash-item.d.ts +35 -0
  126. package/dist-server/service/recurring-cash-item/recurring-cash-item.js +142 -0
  127. package/dist-server/service/recurring-cash-item/recurring-cash-item.js.map +1 -0
  128. package/dist-server/service/recurring-cash-item/recurring-schedule.d.ts +36 -0
  129. package/dist-server/service/recurring-cash-item/recurring-schedule.js +41 -0
  130. package/dist-server/service/recurring-cash-item/recurring-schedule.js.map +1 -0
  131. package/dist-server/service/transaction/transaction-history.d.ts +42 -15
  132. package/dist-server/service/transaction/transaction-history.js +160 -54
  133. package/dist-server/service/transaction/transaction-history.js.map +1 -1
  134. package/dist-server/service/transaction/transaction-mutation.d.ts +0 -1
  135. package/dist-server/service/transaction/transaction-mutation.js +13 -78
  136. package/dist-server/service/transaction/transaction-mutation.js.map +1 -1
  137. package/dist-server/service/transaction/transaction-period.d.ts +16 -0
  138. package/dist-server/service/transaction/transaction-period.js +49 -0
  139. package/dist-server/service/transaction/transaction-period.js.map +1 -0
  140. package/dist-server/service/transaction/transaction-query.d.ts +12 -0
  141. package/dist-server/service/transaction/transaction-query.js +84 -2
  142. package/dist-server/service/transaction/transaction-query.js.map +1 -1
  143. package/dist-server/service/transaction/transaction-service.d.ts +30 -0
  144. package/dist-server/service/transaction/transaction-service.js +130 -0
  145. package/dist-server/service/transaction/transaction-service.js.map +1 -0
  146. package/dist-server/service/transaction/transaction-type.d.ts +39 -7
  147. package/dist-server/service/transaction/transaction-type.js +145 -23
  148. package/dist-server/service/transaction/transaction-type.js.map +1 -1
  149. package/dist-server/service/transaction/transaction.d.ts +58 -31
  150. package/dist-server/service/transaction/transaction.js +216 -102
  151. package/dist-server/service/transaction/transaction.js.map +1 -1
  152. package/dist-server/tsconfig.tsbuildinfo +1 -1
  153. package/package.json +5 -3
  154. package/things-factory.config.js +0 -4
  155. package/translations/en.json +34 -2
  156. package/translations/ja.json +0 -1
  157. package/translations/ko.json +34 -2
  158. package/translations/ms.json +0 -1
  159. package/translations/zh.json +0 -1
  160. package/dist-client/pages/account/account-importer.d.ts +0 -22
  161. package/dist-client/pages/account/account-importer.js +0 -99
  162. package/dist-client/pages/account/account-importer.js.map +0 -1
  163. package/dist-client/pages/account/account-list-page.d.ts +0 -57
  164. package/dist-client/pages/account/account-list-page.js +0 -306
  165. package/dist-client/pages/account/account-list-page.js.map +0 -1
  166. package/dist-client/pages/bank-account/bank-account-importer.d.ts +0 -23
  167. package/dist-client/pages/bank-account/bank-account-importer.js +0 -92
  168. package/dist-client/pages/bank-account/bank-account-importer.js.map +0 -1
  169. package/dist-client/pages/bank-account/bank-account-list-page.d.ts +0 -60
  170. package/dist-client/pages/bank-account/bank-account-list-page.js +0 -317
  171. package/dist-client/pages/bank-account/bank-account-list-page.js.map +0 -1
  172. package/dist-client/pages/financial-statement/financial-statement-importer.d.ts +0 -22
  173. package/dist-client/pages/financial-statement/financial-statement-importer.js +0 -99
  174. package/dist-client/pages/financial-statement/financial-statement-importer.js.map +0 -1
  175. package/dist-client/pages/financial-statement/financial-statement-list-page.d.ts +0 -57
  176. package/dist-client/pages/financial-statement/financial-statement-list-page.js +0 -280
  177. package/dist-client/pages/financial-statement/financial-statement-list-page.js.map +0 -1
  178. package/dist-client/pages/income-statement/income-statement-importer.d.ts +0 -22
  179. package/dist-client/pages/income-statement/income-statement-importer.js +0 -99
  180. package/dist-client/pages/income-statement/income-statement-importer.js.map +0 -1
  181. package/dist-client/pages/income-statement/income-statement-list-page.d.ts +0 -57
  182. package/dist-client/pages/income-statement/income-statement-list-page.js +0 -280
  183. package/dist-client/pages/income-statement/income-statement-list-page.js.map +0 -1
  184. package/dist-client/pages/payment/payment-importer.d.ts +0 -23
  185. package/dist-client/pages/payment/payment-importer.js +0 -92
  186. package/dist-client/pages/payment/payment-importer.js.map +0 -1
  187. package/dist-client/pages/payment/payment-list-page.d.ts +0 -60
  188. package/dist-client/pages/payment/payment-list-page.js +0 -317
  189. package/dist-client/pages/payment/payment-list-page.js.map +0 -1
  190. package/dist-client/pages/transaction/transaction-importer.d.ts +0 -22
  191. package/dist-client/pages/transaction/transaction-importer.js +0 -99
  192. package/dist-client/pages/transaction/transaction-importer.js.map +0 -1
  193. package/dist-client/pages/transaction/transaction-list-page.d.ts +0 -57
  194. package/dist-client/pages/transaction/transaction-list-page.js +0 -280
  195. package/dist-client/pages/transaction/transaction-list-page.js.map +0 -1
  196. package/dist-server/controllers/index.d.ts +0 -1
  197. package/dist-server/controllers/index.js +0 -5
  198. package/dist-server/controllers/index.js.map +0 -1
  199. package/dist-server/controllers/summary-statements.d.ts +0 -4
  200. package/dist-server/controllers/summary-statements.js +0 -149
  201. package/dist-server/controllers/summary-statements.js.map +0 -1
  202. package/dist-server/migrations/1725201567284-seed-country-codes.d.ts +0 -5
  203. package/dist-server/migrations/1725201567284-seed-country-codes.js +0 -255
  204. package/dist-server/migrations/1725201567284-seed-country-codes.js.map +0 -1
  205. package/dist-server/service/financial-statement/financial-statement-line-item.d.ts +0 -19
  206. package/dist-server/service/financial-statement/financial-statement-line-item.js +0 -95
  207. package/dist-server/service/financial-statement/financial-statement-line-item.js.map +0 -1
  208. package/dist-server/service/financial-statement/financial-statement-type.d.ts +0 -20
  209. package/dist-server/service/financial-statement/financial-statement-type.js +0 -77
  210. package/dist-server/service/financial-statement/financial-statement-type.js.map +0 -1
  211. package/dist-server/service/income-statement/event-subscriber.d.ts +0 -7
  212. package/dist-server/service/income-statement/event-subscriber.js +0 -21
  213. package/dist-server/service/income-statement/event-subscriber.js.map +0 -1
  214. package/dist-server/service/income-statement/income-statement-history.d.ts +0 -28
  215. package/dist-server/service/income-statement/income-statement-history.js +0 -146
  216. package/dist-server/service/income-statement/income-statement-history.js.map +0 -1
  217. package/dist-server/service/income-statement/income-statement-line-item.d.ts +0 -19
  218. package/dist-server/service/income-statement/income-statement-line-item.js +0 -97
  219. package/dist-server/service/income-statement/income-statement-line-item.js.map +0 -1
  220. package/dist-server/service/income-statement/income-statement-mutation.d.ts +0 -10
  221. package/dist-server/service/income-statement/income-statement-mutation.js +0 -159
  222. package/dist-server/service/income-statement/income-statement-mutation.js.map +0 -1
  223. package/dist-server/service/income-statement/income-statement-query.d.ts +0 -11
  224. package/dist-server/service/income-statement/income-statement-query.js +0 -81
  225. package/dist-server/service/income-statement/income-statement-query.js.map +0 -1
  226. package/dist-server/service/income-statement/income-statement-type.d.ts +0 -20
  227. package/dist-server/service/income-statement/income-statement-type.js +0 -77
  228. package/dist-server/service/income-statement/income-statement-type.js.map +0 -1
  229. package/dist-server/service/income-statement/income-statement.d.ts +0 -28
  230. package/dist-server/service/income-statement/income-statement.js +0 -137
  231. package/dist-server/service/income-statement/income-statement.js.map +0 -1
  232. package/dist-server/service/income-statement/index.d.ts +0 -8
  233. package/dist-server/service/income-statement/index.js +0 -13
  234. package/dist-server/service/income-statement/index.js.map +0 -1
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.saveRecurringCashItems = saveRecurringCashItems;
4
+ exports.makeForecasts = makeForecasts;
5
+ const typeorm_1 = require("typeorm");
6
+ const shell_1 = require("@things-factory/shell");
7
+ const transaction_1 = require("../transaction/transaction");
8
+ const transaction_service_1 = require("../transaction/transaction-service");
9
+ const recurring_cash_item_1 = require("./recurring-cash-item");
10
+ const recurring_schedule_1 = require("./recurring-schedule");
11
+ const MONTH = /^\d{4}-(0[1-9]|1[0-2])$/;
12
+ function rowOf(input, current) {
13
+ const { id, cuFlag, ...row } = input;
14
+ const merged = { ...current, ...row };
15
+ if (!String(merged.name ?? '').trim())
16
+ throw new shell_1.Refusal('recurring-name-required', {}, 'name: what it is');
17
+ if (!merged.type)
18
+ throw new shell_1.Refusal('transaction-type-required', {}, 'type: money in or money out');
19
+ if (!MONTH.test(String(merged.startMonth ?? '')))
20
+ throw new shell_1.Refusal('recurring-start-required', {}, 'startMonth: YYYY-MM');
21
+ if (merged.endMonth && !MONTH.test(merged.endMonth))
22
+ throw new shell_1.Refusal('recurring-end-not-a-month', {}, 'endMonth: YYYY-MM');
23
+ if (merged.endMonth && merged.endMonth < merged.startMonth)
24
+ throw new shell_1.Refusal('recurring-end-before-start', {}, 'endMonth: before startMonth');
25
+ if (merged.dayOfMonth !== null &&
26
+ merged.dayOfMonth !== undefined &&
27
+ !(merged.dayOfMonth >= 1 && merged.dayOfMonth <= 31)) {
28
+ throw new shell_1.Refusal('day-of-month-out-of-range', {}, 'dayOfMonth: must be 1 to 31');
29
+ }
30
+ if (!current && (row.amount === undefined || row.amount === null))
31
+ throw new shell_1.Refusal('recurring-amount-required', {}, 'amount: every month');
32
+ return row;
33
+ }
34
+ /** Apply rows to a domain's recurring items: `+` (or no id) adds, `M` changes, `-` deletes (softly). */
35
+ async function saveRecurringCashItems(tx, domain, user, inputs) {
36
+ const repo = tx.getRepository(recurring_cash_item_1.RecurringCashItem);
37
+ const deletes = [...new Set(inputs.filter(one => one.cuFlag === '-' && one.id).map(one => one.id))];
38
+ if (deletes.length) {
39
+ const found = await repo.find({ where: { domain: { id: domain.id }, id: (0, typeorm_1.In)(deletes) } });
40
+ if (found.length !== deletes.length)
41
+ throw new shell_1.Refusal('recurring-not-found', {}, 'a recurring item was not found - reload and try again');
42
+ await repo.softRemove(found);
43
+ }
44
+ const saved = [];
45
+ for (const input of inputs.filter(one => one.cuFlag !== '-')) {
46
+ const isNew = !input.id || input.cuFlag === '+';
47
+ const current = isNew ? undefined : await repo.findOne({ where: { domain: { id: domain.id }, id: input.id } });
48
+ if (!isNew && !current)
49
+ throw new shell_1.Refusal('recurring-not-found', {}, 'a recurring item was not found - reload and try again');
50
+ saved.push(await repo.save({
51
+ ...(current ?? { domain, creator: user }),
52
+ ...rowOf(input, current),
53
+ updater: user
54
+ }));
55
+ }
56
+ return saved;
57
+ }
58
+ /**
59
+ * Make the month's forecasts from the recurring items. A forecast already made from an item for that month is not
60
+ * made again, so running it twice changes nothing. Returns how many were made.
61
+ */
62
+ async function makeForecasts(tx, domain, user, year, month) {
63
+ if (!(month >= 1 && month <= 12))
64
+ throw new shell_1.Refusal('month-out-of-range', { month }, 'month: must be 1 to 12');
65
+ const items = await tx.getRepository(recurring_cash_item_1.RecurringCashItem).find({ where: { domain: { id: domain.id } } });
66
+ const made = await tx
67
+ .getRepository(transaction_1.Transaction)
68
+ .find({
69
+ where: { domain: { id: domain.id }, category: transaction_1.TransactionCategory.FORECAST, year, month },
70
+ relations: ['recurringItem']
71
+ });
72
+ const already = new Set(made.map(one => one.recurringItem?.id).filter(Boolean));
73
+ const lines = (0, recurring_schedule_1.linesFor)(items, year, month, already);
74
+ await (0, transaction_service_1.saveTransactions)(tx, domain, user, lines.map(line => {
75
+ return {
76
+ cuFlag: '+',
77
+ category: transaction_1.TransactionCategory.FORECAST,
78
+ type: line.type,
79
+ year: line.year,
80
+ month: line.month,
81
+ description: line.name,
82
+ amount: line.amount,
83
+ currency: line.currency,
84
+ timing: line.timing ?? undefined,
85
+ status: transaction_1.ForecastStatus.PLANNED,
86
+ recurringItem: { id: line.recurringItemId }
87
+ };
88
+ }));
89
+ return lines.length;
90
+ }
91
+ //# sourceMappingURL=recurring-cash-item-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recurring-cash-item-service.js","sourceRoot":"","sources":["../../../server/service/recurring-cash-item/recurring-cash-item-service.ts"],"names":[],"mappings":";;AA0CA,wDA8BC;AAMD,sCAyCC;AAvHD,qCAA2C;AAE3C,iDAA+C;AAE/C,4DAA6F;AAC7F,4EAAqE;AACrE,+DAAyD;AACzD,6DAA+C;AAE/C,MAAM,KAAK,GAAG,yBAAyB,CAAA;AASvC,SAAS,KAAK,CAAC,KAA6B,EAAE,OAAsC;IAClF,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,GAAG,EAAE,GAAG,KAA4B,CAAA;IAC3D,MAAM,MAAM,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,GAAG,EAAE,CAAA;IACrC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;QAAE,MAAM,IAAI,eAAO,CAAC,yBAAyB,EAAE,EAAE,EAAE,kBAAkB,CAAC,CAAA;IAC3G,IAAI,CAAC,MAAM,CAAC,IAAI;QAAE,MAAM,IAAI,eAAO,CAAC,2BAA2B,EAAE,EAAE,EAAE,6BAA6B,CAAC,CAAA;IACnG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;QAC9C,MAAM,IAAI,eAAO,CAAC,0BAA0B,EAAE,EAAE,EAAE,qBAAqB,CAAC,CAAA;IAC1E,IAAI,MAAM,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;QACjD,MAAM,IAAI,eAAO,CAAC,2BAA2B,EAAE,EAAE,EAAE,mBAAmB,CAAC,CAAA;IACzE,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC,UAAU;QACxD,MAAM,IAAI,eAAO,CAAC,4BAA4B,EAAE,EAAE,EAAE,6BAA6B,CAAC,CAAA;IACpF,IACE,MAAM,CAAC,UAAU,KAAK,IAAI;QAC1B,MAAM,CAAC,UAAU,KAAK,SAAS;QAC/B,CAAC,CAAC,MAAM,CAAC,UAAU,IAAI,CAAC,IAAI,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,EACpD,CAAC;QACD,MAAM,IAAI,eAAO,CAAC,2BAA2B,EAAE,EAAE,EAAE,6BAA6B,CAAC,CAAA;IACnF,CAAC;IACD,IAAI,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC;QAC/D,MAAM,IAAI,eAAO,CAAC,2BAA2B,EAAE,EAAE,EAAE,qBAAqB,CAAC,CAAA;IAC3E,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,wGAAwG;AACjG,KAAK,UAAU,sBAAsB,CAC1C,EAAiB,EACjB,MAAsB,EACtB,IAAS,EACT,MAAgC;IAEhC,MAAM,IAAI,GAAG,EAAE,CAAC,aAAa,CAAC,uCAAiB,CAAC,CAAA;IAChD,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAG,CAAC,CAAC,CAAC,CAAA;IACpG,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,IAAA,YAAE,EAAC,OAAO,CAAC,EAAE,EAAE,CAAC,CAAA;QACxF,IAAI,KAAK,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM;YACjC,MAAM,IAAI,eAAO,CAAC,qBAAqB,EAAE,EAAE,EAAE,uDAAuD,CAAC,CAAA;QACvG,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;IAC9B,CAAC;IAED,MAAM,KAAK,GAAwB,EAAE,CAAA;IACrC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,EAAE,CAAC;QAC7D,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,EAAE,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,CAAA;QAC/C,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;QAC9G,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO;YACpB,MAAM,IAAI,eAAO,CAAC,qBAAqB,EAAE,EAAE,EAAE,uDAAuD,CAAC,CAAA;QACvG,KAAK,CAAC,IAAI,CACR,MAAM,IAAI,CAAC,IAAI,CAAC;YACd,GAAG,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YACzC,GAAG,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC;YACxB,OAAO,EAAE,IAAI;SACO,CAAC,CACxB,CAAA;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;GAGG;AACI,KAAK,UAAU,aAAa,CACjC,EAAiB,EACjB,MAAsB,EACtB,IAAS,EACT,IAAY,EACZ,KAAa;IAEb,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;QAAE,MAAM,IAAI,eAAO,CAAC,oBAAoB,EAAE,EAAE,KAAK,EAAE,EAAE,wBAAwB,CAAC,CAAA;IAE9G,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,uCAAiB,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;IACtG,MAAM,IAAI,GAAG,MAAM,EAAE;SAClB,aAAa,CAAC,yBAAW,CAAC;SAC1B,IAAI,CAAC;QACJ,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,iCAAmB,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE;QACzF,SAAS,EAAE,CAAC,eAAe,CAAC;KAC7B,CAAC,CAAA;IACJ,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAa,CAAC,CAAA;IAE3F,MAAM,KAAK,GAAG,IAAA,6BAAQ,EAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAA;IACnD,MAAM,IAAA,sCAAgB,EACpB,EAAE,EACF,MAAM,EACN,IAAI,EACJ,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;QACf,OAAO;YACL,MAAM,EAAE,GAAG;YACX,QAAQ,EAAE,iCAAmB,CAAC,QAAQ;YACtC,IAAI,EAAE,IAAI,CAAC,IAAW;YACtB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,WAAW,EAAE,IAAI,CAAC,IAAI;YACtB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,SAAS;YAChC,MAAM,EAAE,4BAAc,CAAC,OAAO;YAC9B,aAAa,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,eAAe,EAAE;SAC5C,CAAA;IACH,CAAC,CAAC,CACH,CAAA;IAED,OAAO,KAAK,CAAC,MAAM,CAAA;AACrB,CAAC","sourcesContent":["import { EntityManager, In } from 'typeorm'\n\nimport { Refusal } from '@things-factory/shell'\n\nimport { ForecastStatus, Transaction, TransactionCategory } from '../transaction/transaction'\nimport { saveTransactions } from '../transaction/transaction-service'\nimport { RecurringCashItem } from './recurring-cash-item'\nimport { linesFor } from './recurring-schedule'\n\nconst MONTH = /^\\d{4}-(0[1-9]|1[0-2])$/\n\nexport type RecurringCashItemInput = Partial<Omit<RecurringCashItem, 'account' | 'counterparty'>> & {\n id?: string\n cuFlag?: string\n account?: { id: string } | null\n counterparty?: { id: string } | null\n}\n\nfunction rowOf(input: RecurringCashItemInput, current: RecurringCashItem | undefined): Record<string, any> {\n const { id, cuFlag, ...row } = input as Record<string, any>\n const merged = { ...current, ...row }\n if (!String(merged.name ?? '').trim()) throw new Refusal('recurring-name-required', {}, 'name: what it is')\n if (!merged.type) throw new Refusal('transaction-type-required', {}, 'type: money in or money out')\n if (!MONTH.test(String(merged.startMonth ?? '')))\n throw new Refusal('recurring-start-required', {}, 'startMonth: YYYY-MM')\n if (merged.endMonth && !MONTH.test(merged.endMonth))\n throw new Refusal('recurring-end-not-a-month', {}, 'endMonth: YYYY-MM')\n if (merged.endMonth && merged.endMonth < merged.startMonth)\n throw new Refusal('recurring-end-before-start', {}, 'endMonth: before startMonth')\n if (\n merged.dayOfMonth !== null &&\n merged.dayOfMonth !== undefined &&\n !(merged.dayOfMonth >= 1 && merged.dayOfMonth <= 31)\n ) {\n throw new Refusal('day-of-month-out-of-range', {}, 'dayOfMonth: must be 1 to 31')\n }\n if (!current && (row.amount === undefined || row.amount === null))\n throw new Refusal('recurring-amount-required', {}, 'amount: every month')\n return row\n}\n\n/** Apply rows to a domain's recurring items: `+` (or no id) adds, `M` changes, `-` deletes (softly). */\nexport async function saveRecurringCashItems(\n tx: EntityManager,\n domain: { id: string },\n user: any,\n inputs: RecurringCashItemInput[]\n): Promise<RecurringCashItem[]> {\n const repo = tx.getRepository(RecurringCashItem)\n const deletes = [...new Set(inputs.filter(one => one.cuFlag === '-' && one.id).map(one => one.id!))]\n if (deletes.length) {\n const found = await repo.find({ where: { domain: { id: domain.id }, id: In(deletes) } })\n if (found.length !== deletes.length)\n throw new Refusal('recurring-not-found', {}, 'a recurring item was not found - reload and try again')\n await repo.softRemove(found)\n }\n\n const saved: RecurringCashItem[] = []\n for (const input of inputs.filter(one => one.cuFlag !== '-')) {\n const isNew = !input.id || input.cuFlag === '+'\n const current = isNew ? undefined : await repo.findOne({ where: { domain: { id: domain.id }, id: input.id } })\n if (!isNew && !current)\n throw new Refusal('recurring-not-found', {}, 'a recurring item was not found - reload and try again')\n saved.push(\n await repo.save({\n ...(current ?? { domain, creator: user }),\n ...rowOf(input, current),\n updater: user\n } as RecurringCashItem)\n )\n }\n return saved\n}\n\n/**\n * Make the month's forecasts from the recurring items. A forecast already made from an item for that month is not\n * made again, so running it twice changes nothing. Returns how many were made.\n */\nexport async function makeForecasts(\n tx: EntityManager,\n domain: { id: string },\n user: any,\n year: number,\n month: number\n): Promise<number> {\n if (!(month >= 1 && month <= 12)) throw new Refusal('month-out-of-range', { month }, 'month: must be 1 to 12')\n\n const items = await tx.getRepository(RecurringCashItem).find({ where: { domain: { id: domain.id } } })\n const made = await tx\n .getRepository(Transaction)\n .find({\n where: { domain: { id: domain.id }, category: TransactionCategory.FORECAST, year, month },\n relations: ['recurringItem']\n })\n const already = new Set(made.map(one => one.recurringItem?.id).filter(Boolean) as string[])\n\n const lines = linesFor(items, year, month, already)\n await saveTransactions(\n tx,\n domain,\n user,\n lines.map(line => {\n return {\n cuFlag: '+',\n category: TransactionCategory.FORECAST,\n type: line.type as any,\n year: line.year,\n month: line.month,\n description: line.name,\n amount: line.amount,\n currency: line.currency,\n timing: line.timing ?? undefined,\n status: ForecastStatus.PLANNED,\n recurringItem: { id: line.recurringItemId }\n }\n })\n )\n\n return lines.length\n}\n"]}
@@ -0,0 +1,23 @@
1
+ import { ObjectRef } from '@things-factory/shell';
2
+ import { CashFlowType } from '../cash-flow-type';
3
+ import { RecurringCashItem } from './recurring-cash-item';
4
+ export declare class RecurringCashItemPatch {
5
+ id?: string;
6
+ name?: string;
7
+ account?: ObjectRef;
8
+ type?: CashFlowType;
9
+ amount?: number;
10
+ currency?: string;
11
+ dayOfMonth?: number;
12
+ lastDayOfMonth?: boolean;
13
+ startMonth?: string;
14
+ endMonth?: string;
15
+ counterparty?: ObjectRef;
16
+ active?: boolean;
17
+ notes?: string;
18
+ cuFlag?: string;
19
+ }
20
+ export declare class RecurringCashItemList {
21
+ items: RecurringCashItem[];
22
+ total: number;
23
+ }
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RecurringCashItemList = exports.RecurringCashItemPatch = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const type_graphql_1 = require("type-graphql");
6
+ const shell_1 = require("@things-factory/shell");
7
+ const cash_flow_type_1 = require("../cash-flow-type");
8
+ const recurring_cash_item_1 = require("./recurring-cash-item");
9
+ let RecurringCashItemPatch = class RecurringCashItemPatch {
10
+ };
11
+ exports.RecurringCashItemPatch = RecurringCashItemPatch;
12
+ tslib_1.__decorate([
13
+ (0, type_graphql_1.Field)(type => type_graphql_1.ID, { nullable: true, description: 'The item to change or delete' }),
14
+ tslib_1.__metadata("design:type", String)
15
+ ], RecurringCashItemPatch.prototype, "id", void 0);
16
+ tslib_1.__decorate([
17
+ (0, type_graphql_1.Field)({ nullable: true, description: 'What it is' }),
18
+ tslib_1.__metadata("design:type", String)
19
+ ], RecurringCashItemPatch.prototype, "name", void 0);
20
+ tslib_1.__decorate([
21
+ (0, type_graphql_1.Field)(type => shell_1.ObjectRef, { nullable: true, description: 'The account subject it is booked to' }),
22
+ tslib_1.__metadata("design:type", shell_1.ObjectRef)
23
+ ], RecurringCashItemPatch.prototype, "account", void 0);
24
+ tslib_1.__decorate([
25
+ (0, type_graphql_1.Field)(type => cash_flow_type_1.CashFlowType, { nullable: true, description: 'Money in or money out' }),
26
+ tslib_1.__metadata("design:type", String)
27
+ ], RecurringCashItemPatch.prototype, "type", void 0);
28
+ tslib_1.__decorate([
29
+ (0, type_graphql_1.Field)(type => type_graphql_1.Float, { nullable: true, description: 'Amount every month' }),
30
+ tslib_1.__metadata("design:type", Number)
31
+ ], RecurringCashItemPatch.prototype, "amount", void 0);
32
+ tslib_1.__decorate([
33
+ (0, type_graphql_1.Field)({ nullable: true, description: 'ISO 4217 code' }),
34
+ tslib_1.__metadata("design:type", String)
35
+ ], RecurringCashItemPatch.prototype, "currency", void 0);
36
+ tslib_1.__decorate([
37
+ (0, type_graphql_1.Field)(type => type_graphql_1.Int, { nullable: true, description: '1-31' }),
38
+ tslib_1.__metadata("design:type", Number)
39
+ ], RecurringCashItemPatch.prototype, "dayOfMonth", void 0);
40
+ tslib_1.__decorate([
41
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Falls on the last day of every month' }),
42
+ tslib_1.__metadata("design:type", Boolean)
43
+ ], RecurringCashItemPatch.prototype, "lastDayOfMonth", void 0);
44
+ tslib_1.__decorate([
45
+ (0, type_graphql_1.Field)({ nullable: true, description: 'First month - YYYY-MM' }),
46
+ tslib_1.__metadata("design:type", String)
47
+ ], RecurringCashItemPatch.prototype, "startMonth", void 0);
48
+ tslib_1.__decorate([
49
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Last month - YYYY-MM' }),
50
+ tslib_1.__metadata("design:type", String)
51
+ ], RecurringCashItemPatch.prototype, "endMonth", void 0);
52
+ tslib_1.__decorate([
53
+ (0, type_graphql_1.Field)(type => shell_1.ObjectRef, { nullable: true, description: 'Who it is paid to or received from' }),
54
+ tslib_1.__metadata("design:type", shell_1.ObjectRef)
55
+ ], RecurringCashItemPatch.prototype, "counterparty", void 0);
56
+ tslib_1.__decorate([
57
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Whether it still makes forecasts' }),
58
+ tslib_1.__metadata("design:type", Boolean)
59
+ ], RecurringCashItemPatch.prototype, "active", void 0);
60
+ tslib_1.__decorate([
61
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Notes' }),
62
+ tslib_1.__metadata("design:type", String)
63
+ ], RecurringCashItemPatch.prototype, "notes", void 0);
64
+ tslib_1.__decorate([
65
+ (0, type_graphql_1.Field)({ nullable: true, description: '+ adds, M changes, - deletes' }),
66
+ tslib_1.__metadata("design:type", String)
67
+ ], RecurringCashItemPatch.prototype, "cuFlag", void 0);
68
+ exports.RecurringCashItemPatch = RecurringCashItemPatch = tslib_1.__decorate([
69
+ (0, type_graphql_1.InputType)({ description: 'A recurring item, or a grid row: cuFlag + adds, M changes, - deletes' })
70
+ ], RecurringCashItemPatch);
71
+ let RecurringCashItemList = class RecurringCashItemList {
72
+ };
73
+ exports.RecurringCashItemList = RecurringCashItemList;
74
+ tslib_1.__decorate([
75
+ (0, type_graphql_1.Field)(type => [recurring_cash_item_1.RecurringCashItem], { description: 'The items on this page' }),
76
+ tslib_1.__metadata("design:type", Array)
77
+ ], RecurringCashItemList.prototype, "items", void 0);
78
+ tslib_1.__decorate([
79
+ (0, type_graphql_1.Field)(type => type_graphql_1.Int, { description: 'How many there are in all' }),
80
+ tslib_1.__metadata("design:type", Number)
81
+ ], RecurringCashItemList.prototype, "total", void 0);
82
+ exports.RecurringCashItemList = RecurringCashItemList = tslib_1.__decorate([
83
+ (0, type_graphql_1.ObjectType)({ description: 'A page of recurring items' })
84
+ ], RecurringCashItemList);
85
+ //# sourceMappingURL=recurring-cash-item-type.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recurring-cash-item-type.js","sourceRoot":"","sources":["../../../server/service/recurring-cash-item/recurring-cash-item-type.ts"],"names":[],"mappings":";;;;AAAA,+CAA2E;AAE3E,iDAAiD;AAEjD,sDAAgD;AAChD,+DAAyD;AAGlD,IAAM,sBAAsB,GAA5B,MAAM,sBAAsB;CA0ClC,CAAA;AA1CY,wDAAsB;AAEjC;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,8BAA8B,EAAE,CAAC;;kDACxE;AAGX;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC;;oDACxC;AAGb;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAS,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,qCAAqC,EAAE,CAAC;sCACvF,iBAAS;uDAAA;AAGnB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,6BAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,uBAAuB,EAAE,CAAC;;oDACnE;AAGnB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,oBAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,oBAAoB,EAAE,CAAC;;sDAC7D;AAGf;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC;;wDACvC;AAGjB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,kBAAG,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC;;0DACzC;AAGnB;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,sCAAsC,EAAE,CAAC;;8DACvD;AAGxB;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,uBAAuB,EAAE,CAAC;;0DAC7C;AAGnB;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,sBAAsB,EAAE,CAAC;;wDAC9C;AAGjB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAS,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,oCAAoC,EAAE,CAAC;sCACjF,iBAAS;4DAAA;AAGxB;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,kCAAkC,EAAE,CAAC;;sDAC3D;AAGhB;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;;qDAClC;AAGd;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,8BAA8B,EAAE,CAAC;;sDACxD;iCAzCJ,sBAAsB;IADlC,IAAA,wBAAS,EAAC,EAAE,WAAW,EAAE,sEAAsE,EAAE,CAAC;GACtF,sBAAsB,CA0ClC;AAGM,IAAM,qBAAqB,GAA3B,MAAM,qBAAqB;CAMjC,CAAA;AANY,sDAAqB;AAEhC;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,uCAAiB,CAAC,EAAE,EAAE,WAAW,EAAE,wBAAwB,EAAE,CAAC;;oDACpD;AAG1B;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,kBAAG,EAAE,EAAE,WAAW,EAAE,2BAA2B,EAAE,CAAC;;oDACpD;gCALF,qBAAqB;IADjC,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,2BAA2B,EAAE,CAAC;GAC5C,qBAAqB,CAMjC","sourcesContent":["import { ObjectType, Field, Float, InputType, Int, ID } from 'type-graphql'\n\nimport { ObjectRef } from '@things-factory/shell'\n\nimport { CashFlowType } from '../cash-flow-type'\nimport { RecurringCashItem } from './recurring-cash-item'\n\n@InputType({ description: 'A recurring item, or a grid row: cuFlag + adds, M changes, - deletes' })\nexport class RecurringCashItemPatch {\n @Field(type => ID, { nullable: true, description: 'The item to change or delete' })\n id?: string\n\n @Field({ nullable: true, description: 'What it is' })\n name?: string\n\n @Field(type => ObjectRef, { nullable: true, description: 'The account subject it is booked to' })\n account?: ObjectRef\n\n @Field(type => CashFlowType, { nullable: true, description: 'Money in or money out' })\n type?: CashFlowType\n\n @Field(type => Float, { nullable: true, description: 'Amount every month' })\n amount?: number\n\n @Field({ nullable: true, description: 'ISO 4217 code' })\n currency?: string\n\n @Field(type => Int, { nullable: true, description: '1-31' })\n dayOfMonth?: number\n\n @Field({ nullable: true, description: 'Falls on the last day of every month' })\n lastDayOfMonth?: boolean\n\n @Field({ nullable: true, description: 'First month - YYYY-MM' })\n startMonth?: string\n\n @Field({ nullable: true, description: 'Last month - YYYY-MM' })\n endMonth?: string\n\n @Field(type => ObjectRef, { nullable: true, description: 'Who it is paid to or received from' })\n counterparty?: ObjectRef\n\n @Field({ nullable: true, description: 'Whether it still makes forecasts' })\n active?: boolean\n\n @Field({ nullable: true, description: 'Notes' })\n notes?: string\n\n @Field({ nullable: true, description: '+ adds, M changes, - deletes' })\n cuFlag?: string\n}\n\n@ObjectType({ description: 'A page of recurring items' })\nexport class RecurringCashItemList {\n @Field(type => [RecurringCashItem], { description: 'The items on this page' })\n items: RecurringCashItem[]\n\n @Field(type => Int, { description: 'How many there are in all' })\n total: number\n}\n"]}
@@ -0,0 +1,35 @@
1
+ import { Domain } from '@things-factory/shell';
2
+ import { User } from '@things-factory/auth-base';
3
+ import { Counterparty } from '@things-factory/biz-base';
4
+ import { Account } from '../account/account';
5
+ import { CashFlowType } from '../cash-flow-type';
6
+ /**
7
+ * Money that comes in or goes out every month on a known day - rent, a subscription, a loan's interest. Each month it
8
+ * falls in, it makes a forecast (§`Transaction.recurringItem`).
9
+ */
10
+ export declare class RecurringCashItem {
11
+ readonly id: string;
12
+ domain?: Domain;
13
+ domainId?: string;
14
+ name: string;
15
+ account?: Account;
16
+ accountId?: string;
17
+ type: CashFlowType;
18
+ amount: number;
19
+ currency: string;
20
+ dayOfMonth?: number;
21
+ lastDayOfMonth: boolean;
22
+ startMonth: string;
23
+ endMonth?: string;
24
+ counterparty?: Counterparty;
25
+ counterpartyId?: string;
26
+ active: boolean;
27
+ notes?: string;
28
+ createdAt?: Date;
29
+ updatedAt?: Date;
30
+ deletedAt?: Date;
31
+ creator?: User;
32
+ creatorId?: string;
33
+ updater?: User;
34
+ updaterId?: string;
35
+ }
@@ -0,0 +1,142 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RecurringCashItem = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const typeorm_1 = require("typeorm");
6
+ const type_graphql_1 = require("type-graphql");
7
+ const shell_1 = require("@things-factory/shell");
8
+ const auth_base_1 = require("@things-factory/auth-base");
9
+ const biz_base_1 = require("@things-factory/biz-base");
10
+ const account_1 = require("../account/account");
11
+ const cash_flow_type_1 = require("../cash-flow-type");
12
+ /**
13
+ * Money that comes in or goes out every month on a known day - rent, a subscription, a loan's interest. Each month it
14
+ * falls in, it makes a forecast (§`Transaction.recurringItem`).
15
+ */
16
+ let RecurringCashItem = class RecurringCashItem {
17
+ };
18
+ exports.RecurringCashItem = RecurringCashItem;
19
+ tslib_1.__decorate([
20
+ (0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
21
+ (0, type_graphql_1.Field)(type => type_graphql_1.ID, { description: 'Unique identifier' }),
22
+ tslib_1.__metadata("design:type", String)
23
+ ], RecurringCashItem.prototype, "id", void 0);
24
+ tslib_1.__decorate([
25
+ (0, typeorm_1.ManyToOne)(type => shell_1.Domain),
26
+ (0, type_graphql_1.Field)(type => shell_1.Domain, { nullable: true, description: 'The domain whose item it is' }),
27
+ tslib_1.__metadata("design:type", shell_1.Domain)
28
+ ], RecurringCashItem.prototype, "domain", void 0);
29
+ tslib_1.__decorate([
30
+ (0, typeorm_1.RelationId)((item) => item.domain),
31
+ tslib_1.__metadata("design:type", String)
32
+ ], RecurringCashItem.prototype, "domainId", void 0);
33
+ tslib_1.__decorate([
34
+ (0, typeorm_1.Column)(),
35
+ (0, type_graphql_1.Field)({ description: 'What it is - the forecasts it makes take this as their description' }),
36
+ tslib_1.__metadata("design:type", String)
37
+ ], RecurringCashItem.prototype, "name", void 0);
38
+ tslib_1.__decorate([
39
+ (0, typeorm_1.ManyToOne)(type => account_1.Account, { nullable: true, onDelete: 'SET NULL' }),
40
+ (0, type_graphql_1.Field)(type => account_1.Account, { nullable: true, description: 'The account subject it is booked to' }),
41
+ tslib_1.__metadata("design:type", account_1.Account)
42
+ ], RecurringCashItem.prototype, "account", void 0);
43
+ tslib_1.__decorate([
44
+ (0, typeorm_1.RelationId)((item) => item.account),
45
+ tslib_1.__metadata("design:type", String)
46
+ ], RecurringCashItem.prototype, "accountId", void 0);
47
+ tslib_1.__decorate([
48
+ (0, typeorm_1.Column)({ default: cash_flow_type_1.CashFlowType.EXPENSE }),
49
+ (0, type_graphql_1.Field)(type => cash_flow_type_1.CashFlowType, { description: 'Money in or money out' }),
50
+ tslib_1.__metadata("design:type", String)
51
+ ], RecurringCashItem.prototype, "type", void 0);
52
+ tslib_1.__decorate([
53
+ (0, typeorm_1.Column)((0, shell_1.moneyColumn)()),
54
+ (0, type_graphql_1.Field)(type => type_graphql_1.Float, { description: 'Amount every month' }),
55
+ tslib_1.__metadata("design:type", Number)
56
+ ], RecurringCashItem.prototype, "amount", void 0);
57
+ tslib_1.__decorate([
58
+ (0, typeorm_1.Column)({ default: 'KRW' }),
59
+ (0, type_graphql_1.Field)({ description: 'ISO 4217 code' }),
60
+ tslib_1.__metadata("design:type", String)
61
+ ], RecurringCashItem.prototype, "currency", void 0);
62
+ tslib_1.__decorate([
63
+ (0, typeorm_1.Column)({ type: 'int', nullable: true }),
64
+ (0, type_graphql_1.Field)(type => type_graphql_1.Int, {
65
+ nullable: true,
66
+ description: "1-31; a day past the month's end is its last day. Empty with lastDayOfMonth"
67
+ }),
68
+ tslib_1.__metadata("design:type", Number)
69
+ ], RecurringCashItem.prototype, "dayOfMonth", void 0);
70
+ tslib_1.__decorate([
71
+ (0, typeorm_1.Column)({ default: false }),
72
+ (0, type_graphql_1.Field)({ description: 'Falls on the last day of every month' }),
73
+ tslib_1.__metadata("design:type", Boolean)
74
+ ], RecurringCashItem.prototype, "lastDayOfMonth", void 0);
75
+ tslib_1.__decorate([
76
+ (0, typeorm_1.Column)(),
77
+ (0, type_graphql_1.Field)({ description: 'First month - YYYY-MM' }),
78
+ tslib_1.__metadata("design:type", String)
79
+ ], RecurringCashItem.prototype, "startMonth", void 0);
80
+ tslib_1.__decorate([
81
+ (0, typeorm_1.Column)({ nullable: true }),
82
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Last month; open-ended when empty - YYYY-MM' }),
83
+ tslib_1.__metadata("design:type", String)
84
+ ], RecurringCashItem.prototype, "endMonth", void 0);
85
+ tslib_1.__decorate([
86
+ (0, typeorm_1.ManyToOne)(type => biz_base_1.Counterparty, { nullable: true, onDelete: 'SET NULL' }),
87
+ (0, type_graphql_1.Field)(type => biz_base_1.Counterparty, { nullable: true, description: 'Who it is paid to or received from' }),
88
+ tslib_1.__metadata("design:type", biz_base_1.Counterparty)
89
+ ], RecurringCashItem.prototype, "counterparty", void 0);
90
+ tslib_1.__decorate([
91
+ (0, typeorm_1.RelationId)((item) => item.counterparty),
92
+ tslib_1.__metadata("design:type", String)
93
+ ], RecurringCashItem.prototype, "counterpartyId", void 0);
94
+ tslib_1.__decorate([
95
+ (0, typeorm_1.Column)({ default: true }),
96
+ (0, type_graphql_1.Field)({ description: 'An inactive item makes no more forecasts' }),
97
+ tslib_1.__metadata("design:type", Boolean)
98
+ ], RecurringCashItem.prototype, "active", void 0);
99
+ tslib_1.__decorate([
100
+ (0, typeorm_1.Column)({ type: 'text', nullable: true }),
101
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Notes' }),
102
+ tslib_1.__metadata("design:type", String)
103
+ ], RecurringCashItem.prototype, "notes", void 0);
104
+ tslib_1.__decorate([
105
+ (0, typeorm_1.CreateDateColumn)(),
106
+ (0, type_graphql_1.Field)({ nullable: true, description: 'When it was created' }),
107
+ tslib_1.__metadata("design:type", Date)
108
+ ], RecurringCashItem.prototype, "createdAt", void 0);
109
+ tslib_1.__decorate([
110
+ (0, typeorm_1.UpdateDateColumn)(),
111
+ (0, type_graphql_1.Field)({ nullable: true, description: 'When it last changed' }),
112
+ tslib_1.__metadata("design:type", Date)
113
+ ], RecurringCashItem.prototype, "updatedAt", void 0);
114
+ tslib_1.__decorate([
115
+ (0, typeorm_1.DeleteDateColumn)(),
116
+ (0, type_graphql_1.Field)({ nullable: true, description: 'When it was deleted - the forecasts it made are kept' }),
117
+ tslib_1.__metadata("design:type", Date)
118
+ ], RecurringCashItem.prototype, "deletedAt", void 0);
119
+ tslib_1.__decorate([
120
+ (0, typeorm_1.ManyToOne)(type => auth_base_1.User, { nullable: true }),
121
+ (0, type_graphql_1.Field)(type => auth_base_1.User, { nullable: true, description: 'Who created it' }),
122
+ tslib_1.__metadata("design:type", auth_base_1.User)
123
+ ], RecurringCashItem.prototype, "creator", void 0);
124
+ tslib_1.__decorate([
125
+ (0, typeorm_1.RelationId)((item) => item.creator),
126
+ tslib_1.__metadata("design:type", String)
127
+ ], RecurringCashItem.prototype, "creatorId", void 0);
128
+ tslib_1.__decorate([
129
+ (0, typeorm_1.ManyToOne)(type => auth_base_1.User, { nullable: true }),
130
+ (0, type_graphql_1.Field)(type => auth_base_1.User, { nullable: true, description: 'Who last changed it' }),
131
+ tslib_1.__metadata("design:type", auth_base_1.User)
132
+ ], RecurringCashItem.prototype, "updater", void 0);
133
+ tslib_1.__decorate([
134
+ (0, typeorm_1.RelationId)((item) => item.updater),
135
+ tslib_1.__metadata("design:type", String)
136
+ ], RecurringCashItem.prototype, "updaterId", void 0);
137
+ exports.RecurringCashItem = RecurringCashItem = tslib_1.__decorate([
138
+ (0, typeorm_1.Entity)(),
139
+ (0, typeorm_1.Index)('ix_recurring_cash_item_0', (item) => [item.domain, item.active]),
140
+ (0, type_graphql_1.ObjectType)({ description: 'Money that comes in or goes out every month on a known day' })
141
+ ], RecurringCashItem);
142
+ //# sourceMappingURL=recurring-cash-item.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recurring-cash-item.js","sourceRoot":"","sources":["../../../server/service/recurring-cash-item/recurring-cash-item.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Column,\n CreateDateColumn,\n DeleteDateColumn,\n Entity,\n Index,\n ManyToOne,\n PrimaryGeneratedColumn,\n RelationId,\n UpdateDateColumn\n} from 'typeorm'\nimport { Field, Float, ID, Int, ObjectType } from 'type-graphql'\n\nimport { Domain, moneyColumn } from '@things-factory/shell'\nimport { User } from '@things-factory/auth-base'\nimport { Counterparty } from '@things-factory/biz-base'\n\nimport { Account } from '../account/account'\nimport { CashFlowType } from '../cash-flow-type'\n\n/**\n * Money that comes in or goes out every month on a known day - rent, a subscription, a loan's interest. Each month it\n * falls in, it makes a forecast (§`Transaction.recurringItem`).\n */\n@Entity()\n@Index('ix_recurring_cash_item_0', (item: RecurringCashItem) => [item.domain, item.active])\n@ObjectType({ description: 'Money that comes in or goes out every month on a known day' })\nexport class RecurringCashItem {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier' })\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'The domain whose item it is' })\n domain?: Domain\n\n @RelationId((item: RecurringCashItem) => item.domain)\n domainId?: string\n\n @Column()\n @Field({ description: 'What it is - the forecasts it makes take this as their description' })\n name: string\n\n @ManyToOne(type => Account, { nullable: true, onDelete: 'SET NULL' })\n @Field(type => Account, { nullable: true, description: 'The account subject it is booked to' })\n account?: Account\n\n @RelationId((item: RecurringCashItem) => item.account)\n accountId?: string\n\n @Column({ default: CashFlowType.EXPENSE })\n @Field(type => CashFlowType, { description: 'Money in or money out' })\n type: CashFlowType\n\n @Column(moneyColumn())\n @Field(type => Float, { description: 'Amount every month' })\n amount: number\n\n @Column({ default: 'KRW' })\n @Field({ description: 'ISO 4217 code' })\n currency: string\n\n @Column({ type: 'int', nullable: true })\n @Field(type => Int, {\n nullable: true,\n description: \"1-31; a day past the month's end is its last day. Empty with lastDayOfMonth\"\n })\n dayOfMonth?: number\n\n @Column({ default: false })\n @Field({ description: 'Falls on the last day of every month' })\n lastDayOfMonth: boolean\n\n @Column()\n @Field({ description: 'First month - YYYY-MM' })\n startMonth: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Last month; open-ended when empty - YYYY-MM' })\n endMonth?: string\n\n @ManyToOne(type => Counterparty, { nullable: true, onDelete: 'SET NULL' })\n @Field(type => Counterparty, { nullable: true, description: 'Who it is paid to or received from' })\n counterparty?: Counterparty\n\n @RelationId((item: RecurringCashItem) => item.counterparty)\n counterpartyId?: string\n\n @Column({ default: true })\n @Field({ description: 'An inactive item makes no more forecasts' })\n active: boolean\n\n @Column({ type: 'text', nullable: true })\n @Field({ nullable: true, description: 'Notes' })\n notes?: string\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'When it was created' })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'When it last changed' })\n updatedAt?: Date\n\n @DeleteDateColumn()\n @Field({ nullable: true, description: 'When it was deleted - the forecasts it made are kept' })\n deletedAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'Who created it' })\n creator?: User\n\n @RelationId((item: RecurringCashItem) => item.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'Who last changed it' })\n updater?: User\n\n @RelationId((item: RecurringCashItem) => item.updater)\n updaterId?: string\n}\n"]}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Which recurring items fall in a month, and the forecast line each one makes.
3
+ *
4
+ * An item falls in a month when it is active and the month lies within [startMonth, endMonth].
5
+ * Its timing is written the way the forecast ledger writes it — `21일`, `말일` — so the calendar
6
+ * places the line on that day (§`forecastDay`). An item with neither a day nor 말일 makes a line
7
+ * with no timing: the calendar shows it undated, as it does any line nobody gave a day.
8
+ *
9
+ * Pure.
10
+ */
11
+ export interface RecurringItem {
12
+ id: string;
13
+ name: string;
14
+ type: string;
15
+ amount: number;
16
+ currency?: string | null;
17
+ dayOfMonth?: number | null;
18
+ lastDayOfMonth?: boolean | null;
19
+ startMonth: string;
20
+ endMonth?: string | null;
21
+ active?: boolean | null;
22
+ }
23
+ export interface GeneratedLine {
24
+ recurringItemId: string;
25
+ year: number;
26
+ month: number;
27
+ type: string;
28
+ name: string;
29
+ amount: number;
30
+ currency: string;
31
+ timing: string | null;
32
+ }
33
+ export declare function fallsIn(item: RecurringItem, year: number, month: number): boolean;
34
+ export declare function timingOf(item: RecurringItem): string | null;
35
+ /** The lines to add for a month — leaving out items that already made one (`already`). */
36
+ export declare function linesFor(items: readonly RecurringItem[], year: number, month: number, already: ReadonlySet<string>): GeneratedLine[];
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ /**
3
+ * Which recurring items fall in a month, and the forecast line each one makes.
4
+ *
5
+ * An item falls in a month when it is active and the month lies within [startMonth, endMonth].
6
+ * Its timing is written the way the forecast ledger writes it — `21일`, `말일` — so the calendar
7
+ * places the line on that day (§`forecastDay`). An item with neither a day nor 말일 makes a line
8
+ * with no timing: the calendar shows it undated, as it does any line nobody gave a day.
9
+ *
10
+ * Pure.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.fallsIn = fallsIn;
14
+ exports.timingOf = timingOf;
15
+ exports.linesFor = linesFor;
16
+ const monthKey = (year, month) => `${year}-${String(month).padStart(2, '0')}`;
17
+ function fallsIn(item, year, month) {
18
+ const key = monthKey(year, month);
19
+ return item.active !== false && item.startMonth <= key && (!item.endMonth || key <= item.endMonth);
20
+ }
21
+ function timingOf(item) {
22
+ if (item.lastDayOfMonth)
23
+ return '말일';
24
+ return item.dayOfMonth ? `${item.dayOfMonth}일` : null;
25
+ }
26
+ /** The lines to add for a month — leaving out items that already made one (`already`). */
27
+ function linesFor(items, year, month, already) {
28
+ return items
29
+ .filter(item => fallsIn(item, year, month) && !already.has(item.id))
30
+ .map(item => ({
31
+ recurringItemId: item.id,
32
+ year,
33
+ month,
34
+ type: item.type,
35
+ name: item.name,
36
+ amount: item.amount,
37
+ currency: item.currency || 'KRW',
38
+ timing: timingOf(item)
39
+ }));
40
+ }
41
+ //# sourceMappingURL=recurring-schedule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recurring-schedule.js","sourceRoot":"","sources":["../../../server/service/recurring-cash-item/recurring-schedule.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;AA4BH,0BAGC;AAED,4BAGC;AAGD,4BAkBC;AA/BD,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAE,KAAa,EAAE,EAAE,CAAC,GAAG,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAA;AAE7F,SAAgB,OAAO,CAAC,IAAmB,EAAE,IAAY,EAAE,KAAa;IACtE,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IACjC,OAAO,IAAI,CAAC,MAAM,KAAK,KAAK,IAAI,IAAI,CAAC,UAAU,IAAI,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,IAAI,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAA;AACpG,CAAC;AAED,SAAgB,QAAQ,CAAC,IAAmB;IAC1C,IAAI,IAAI,CAAC,cAAc;QAAE,OAAO,IAAI,CAAA;IACpC,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,IAAI,CAAA;AACvD,CAAC;AAED,0FAA0F;AAC1F,SAAgB,QAAQ,CACtB,KAA+B,EAC/B,IAAY,EACZ,KAAa,EACb,OAA4B;IAE5B,OAAO,KAAK;SACT,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;SACnE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACZ,eAAe,EAAE,IAAI,CAAC,EAAE;QACxB,IAAI;QACJ,KAAK;QACL,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,KAAK;QAChC,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC;KACvB,CAAC,CAAC,CAAA;AACP,CAAC","sourcesContent":["/**\n * Which recurring items fall in a month, and the forecast line each one makes.\n *\n * An item falls in a month when it is active and the month lies within [startMonth, endMonth].\n * Its timing is written the way the forecast ledger writes it — `21일`, `말일` — so the calendar\n * places the line on that day (§`forecastDay`). An item with neither a day nor 말일 makes a line\n * with no timing: the calendar shows it undated, as it does any line nobody gave a day.\n *\n * Pure.\n */\n\nexport interface RecurringItem {\n id: string\n name: string\n type: string\n amount: number\n currency?: string | null\n dayOfMonth?: number | null\n lastDayOfMonth?: boolean | null\n startMonth: string\n endMonth?: string | null\n active?: boolean | null\n}\n\nexport interface GeneratedLine {\n recurringItemId: string\n year: number\n month: number\n type: string\n name: string\n amount: number\n currency: string\n timing: string | null\n}\n\nconst monthKey = (year: number, month: number) => `${year}-${String(month).padStart(2, '0')}`\n\nexport function fallsIn(item: RecurringItem, year: number, month: number): boolean {\n const key = monthKey(year, month)\n return item.active !== false && item.startMonth <= key && (!item.endMonth || key <= item.endMonth)\n}\n\nexport function timingOf(item: RecurringItem): string | null {\n if (item.lastDayOfMonth) return '말일'\n return item.dayOfMonth ? `${item.dayOfMonth}일` : null\n}\n\n/** The lines to add for a month — leaving out items that already made one (`already`). */\nexport function linesFor(\n items: readonly RecurringItem[],\n year: number,\n month: number,\n already: ReadonlySet<string>\n): GeneratedLine[] {\n return items\n .filter(item => fallsIn(item, year, month) && !already.has(item.id))\n .map(item => ({\n recurringItemId: item.id,\n year,\n month,\n type: item.type,\n name: item.name,\n amount: item.amount,\n currency: item.currency || 'KRW',\n timing: timingOf(item)\n }))\n}\n"]}
@@ -1,29 +1,56 @@
1
1
  import { HistoryActionType, HistoryEntityInterface } from '@operato/typeorm-history';
2
2
  import { User } from '@things-factory/auth-base';
3
3
  import { Domain } from '@things-factory/shell';
4
- import { Transaction, TransactionCategory, TransactionStatus, TransactionType } from './transaction';
4
+ import { Counterparty } from '@things-factory/biz-base';
5
5
  import { Account } from '../account/account';
6
+ import { BankAccount } from '../bank-account/bank-account';
7
+ import { BankStatement } from '../bank-statement/bank-statement';
8
+ import { CashFlowType } from '../cash-flow-type';
9
+ import { RecurringCashItem } from '../recurring-cash-item/recurring-cash-item';
10
+ import { ForecastStatus, Transaction, TransactionCategory, TransactionSource } from './transaction';
11
+ /** Each version of a transaction, written when it changes. */
6
12
  export declare class TransactionHistory implements HistoryEntityInterface<Transaction> {
7
13
  readonly id: string;
8
14
  version?: number;
9
15
  domain?: Domain;
10
16
  domainId?: string;
11
- name?: string;
12
- description?: string;
13
- currency?: string;
14
- amount?: number;
15
- active?: boolean;
16
- type?: TransactionType;
17
17
  category: TransactionCategory;
18
- status: TransactionStatus;
19
- probability?: number;
20
- forecastNotes?: string;
21
- account?: Account;
22
- accountId?: string;
23
- year?: number;
24
- quarter?: number;
25
- month?: number;
18
+ type: CashFlowType;
19
+ bankAccount: BankAccount;
20
+ bankAccountId?: string;
26
21
  transactionDate: string;
22
+ transactionAt: string;
23
+ year: number;
24
+ month: number;
25
+ amount: number;
26
+ currency: string;
27
+ balance: number;
28
+ account: Account;
29
+ accountId?: string;
30
+ description: string;
31
+ ledgerCategory: string;
32
+ counterpartyName: string;
33
+ counterparty: Counterparty;
34
+ counterpartyId?: string;
35
+ source: TransactionSource;
36
+ bankStatement: BankStatement;
37
+ bankStatementId?: string;
38
+ sourceFile: string;
39
+ sourceRow: number;
40
+ bankSequence: number;
41
+ bankFingerprint: string;
42
+ bankDescription: string;
43
+ bankKind: string;
44
+ bankCounterpartyName: string;
45
+ bankCounterpartyAccount: string;
46
+ bankCounterpartyBank: string;
47
+ bankMemo: string;
48
+ timing: string;
49
+ status: ForecastStatus;
50
+ probability: number;
51
+ notes: string;
52
+ recurringItem: RecurringCashItem;
53
+ recurringItemId?: string;
27
54
  createdAt?: Date;
28
55
  updatedAt?: Date;
29
56
  deletedAt?: Date;