@things-factory/accounting 10.1.238 → 10.1.241

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 (43) hide show
  1. package/dist-server/service/index.d.ts +4 -0
  2. package/dist-server/service/index.js +4 -0
  3. package/dist-server/service/index.js.map +1 -1
  4. package/dist-server/service/recurring-cash-item/index.d.ts +3 -1
  5. package/dist-server/service/recurring-cash-item/index.js +3 -1
  6. package/dist-server/service/recurring-cash-item/index.js.map +1 -1
  7. package/dist-server/service/recurring-cash-item/recurring-candidate-service.d.ts +29 -0
  8. package/dist-server/service/recurring-cash-item/recurring-candidate-service.js +117 -0
  9. package/dist-server/service/recurring-cash-item/recurring-candidate-service.js.map +1 -0
  10. package/dist-server/service/recurring-cash-item/recurring-candidates.d.ts +42 -0
  11. package/dist-server/service/recurring-cash-item/recurring-candidates.js +57 -0
  12. package/dist-server/service/recurring-cash-item/recurring-candidates.js.map +1 -0
  13. package/dist-server/service/recurring-cash-item/recurring-cash-item-mutation.d.ts +2 -0
  14. package/dist-server/service/recurring-cash-item/recurring-cash-item-mutation.js +38 -0
  15. package/dist-server/service/recurring-cash-item/recurring-cash-item-mutation.js.map +1 -1
  16. package/dist-server/service/recurring-cash-item/recurring-cash-item-query.d.ts +2 -1
  17. package/dist-server/service/recurring-cash-item/recurring-cash-item-query.js +14 -0
  18. package/dist-server/service/recurring-cash-item/recurring-cash-item-query.js.map +1 -1
  19. package/dist-server/service/recurring-cash-item/recurring-cash-item-service.js +8 -3
  20. package/dist-server/service/recurring-cash-item/recurring-cash-item-service.js.map +1 -1
  21. package/dist-server/service/recurring-cash-item/recurring-cash-item-type.d.ts +15 -0
  22. package/dist-server/service/recurring-cash-item/recurring-cash-item-type.js +60 -2
  23. package/dist-server/service/recurring-cash-item/recurring-cash-item-type.js.map +1 -1
  24. package/dist-server/service/recurring-cash-item/recurring-cash-item.d.ts +2 -1
  25. package/dist-server/service/recurring-cash-item/recurring-cash-item.js +7 -2
  26. package/dist-server/service/recurring-cash-item/recurring-cash-item.js.map +1 -1
  27. package/dist-server/service/recurring-cash-item/recurring-hidden-vendor.d.ts +24 -0
  28. package/dist-server/service/recurring-cash-item/recurring-hidden-vendor.js +84 -0
  29. package/dist-server/service/recurring-cash-item/recurring-hidden-vendor.js.map +1 -0
  30. package/dist-server/service/recurring-cash-item/recurring-schedule.d.ts +12 -1
  31. package/dist-server/service/recurring-cash-item/recurring-schedule.js +28 -0
  32. package/dist-server/service/recurring-cash-item/recurring-schedule.js.map +1 -1
  33. package/dist-server/service/recurring-cash-item/recurring-target.d.ts +2 -0
  34. package/dist-server/service/recurring-cash-item/recurring-target.js +43 -0
  35. package/dist-server/service/recurring-cash-item/recurring-target.js.map +1 -0
  36. package/dist-server/tsconfig.tsbuildinfo +1 -1
  37. package/package.json +10 -10
  38. package/translations/en.json +7 -2
  39. package/translations/es.json +7 -2
  40. package/translations/ja.json +7 -1
  41. package/translations/ko.json +7 -2
  42. package/translations/ms.json +7 -1
  43. package/translations/zh.json +7 -1
@@ -28,7 +28,11 @@ export * from './payment/document-targets';
28
28
  export * from './financial-statement/financial-statement-line';
29
29
  export * from './financial-statement/financial-statement-service';
30
30
  export * from './recurring-cash-item/recurring-schedule';
31
+ export * from './recurring-cash-item/recurring-target';
31
32
  export * from './recurring-cash-item/recurring-cash-item-service';
33
+ export * from './recurring-cash-item/recurring-candidates';
34
+ export * from './recurring-cash-item/recurring-candidate-service';
35
+ export * from './recurring-cash-item/recurring-hidden-vendor';
32
36
  export * from './account/account-match';
33
37
  export * from './account/default-accounts';
34
38
  export * from './account/account-choice';
@@ -34,7 +34,11 @@ tslib_1.__exportStar(require("./payment/document-targets"), exports);
34
34
  tslib_1.__exportStar(require("./financial-statement/financial-statement-line"), exports);
35
35
  tslib_1.__exportStar(require("./financial-statement/financial-statement-service"), exports);
36
36
  tslib_1.__exportStar(require("./recurring-cash-item/recurring-schedule"), exports);
37
+ tslib_1.__exportStar(require("./recurring-cash-item/recurring-target"), exports);
37
38
  tslib_1.__exportStar(require("./recurring-cash-item/recurring-cash-item-service"), exports);
39
+ tslib_1.__exportStar(require("./recurring-cash-item/recurring-candidates"), exports);
40
+ tslib_1.__exportStar(require("./recurring-cash-item/recurring-candidate-service"), exports);
41
+ tslib_1.__exportStar(require("./recurring-cash-item/recurring-hidden-vendor"), exports);
38
42
  tslib_1.__exportStar(require("./account/account-match"), exports);
39
43
  tslib_1.__exportStar(require("./account/default-accounts"), exports);
40
44
  tslib_1.__exportStar(require("./account/account-choice"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/service/index.ts"],"names":[],"mappings":";;;;AAAA,yBAAyB;AACzB,2DAAgC;AAChC,oFAAyD;AACzD,oFAAyD;AACzD,oEAAyC;AACzC,sEAA2C;AAC3C,0EAA+C;AAC/C,4DAAiC;AACjC,4DAAiC;AACjC,oFAAyD;AACzD,oFAAyD;AACzD,wFAA6D;AAC7D,sEAA2C;AAC3C,0EAA+C;AAC/C,oEAAyC;AACzC,oFAAyD;AACzD,yFAA8D;AAE9D,qBAAqB;AACrB,2EAAgD;AAChD,4EAAiD;AACjD,0EAA+C;AAC/C,8EAAmD;AACnD,oEAAyC;AACzC,sEAA2C;AAC3C,qEAA0C;AAC1C,oEAAyC;AACzC,oEAAyC;AACzC,qEAA0C;AAC1C,qEAA0C;AAC1C,yFAA8D;AAC9D,4FAAiE;AACjE,mFAAwD;AACxD,4FAAiE;AACjE,kEAAuC;AACvC,qEAA0C;AAC1C,mEAAwC;AACxC,oEAAyC;AACzC,uEAA4C;AAC5C,uEAA4C;AAC5C,0EAA+C;AAC/C,4EAAiD;AACjD,uEAA4C;AAC5C,4FAAiE;AACjE,8FAAmE;AACnE,0FAA+D;AAC/D,0FAA+D;AAC/D,4FAAiE;AAEjE,mCAAmC;AACnC,+DAI8B;AAC9B,+DAI8B;AAC9B,+CAIsB;AACtB,iDAIuB;AACvB,qDAIyB;AACzB,uCAIkB;AAClB,uCAIkB;AAClB,+DAI8B;AAC9B,+DAI8B;AAC9B,mEAIgC;AAChC,iDAIuB;AACvB,qDAIyB;AACzB,+CAIsB;AACtB,iEAI+B;AAC/B,+DAI8B;AAEjB,QAAA,QAAQ,GAAG;IACtB,GAAG,8BAA0B;IAC7B,GAAG,8BAA0B;IAC7B,GAAG,sBAAmB;IACtB,GAAG,uBAAmB;IACtB,GAAG,yBAAqB;IACxB,GAAG,kBAAe;IAClB,GAAG,kBAAe;IAClB,GAAG,8BAA0B;IAC7B,GAAG,8BAAyB;IAC5B,GAAG,gCAA4B;IAC/B,GAAG,uBAAmB;IACtB,GAAG,yBAAqB;IACxB,GAAG,sBAAkB;IACrB,GAAG,+BAA2B;IAC9B,GAAG,8BAA0B;CAC9B,CAAA;AAEY,QAAA,WAAW,GAAG;IACzB,GAAG,iCAA6B;IAChC,GAAG,iCAA6B;IAChC,GAAG,yBAAsB;IACzB,GAAG,0BAAsB;IACzB,GAAG,4BAAwB;IAC3B,GAAG,qBAAkB;IACrB,GAAG,qBAAkB;IACrB,GAAG,iCAA6B;IAChC,GAAG,iCAA4B;IAC/B,GAAG,mCAA+B;IAClC,GAAG,0BAAsB;IACzB,GAAG,4BAAwB;IAC3B,GAAG,yBAAqB;IACxB,GAAG,kCAA8B;IACjC,GAAG,iCAA6B;CACjC,CAAA;AAEY,QAAA,MAAM,GAAG;IACpB,eAAe,EAAE;QACf,GAAG,+BAA2B;QAC9B,GAAG,+BAA2B;QAC9B,GAAG,uBAAoB;QACvB,GAAG,wBAAoB;QACvB,GAAG,0BAAsB;QACzB,GAAG,mBAAgB;QACnB,GAAG,mBAAgB;QACnB,GAAG,+BAA2B;QAC9B,GAAG,+BAA0B;QAC7B,GAAG,iCAA6B;QAChC,GAAG,wBAAoB;QACvB,GAAG,0BAAsB;QACzB,GAAG,uBAAmB;QACtB,GAAG,gCAA4B;QAC/B,GAAG,+BAA2B;KAC/B;CACF,CAAA","sourcesContent":["/* EXPORT ENTITY TYPES */\nexport * from './cash-flow-type'\nexport * from './financial-statement/financial-statement'\nexport * from './accounting-category/accounting-category'\nexport * from './transaction/transaction'\nexport * from './bank-account/bank-account'\nexport * from './bank-statement/bank-statement'\nexport * from './payment/payment'\nexport * from './account/account'\nexport * from './accounting-document/accounting-document'\nexport * from './recurring-cash-item/recurring-cash-item'\nexport * from './financial-institution/financial-institution'\nexport * from './fiscal-month/fiscal-month'\nexport * from './fiscal-quarter/fiscal-quarter'\nexport * from './fiscal-year/fiscal-year'\nexport * from './expenditure-request/expenditure-request'\nexport * from './expenditure-request/expenditure-request-item'\n\n/* EXPORT SERVICES */\nexport * from './transaction/transaction-period'\nexport * from './transaction/transaction-service'\nexport * from './transaction/transaction-links'\nexport * from './bank-account/bank-account-service'\nexport * from './bank-account/card-rules'\nexport * from './bank-account/card-summary'\nexport * from './payment/card-bill-target'\nexport * from './payment/payment-targets'\nexport * from './payment/payment-service'\nexport * from './payment/payment-currency'\nexport * from './payment/document-targets'\nexport * from './financial-statement/financial-statement-line'\nexport * from './financial-statement/financial-statement-service'\nexport * from './recurring-cash-item/recurring-schedule'\nexport * from './recurring-cash-item/recurring-cash-item-service'\nexport * from './account/account-match'\nexport * from './account/default-accounts'\nexport * from './account/account-choice'\nexport * from './account/account-service'\nexport * from './bank-statement/bank-source'\nexport * from './bank-statement/bank-parser'\nexport * from './bank-statement/bank-reconcile'\nexport * from './bank-statement/bank-import-type'\nexport * from './bank-statement/bank-import'\nexport * from './counterparty-account/counterparty-account-rules'\nexport * from './counterparty-account/counterparty-account-service'\nexport * from './expenditure-request/expenditure-request-rules'\nexport * from './expenditure-request/expenditure-payment-state'\nexport * from './expenditure-request/expenditure-request-service'\n\n/* IMPORT ENTITIES AND RESOLVERS */\nimport {\n entities as FinancialStatementEntities,\n resolvers as FinancialStatementResolvers,\n subscribers as FinancialStatementSubscribers\n} from './financial-statement'\nimport {\n entities as AccountingCategoryEntities,\n resolvers as AccountingCategoryResolvers,\n subscribers as AccountingCategorySubscribers\n} from './accounting-category'\nimport {\n entities as TransactionEntities,\n resolvers as TransactionResolvers,\n subscribers as TransactionSubscribers\n} from './transaction'\nimport {\n entities as BankAccountEntities,\n resolvers as BankAccountResolvers,\n subscribers as BankAccountSubscribers\n} from './bank-account'\nimport {\n entities as BankStatementEntities,\n resolvers as BankStatementResolvers,\n subscribers as BankStatementSubscribers\n} from './bank-statement'\nimport {\n entities as PaymentEntities,\n resolvers as PaymentResolvers,\n subscribers as PaymentSubscribers\n} from './payment'\nimport {\n entities as AccountEntities,\n resolvers as AccountResolvers,\n subscribers as AccountSubscribers\n} from './account'\nimport {\n entities as AccountingDocumentEntities,\n resolvers as AccountingDocumentResolvers,\n subscribers as AccountingDocumentSubscribers\n} from './accounting-document'\nimport {\n entities as RecurringCashItemEntities,\n resolvers as RecurringCashItemResolvers,\n subscribers as RecurringCashItemSubscribers\n} from './recurring-cash-item'\nimport {\n entities as FinancialInstitutionEntities,\n resolvers as FinancialInstitutionResolvers,\n subscribers as FinancialInstitutionSubscribers\n} from './financial-institution'\nimport {\n entities as FiscalMonthEntities,\n resolvers as FiscalMonthResolvers,\n subscribers as FiscalMonthSubscribers\n} from './fiscal-month'\nimport {\n entities as FiscalQuarterEntities,\n resolvers as FiscalQuarterResolvers,\n subscribers as FiscalQuarterSubscribers\n} from './fiscal-quarter'\nimport {\n entities as FiscalYearEntities,\n resolvers as FiscalYearResolvers,\n subscribers as FiscalYearSubscribers\n} from './fiscal-year'\nimport {\n entities as CounterpartyAccountEntities,\n resolvers as CounterpartyAccountResolvers,\n subscribers as CounterpartyAccountSubscribers\n} from './counterparty-account'\nimport {\n entities as ExpenditureRequestEntities,\n resolvers as ExpenditureRequestResolvers,\n subscribers as ExpenditureRequestSubscribers\n} from './expenditure-request'\n\nexport const entities = [\n ...FinancialStatementEntities,\n ...AccountingCategoryEntities,\n ...TransactionEntities,\n ...BankAccountEntities,\n ...BankStatementEntities,\n ...PaymentEntities,\n ...AccountEntities,\n ...AccountingDocumentEntities,\n ...RecurringCashItemEntities,\n ...FinancialInstitutionEntities,\n ...FiscalMonthEntities,\n ...FiscalQuarterEntities,\n ...FiscalYearEntities,\n ...CounterpartyAccountEntities,\n ...ExpenditureRequestEntities\n]\n\nexport const subscribers = [\n ...FinancialStatementSubscribers,\n ...AccountingCategorySubscribers,\n ...TransactionSubscribers,\n ...BankAccountSubscribers,\n ...BankStatementSubscribers,\n ...PaymentSubscribers,\n ...AccountSubscribers,\n ...AccountingDocumentSubscribers,\n ...RecurringCashItemSubscribers,\n ...FinancialInstitutionSubscribers,\n ...FiscalMonthSubscribers,\n ...FiscalQuarterSubscribers,\n ...FiscalYearSubscribers,\n ...CounterpartyAccountSubscribers,\n ...ExpenditureRequestSubscribers\n]\n\nexport const schema = {\n resolverClasses: [\n ...FinancialStatementResolvers,\n ...AccountingCategoryResolvers,\n ...TransactionResolvers,\n ...BankAccountResolvers,\n ...BankStatementResolvers,\n ...PaymentResolvers,\n ...AccountResolvers,\n ...AccountingDocumentResolvers,\n ...RecurringCashItemResolvers,\n ...FinancialInstitutionResolvers,\n ...FiscalMonthResolvers,\n ...FiscalQuarterResolvers,\n ...FiscalYearResolvers,\n ...CounterpartyAccountResolvers,\n ...ExpenditureRequestResolvers\n ]\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/service/index.ts"],"names":[],"mappings":";;;;AAAA,yBAAyB;AACzB,2DAAgC;AAChC,oFAAyD;AACzD,oFAAyD;AACzD,oEAAyC;AACzC,sEAA2C;AAC3C,0EAA+C;AAC/C,4DAAiC;AACjC,4DAAiC;AACjC,oFAAyD;AACzD,oFAAyD;AACzD,wFAA6D;AAC7D,sEAA2C;AAC3C,0EAA+C;AAC/C,oEAAyC;AACzC,oFAAyD;AACzD,yFAA8D;AAE9D,qBAAqB;AACrB,2EAAgD;AAChD,4EAAiD;AACjD,0EAA+C;AAC/C,8EAAmD;AACnD,oEAAyC;AACzC,sEAA2C;AAC3C,qEAA0C;AAC1C,oEAAyC;AACzC,oEAAyC;AACzC,qEAA0C;AAC1C,qEAA0C;AAC1C,yFAA8D;AAC9D,4FAAiE;AACjE,mFAAwD;AACxD,iFAAsD;AACtD,4FAAiE;AACjE,qFAA0D;AAC1D,4FAAiE;AACjE,wFAA6D;AAC7D,kEAAuC;AACvC,qEAA0C;AAC1C,mEAAwC;AACxC,oEAAyC;AACzC,uEAA4C;AAC5C,uEAA4C;AAC5C,0EAA+C;AAC/C,4EAAiD;AACjD,uEAA4C;AAC5C,4FAAiE;AACjE,8FAAmE;AACnE,0FAA+D;AAC/D,0FAA+D;AAC/D,4FAAiE;AAEjE,mCAAmC;AACnC,+DAI8B;AAC9B,+DAI8B;AAC9B,+CAIsB;AACtB,iDAIuB;AACvB,qDAIyB;AACzB,uCAIkB;AAClB,uCAIkB;AAClB,+DAI8B;AAC9B,+DAI8B;AAC9B,mEAIgC;AAChC,iDAIuB;AACvB,qDAIyB;AACzB,+CAIsB;AACtB,iEAI+B;AAC/B,+DAI8B;AAEjB,QAAA,QAAQ,GAAG;IACtB,GAAG,8BAA0B;IAC7B,GAAG,8BAA0B;IAC7B,GAAG,sBAAmB;IACtB,GAAG,uBAAmB;IACtB,GAAG,yBAAqB;IACxB,GAAG,kBAAe;IAClB,GAAG,kBAAe;IAClB,GAAG,8BAA0B;IAC7B,GAAG,8BAAyB;IAC5B,GAAG,gCAA4B;IAC/B,GAAG,uBAAmB;IACtB,GAAG,yBAAqB;IACxB,GAAG,sBAAkB;IACrB,GAAG,+BAA2B;IAC9B,GAAG,8BAA0B;CAC9B,CAAA;AAEY,QAAA,WAAW,GAAG;IACzB,GAAG,iCAA6B;IAChC,GAAG,iCAA6B;IAChC,GAAG,yBAAsB;IACzB,GAAG,0BAAsB;IACzB,GAAG,4BAAwB;IAC3B,GAAG,qBAAkB;IACrB,GAAG,qBAAkB;IACrB,GAAG,iCAA6B;IAChC,GAAG,iCAA4B;IAC/B,GAAG,mCAA+B;IAClC,GAAG,0BAAsB;IACzB,GAAG,4BAAwB;IAC3B,GAAG,yBAAqB;IACxB,GAAG,kCAA8B;IACjC,GAAG,iCAA6B;CACjC,CAAA;AAEY,QAAA,MAAM,GAAG;IACpB,eAAe,EAAE;QACf,GAAG,+BAA2B;QAC9B,GAAG,+BAA2B;QAC9B,GAAG,uBAAoB;QACvB,GAAG,wBAAoB;QACvB,GAAG,0BAAsB;QACzB,GAAG,mBAAgB;QACnB,GAAG,mBAAgB;QACnB,GAAG,+BAA2B;QAC9B,GAAG,+BAA0B;QAC7B,GAAG,iCAA6B;QAChC,GAAG,wBAAoB;QACvB,GAAG,0BAAsB;QACzB,GAAG,uBAAmB;QACtB,GAAG,gCAA4B;QAC/B,GAAG,+BAA2B;KAC/B;CACF,CAAA","sourcesContent":["/* EXPORT ENTITY TYPES */\nexport * from './cash-flow-type'\nexport * from './financial-statement/financial-statement'\nexport * from './accounting-category/accounting-category'\nexport * from './transaction/transaction'\nexport * from './bank-account/bank-account'\nexport * from './bank-statement/bank-statement'\nexport * from './payment/payment'\nexport * from './account/account'\nexport * from './accounting-document/accounting-document'\nexport * from './recurring-cash-item/recurring-cash-item'\nexport * from './financial-institution/financial-institution'\nexport * from './fiscal-month/fiscal-month'\nexport * from './fiscal-quarter/fiscal-quarter'\nexport * from './fiscal-year/fiscal-year'\nexport * from './expenditure-request/expenditure-request'\nexport * from './expenditure-request/expenditure-request-item'\n\n/* EXPORT SERVICES */\nexport * from './transaction/transaction-period'\nexport * from './transaction/transaction-service'\nexport * from './transaction/transaction-links'\nexport * from './bank-account/bank-account-service'\nexport * from './bank-account/card-rules'\nexport * from './bank-account/card-summary'\nexport * from './payment/card-bill-target'\nexport * from './payment/payment-targets'\nexport * from './payment/payment-service'\nexport * from './payment/payment-currency'\nexport * from './payment/document-targets'\nexport * from './financial-statement/financial-statement-line'\nexport * from './financial-statement/financial-statement-service'\nexport * from './recurring-cash-item/recurring-schedule'\nexport * from './recurring-cash-item/recurring-target'\nexport * from './recurring-cash-item/recurring-cash-item-service'\nexport * from './recurring-cash-item/recurring-candidates'\nexport * from './recurring-cash-item/recurring-candidate-service'\nexport * from './recurring-cash-item/recurring-hidden-vendor'\nexport * from './account/account-match'\nexport * from './account/default-accounts'\nexport * from './account/account-choice'\nexport * from './account/account-service'\nexport * from './bank-statement/bank-source'\nexport * from './bank-statement/bank-parser'\nexport * from './bank-statement/bank-reconcile'\nexport * from './bank-statement/bank-import-type'\nexport * from './bank-statement/bank-import'\nexport * from './counterparty-account/counterparty-account-rules'\nexport * from './counterparty-account/counterparty-account-service'\nexport * from './expenditure-request/expenditure-request-rules'\nexport * from './expenditure-request/expenditure-payment-state'\nexport * from './expenditure-request/expenditure-request-service'\n\n/* IMPORT ENTITIES AND RESOLVERS */\nimport {\n entities as FinancialStatementEntities,\n resolvers as FinancialStatementResolvers,\n subscribers as FinancialStatementSubscribers\n} from './financial-statement'\nimport {\n entities as AccountingCategoryEntities,\n resolvers as AccountingCategoryResolvers,\n subscribers as AccountingCategorySubscribers\n} from './accounting-category'\nimport {\n entities as TransactionEntities,\n resolvers as TransactionResolvers,\n subscribers as TransactionSubscribers\n} from './transaction'\nimport {\n entities as BankAccountEntities,\n resolvers as BankAccountResolvers,\n subscribers as BankAccountSubscribers\n} from './bank-account'\nimport {\n entities as BankStatementEntities,\n resolvers as BankStatementResolvers,\n subscribers as BankStatementSubscribers\n} from './bank-statement'\nimport {\n entities as PaymentEntities,\n resolvers as PaymentResolvers,\n subscribers as PaymentSubscribers\n} from './payment'\nimport {\n entities as AccountEntities,\n resolvers as AccountResolvers,\n subscribers as AccountSubscribers\n} from './account'\nimport {\n entities as AccountingDocumentEntities,\n resolvers as AccountingDocumentResolvers,\n subscribers as AccountingDocumentSubscribers\n} from './accounting-document'\nimport {\n entities as RecurringCashItemEntities,\n resolvers as RecurringCashItemResolvers,\n subscribers as RecurringCashItemSubscribers\n} from './recurring-cash-item'\nimport {\n entities as FinancialInstitutionEntities,\n resolvers as FinancialInstitutionResolvers,\n subscribers as FinancialInstitutionSubscribers\n} from './financial-institution'\nimport {\n entities as FiscalMonthEntities,\n resolvers as FiscalMonthResolvers,\n subscribers as FiscalMonthSubscribers\n} from './fiscal-month'\nimport {\n entities as FiscalQuarterEntities,\n resolvers as FiscalQuarterResolvers,\n subscribers as FiscalQuarterSubscribers\n} from './fiscal-quarter'\nimport {\n entities as FiscalYearEntities,\n resolvers as FiscalYearResolvers,\n subscribers as FiscalYearSubscribers\n} from './fiscal-year'\nimport {\n entities as CounterpartyAccountEntities,\n resolvers as CounterpartyAccountResolvers,\n subscribers as CounterpartyAccountSubscribers\n} from './counterparty-account'\nimport {\n entities as ExpenditureRequestEntities,\n resolvers as ExpenditureRequestResolvers,\n subscribers as ExpenditureRequestSubscribers\n} from './expenditure-request'\n\nexport const entities = [\n ...FinancialStatementEntities,\n ...AccountingCategoryEntities,\n ...TransactionEntities,\n ...BankAccountEntities,\n ...BankStatementEntities,\n ...PaymentEntities,\n ...AccountEntities,\n ...AccountingDocumentEntities,\n ...RecurringCashItemEntities,\n ...FinancialInstitutionEntities,\n ...FiscalMonthEntities,\n ...FiscalQuarterEntities,\n ...FiscalYearEntities,\n ...CounterpartyAccountEntities,\n ...ExpenditureRequestEntities\n]\n\nexport const subscribers = [\n ...FinancialStatementSubscribers,\n ...AccountingCategorySubscribers,\n ...TransactionSubscribers,\n ...BankAccountSubscribers,\n ...BankStatementSubscribers,\n ...PaymentSubscribers,\n ...AccountSubscribers,\n ...AccountingDocumentSubscribers,\n ...RecurringCashItemSubscribers,\n ...FinancialInstitutionSubscribers,\n ...FiscalMonthSubscribers,\n ...FiscalQuarterSubscribers,\n ...FiscalYearSubscribers,\n ...CounterpartyAccountSubscribers,\n ...ExpenditureRequestSubscribers\n]\n\nexport const schema = {\n resolverClasses: [\n ...FinancialStatementResolvers,\n ...AccountingCategoryResolvers,\n ...TransactionResolvers,\n ...BankAccountResolvers,\n ...BankStatementResolvers,\n ...PaymentResolvers,\n ...AccountResolvers,\n ...AccountingDocumentResolvers,\n ...RecurringCashItemResolvers,\n ...FinancialInstitutionResolvers,\n ...FiscalMonthResolvers,\n ...FiscalQuarterResolvers,\n ...FiscalYearResolvers,\n ...CounterpartyAccountResolvers,\n ...ExpenditureRequestResolvers\n ]\n}\n"]}
@@ -1,6 +1,8 @@
1
1
  import { RecurringCashItem } from './recurring-cash-item';
2
+ import { RecurringHiddenVendor } from './recurring-hidden-vendor';
2
3
  import { RecurringCashItemQuery } from './recurring-cash-item-query';
3
4
  import { RecurringCashItemMutation } from './recurring-cash-item-mutation';
4
- export declare const entities: (typeof RecurringCashItem)[];
5
+ import './recurring-target';
6
+ export declare const entities: (typeof RecurringCashItem | typeof RecurringHiddenVendor)[];
5
7
  export declare const resolvers: (typeof RecurringCashItemQuery | typeof RecurringCashItemMutation)[];
6
8
  export declare const subscribers: any[];
@@ -2,9 +2,11 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.subscribers = exports.resolvers = exports.entities = void 0;
4
4
  const recurring_cash_item_1 = require("./recurring-cash-item");
5
+ const recurring_hidden_vendor_1 = require("./recurring-hidden-vendor");
5
6
  const recurring_cash_item_query_1 = require("./recurring-cash-item-query");
6
7
  const recurring_cash_item_mutation_1 = require("./recurring-cash-item-mutation");
7
- exports.entities = [recurring_cash_item_1.RecurringCashItem];
8
+ require("./recurring-target");
9
+ exports.entities = [recurring_cash_item_1.RecurringCashItem, recurring_hidden_vendor_1.RecurringHiddenVendor];
8
10
  exports.resolvers = [recurring_cash_item_query_1.RecurringCashItemQuery, recurring_cash_item_mutation_1.RecurringCashItemMutation];
9
11
  exports.subscribers = [];
10
12
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/recurring-cash-item/index.ts"],"names":[],"mappings":";;;AAAA,+DAAyD;AACzD,2EAAoE;AACpE,iFAA0E;AAE7D,QAAA,QAAQ,GAAG,CAAC,uCAAiB,CAAC,CAAA;AAC9B,QAAA,SAAS,GAAG,CAAC,kDAAsB,EAAE,wDAAyB,CAAC,CAAA;AAC/D,QAAA,WAAW,GAAG,EAAE,CAAA","sourcesContent":["import { RecurringCashItem } from './recurring-cash-item'\nimport { RecurringCashItemQuery } from './recurring-cash-item-query'\nimport { RecurringCashItemMutation } from './recurring-cash-item-mutation'\n\nexport const entities = [RecurringCashItem]\nexport const resolvers = [RecurringCashItemQuery, RecurringCashItemMutation]\nexport const subscribers = []\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/recurring-cash-item/index.ts"],"names":[],"mappings":";;;AAAA,+DAAyD;AACzD,uEAAiE;AACjE,2EAAoE;AACpE,iFAA0E;AAC1E,8BAA2B;AAEd,QAAA,QAAQ,GAAG,CAAC,uCAAiB,EAAE,+CAAqB,CAAC,CAAA;AACrD,QAAA,SAAS,GAAG,CAAC,kDAAsB,EAAE,wDAAyB,CAAC,CAAA;AAC/D,QAAA,WAAW,GAAG,EAAE,CAAA","sourcesContent":["import { RecurringCashItem } from './recurring-cash-item'\nimport { RecurringHiddenVendor } from './recurring-hidden-vendor'\nimport { RecurringCashItemQuery } from './recurring-cash-item-query'\nimport { RecurringCashItemMutation } from './recurring-cash-item-mutation'\nimport './recurring-target'\n\nexport const entities = [RecurringCashItem, RecurringHiddenVendor]\nexport const resolvers = [RecurringCashItemQuery, RecurringCashItemMutation]\nexport const subscribers = []\n"]}
@@ -0,0 +1,29 @@
1
+ import { EntityManager } from 'typeorm';
2
+ import { RecurringCashItem } from './recurring-cash-item';
3
+ import { CandidateFacts } from './recurring-candidates';
4
+ /** A candidate with its vendor's name, for the list. */
5
+ export type RecurringCandidateRow = CandidateFacts & {
6
+ counterpartyName: string;
7
+ hidden: boolean;
8
+ };
9
+ /**
10
+ * Whom the bank and card lines of the last twelve months show paid month after month that is no recurring item yet.
11
+ * A line on a subject outside profit and loss (a card bill, a tax, a transfer, a loan) pays no vendor, and a person
12
+ * (salary, expenses) is no vendor. With `hidden`, the ones a keeper hid instead.
13
+ */
14
+ export declare function recurringCandidatesOf(tx: EntityManager, domain: {
15
+ id: string;
16
+ }, today: string, hidden?: boolean): Promise<RecurringCandidateRow[]>;
17
+ /**
18
+ * Make a recurring item of each candidate - money out, named after the vendor, on the subject and the day it was paid on
19
+ * most, from the month of its first line, its amount empty (it varies - expected at its latest months). A vendor the
20
+ * lines only name is registered as a counterparty first; the lines written with its name are linked to it. One that is
21
+ * no candidate any more is refused.
22
+ */
23
+ export declare function createRecurringItemsFromCandidates(tx: EntityManager, domain: {
24
+ id: string;
25
+ }, user: any, keys: string[], today: string): Promise<RecurringCashItem[]>;
26
+ /** Hide candidates - by their keys - or show them again. */
27
+ export declare function hideRecurringCandidates(tx: EntityManager, domain: {
28
+ id: string;
29
+ }, user: any, keys: string[], hide: boolean): Promise<boolean>;
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.recurringCandidatesOf = recurringCandidatesOf;
4
+ exports.createRecurringItemsFromCandidates = createRecurringItemsFromCandidates;
5
+ exports.hideRecurringCandidates = hideRecurringCandidates;
6
+ const biz_base_1 = require("@things-factory/biz-base");
7
+ const shell_1 = require("@things-factory/shell");
8
+ const typeorm_1 = require("typeorm");
9
+ const cash_flow_type_1 = require("../cash-flow-type");
10
+ const transaction_1 = require("../transaction/transaction");
11
+ const transaction_links_1 = require("../transaction/transaction-links");
12
+ const recurring_cash_item_1 = require("./recurring-cash-item");
13
+ const recurring_cash_item_service_1 = require("./recurring-cash-item-service");
14
+ const recurring_candidates_1 = require("./recurring-candidates");
15
+ const recurring_hidden_vendor_1 = require("./recurring-hidden-vendor");
16
+ const shiftMonth = (key, by) => {
17
+ const [year, month] = key.split('-').map(Number);
18
+ const index = year * 12 + (month - 1) + by;
19
+ return `${Math.floor(index / 12)}-${String((index % 12) + 1).padStart(2, '0')}`;
20
+ };
21
+ /**
22
+ * Whom the bank and card lines of the last twelve months show paid month after month that is no recurring item yet.
23
+ * A line on a subject outside profit and loss (a card bill, a tax, a transfer, a loan) pays no vendor, and a person
24
+ * (salary, expenses) is no vendor. With `hidden`, the ones a keeper hid instead.
25
+ */
26
+ async function recurringCandidatesOf(tx, domain, today, hidden = false) {
27
+ const from = `${shiftMonth(today.slice(0, 7), -12)}-01`;
28
+ const lines = await tx
29
+ .getRepository(transaction_1.Transaction)
30
+ .createQueryBuilder('line')
31
+ .leftJoinAndSelect('line.account', 'subject')
32
+ .where('line.domain = :domain', { domain: domain.id })
33
+ .andWhere('line.category IN (:...categories)', { categories: [transaction_1.TransactionCategory.CONFIRMED, transaction_1.TransactionCategory.CARD] })
34
+ .andWhere('line.type = :type', { type: cash_flow_type_1.CashFlowType.EXPENSE })
35
+ .andWhere('line.transactionDate >= :from', { from })
36
+ .getMany();
37
+ const items = await tx.getRepository(recurring_cash_item_1.RecurringCashItem).find({ where: { domain: { id: domain.id } } });
38
+ const hiddenKeys = new Set((await tx.getRepository(recurring_hidden_vendor_1.RecurringHiddenVendor).find({ where: { domain: { id: domain.id } } })).map(one => one.counterpartyId ?? `name:${one.nameKey}`));
39
+ const skip = new Set([...items.map(one => one.counterpartyId), ...(hidden ? [] : hiddenKeys)].filter(Boolean));
40
+ const parties = await tx.getRepository(biz_base_1.Counterparty).find({ where: { domain: { id: domain.id } }, select: ['id', 'name', 'aliases', 'kind'] });
41
+ const named = (0, biz_base_1.partyNamed)(parties);
42
+ const people = new Set(parties.filter(one => one.kind === biz_base_1.CounterpartyKind.PERSON).map(one => one.id));
43
+ /* Whom a line paid: its counterparty, else the one its written name is (the rule a line is linked by), else the name. */
44
+ const vendorOf = (line) => {
45
+ const id = line.counterpartyId ?? named(line.counterpartyName)?.id;
46
+ if (id)
47
+ return people.has(id) ? null : { key: id, counterpartyId: id };
48
+ const key = (0, biz_base_1.nameKey)(line.counterpartyName);
49
+ return key && !(0, biz_base_1.looksLikePersonName)(line.counterpartyName) ? { key: `name:${key}`, counterpartyId: null } : null;
50
+ };
51
+ const found = (0, recurring_candidates_1.candidatesOf)(lines
52
+ .filter(line => line.account?.profitAndLoss !== false)
53
+ .flatMap(line => {
54
+ const vendor = vendorOf(line);
55
+ return vendor ? [{ ...vendor, name: line.counterpartyName, transactionDate: line.transactionDate, amount: Number(line.amount), currency: line.currency, subjectId: line.account?.id ?? null }] : [];
56
+ }), skip).filter(one => hiddenKeys.has(one.key) === hidden);
57
+ return found.map(one => ({ ...one, counterpartyName: parties.find(party => party.id === one.counterpartyId)?.name ?? one.name ?? '', hidden }));
58
+ }
59
+ /**
60
+ * Make a recurring item of each candidate - money out, named after the vendor, on the subject and the day it was paid on
61
+ * most, from the month of its first line, its amount empty (it varies - expected at its latest months). A vendor the
62
+ * lines only name is registered as a counterparty first; the lines written with its name are linked to it. One that is
63
+ * no candidate any more is refused.
64
+ */
65
+ async function createRecurringItemsFromCandidates(tx, domain, user, keys, today) {
66
+ const candidates = await recurringCandidatesOf(tx, domain, today);
67
+ const made = [];
68
+ for (const key of [...new Set(keys)]) {
69
+ const one = candidates.find(candidate => candidate.key === key);
70
+ if (!one)
71
+ throw new shell_1.Refusal('recurring-candidate-not-found', {}, 'It is no candidate any more - reload and try again');
72
+ const counterpartyId = one.counterpartyId ?? (await (0, biz_base_1.saveCounterparties)(tx, domain, user, [{ cuFlag: '+', name: one.counterpartyName, kind: biz_base_1.CounterpartyKind.COMPANY }]))[0].id;
73
+ await (0, transaction_links_1.linkLinesByName)(tx, domain, user, [counterpartyId]);
74
+ const [item] = await (0, recurring_cash_item_service_1.saveRecurringCashItems)(tx, domain, user, [
75
+ {
76
+ cuFlag: '+',
77
+ name: one.counterpartyName,
78
+ type: cash_flow_type_1.CashFlowType.EXPENSE,
79
+ currency: one.currency,
80
+ counterparty: { id: counterpartyId },
81
+ account: one.subjectId ? { id: one.subjectId } : null,
82
+ dayOfMonth: one.dayOfMonth === 31 ? null : one.dayOfMonth,
83
+ lastDayOfMonth: one.dayOfMonth === 31,
84
+ startMonth: one.firstDate.slice(0, 7),
85
+ active: true
86
+ }
87
+ ]);
88
+ made.push(item);
89
+ }
90
+ return made;
91
+ }
92
+ /** Hide candidates - by their keys - or show them again. */
93
+ async function hideRecurringCandidates(tx, domain, user, keys, hide) {
94
+ const repo = tx.getRepository(recurring_hidden_vendor_1.RecurringHiddenVendor);
95
+ const wanted = [...new Set(keys)].filter(Boolean);
96
+ const names = wanted.filter(key => key.startsWith('name:')).map(key => key.slice(5));
97
+ const ids = wanted.filter(key => !key.startsWith('name:'));
98
+ const parties = ids.length ? await tx.getRepository(biz_base_1.Counterparty).find({ where: { domain: { id: domain.id }, id: (0, typeorm_1.In)(ids) } }) : [];
99
+ if (parties.length !== ids.length)
100
+ throw new shell_1.Refusal('recurring-counterparty-not-found', {}, 'The vendor was not found - reload and try again');
101
+ const rows = await repo.find({ where: { domain: { id: domain.id } } });
102
+ const held = (row) => (row.counterpartyId ? ids.includes(row.counterpartyId) : names.includes(row.nameKey));
103
+ if (!hide) {
104
+ const gone = rows.filter(held);
105
+ if (gone.length)
106
+ await repo.softRemove(gone);
107
+ return true;
108
+ }
109
+ for (const party of parties)
110
+ if (!rows.some(row => row.counterpartyId === party.id))
111
+ await repo.save({ domain, counterparty: party, creator: user, updater: user });
112
+ for (const key of names)
113
+ if (!rows.some(row => !row.counterpartyId && row.nameKey === key))
114
+ await repo.save({ domain, nameKey: key, creator: user, updater: user });
115
+ return true;
116
+ }
117
+ //# sourceMappingURL=recurring-candidate-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recurring-candidate-service.js","sourceRoot":"","sources":["../../../server/service/recurring-cash-item/recurring-candidate-service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Counterparty, CounterpartyKind, looksLikePersonName, nameKey, partyNamed, saveCounterparties } from '@things-factory/biz-base'\nimport { Refusal } from '@things-factory/shell'\nimport { EntityManager, In } from 'typeorm'\n\nimport { CashFlowType } from '../cash-flow-type'\nimport { Transaction, TransactionCategory } from '../transaction/transaction'\nimport { linkLinesByName } from '../transaction/transaction-links'\nimport { RecurringCashItem } from './recurring-cash-item'\nimport { saveRecurringCashItems } from './recurring-cash-item-service'\nimport { candidatesOf, CandidateFacts } from './recurring-candidates'\nimport { RecurringHiddenVendor } from './recurring-hidden-vendor'\n\n/* 장부에서 찾기 (ADR-0177 개정 1, 7-5) - read from the bank and card lines; an item made of one keeps its money. */\n\n/** A candidate with its vendor's name, for the list. */\nexport type RecurringCandidateRow = CandidateFacts & { counterpartyName: string; hidden: boolean }\n\nconst shiftMonth = (key: string, by: number) => {\n const [year, month] = key.split('-').map(Number)\n const index = year * 12 + (month - 1) + by\n return `${Math.floor(index / 12)}-${String((index % 12) + 1).padStart(2, '0')}`\n}\n\n/**\n * Whom the bank and card lines of the last twelve months show paid month after month that is no recurring item yet.\n * A line on a subject outside profit and loss (a card bill, a tax, a transfer, a loan) pays no vendor, and a person\n * (salary, expenses) is no vendor. With `hidden`, the ones a keeper hid instead.\n */\nexport async function recurringCandidatesOf(tx: EntityManager, domain: { id: string }, today: string, hidden = false): Promise<RecurringCandidateRow[]> {\n const from = `${shiftMonth(today.slice(0, 7), -12)}-01`\n const lines = await tx\n .getRepository(Transaction)\n .createQueryBuilder('line')\n .leftJoinAndSelect('line.account', 'subject')\n .where('line.domain = :domain', { domain: domain.id })\n .andWhere('line.category IN (:...categories)', { categories: [TransactionCategory.CONFIRMED, TransactionCategory.CARD] })\n .andWhere('line.type = :type', { type: CashFlowType.EXPENSE })\n .andWhere('line.transactionDate >= :from', { from })\n .getMany()\n const items = await tx.getRepository(RecurringCashItem).find({ where: { domain: { id: domain.id } } as any })\n const hiddenKeys = new Set((await tx.getRepository(RecurringHiddenVendor).find({ where: { domain: { id: domain.id } } as any })).map(one => one.counterpartyId ?? `name:${one.nameKey}`))\n const skip = new Set([...items.map(one => one.counterpartyId), ...(hidden ? [] : hiddenKeys)].filter(Boolean) as string[])\n const parties = await tx.getRepository(Counterparty).find({ where: { domain: { id: domain.id } } as any, select: ['id', 'name', 'aliases', 'kind'] })\n const named = partyNamed(parties)\n const people = new Set(parties.filter(one => one.kind === CounterpartyKind.PERSON).map(one => one.id))\n /* Whom a line paid: its counterparty, else the one its written name is (the rule a line is linked by), else the name. */\n const vendorOf = (line: Transaction) => {\n const id = line.counterpartyId ?? named(line.counterpartyName)?.id\n if (id) return people.has(id) ? null : { key: id, counterpartyId: id }\n const key = nameKey(line.counterpartyName)\n return key && !looksLikePersonName(line.counterpartyName!) ? { key: `name:${key}`, counterpartyId: null } : null\n }\n const found = candidatesOf(\n lines\n .filter(line => line.account?.profitAndLoss !== false)\n .flatMap(line => {\n const vendor = vendorOf(line)\n return vendor ? [{ ...vendor, name: line.counterpartyName, transactionDate: line.transactionDate!, amount: Number(line.amount), currency: line.currency, subjectId: line.account?.id ?? null }] : []\n }),\n skip\n ).filter(one => hiddenKeys.has(one.key) === hidden)\n return found.map(one => ({ ...one, counterpartyName: parties.find(party => party.id === one.counterpartyId)?.name ?? one.name ?? '', hidden }))\n}\n\n/**\n * Make a recurring item of each candidate - money out, named after the vendor, on the subject and the day it was paid on\n * most, from the month of its first line, its amount empty (it varies - expected at its latest months). A vendor the\n * lines only name is registered as a counterparty first; the lines written with its name are linked to it. One that is\n * no candidate any more is refused.\n */\nexport async function createRecurringItemsFromCandidates(tx: EntityManager, domain: { id: string }, user: any, keys: string[], today: string): Promise<RecurringCashItem[]> {\n const candidates = await recurringCandidatesOf(tx, domain, today)\n const made: RecurringCashItem[] = []\n for (const key of [...new Set(keys)]) {\n const one = candidates.find(candidate => candidate.key === key)\n if (!one) throw new Refusal('recurring-candidate-not-found', {}, 'It is no candidate any more - reload and try again')\n const counterpartyId = one.counterpartyId ?? (await saveCounterparties(tx, domain as any, user, [{ cuFlag: '+', name: one.counterpartyName, kind: CounterpartyKind.COMPANY }]))[0].id\n await linkLinesByName(tx, domain, user, [counterpartyId])\n const [item] = await saveRecurringCashItems(tx, domain, user, [\n {\n cuFlag: '+',\n name: one.counterpartyName,\n type: CashFlowType.EXPENSE,\n currency: one.currency,\n counterparty: { id: counterpartyId },\n account: one.subjectId ? { id: one.subjectId } : null,\n dayOfMonth: one.dayOfMonth === 31 ? null : one.dayOfMonth,\n lastDayOfMonth: one.dayOfMonth === 31,\n startMonth: one.firstDate.slice(0, 7),\n active: true\n } as any\n ])\n made.push(item)\n }\n return made\n}\n\n/** Hide candidates - by their keys - or show them again. */\nexport async function hideRecurringCandidates(tx: EntityManager, domain: { id: string }, user: any, keys: string[], hide: boolean): Promise<boolean> {\n const repo = tx.getRepository(RecurringHiddenVendor)\n const wanted = [...new Set(keys)].filter(Boolean)\n const names = wanted.filter(key => key.startsWith('name:')).map(key => key.slice(5))\n const ids = wanted.filter(key => !key.startsWith('name:'))\n const parties = ids.length ? await tx.getRepository(Counterparty).find({ where: { domain: { id: domain.id }, id: In(ids) } as any }) : []\n if (parties.length !== ids.length) throw new Refusal('recurring-counterparty-not-found', {}, 'The vendor was not found - reload and try again')\n const rows = await repo.find({ where: { domain: { id: domain.id } } as any })\n const held = (row: RecurringHiddenVendor) => (row.counterpartyId ? ids.includes(row.counterpartyId) : names.includes(row.nameKey!))\n if (!hide) {\n const gone = rows.filter(held)\n if (gone.length) await repo.softRemove(gone)\n return true\n }\n for (const party of parties) if (!rows.some(row => row.counterpartyId === party.id)) await repo.save({ domain, counterparty: party, creator: user, updater: user } as any)\n for (const key of names) if (!rows.some(row => !row.counterpartyId && row.nameKey === key)) await repo.save({ domain, nameKey: key, creator: user, updater: user } as any)\n return true\n}\n"]}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * A line of money out - a bank withdrawal or a card's charge - and whom it paid: its counterparty, or for a line no
3
+ * counterparty is linked to, the name written on it (`key` is the counterparty id, else `name:` and the name's key).
4
+ */
5
+ export interface VendorLine {
6
+ key: string;
7
+ counterpartyId?: string | null;
8
+ name?: string | null;
9
+ transactionDate: string;
10
+ amount: number;
11
+ currency?: string | null;
12
+ /** The account subject it is booked to. */
13
+ subjectId?: string | null;
14
+ }
15
+ export interface CandidateFacts {
16
+ key: string;
17
+ /** The counterparty paid; none when the lines only name it - a new item registers it. */
18
+ counterpartyId: string | null;
19
+ /** The name written most on the lines. */
20
+ name: string | null;
21
+ /** The months money went out in, of the window. */
22
+ months: number;
23
+ /** What went out a month, on average over those months. */
24
+ average: number;
25
+ /** The first line of the window - it is known to have started by then. */
26
+ firstDate: string;
27
+ lastDate: string;
28
+ lastAmount: number;
29
+ currency: string;
30
+ /** The account subject it is booked to most. */
31
+ subjectId: string | null;
32
+ /** The day of the month it went out on most; a month's last day is 31. */
33
+ dayOfMonth: number | null;
34
+ }
35
+ /** At least this many months of the window paid one vendor before it looks recurring. */
36
+ export declare const CANDIDATE_MIN_MONTHS = 3;
37
+ /**
38
+ * Whom the lines say is paid month after month - in at least `CANDIDATE_MIN_MONTHS` months, in the currency paid most -
39
+ * each with what a new item would start from. Those whose key is in `skip` (already an item, hidden) are not
40
+ * candidates. Largest first.
41
+ */
42
+ export declare function candidatesOf(lines: readonly VendorLine[], skip: ReadonlySet<string>): CandidateFacts[];
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ /*
3
+ * What the books already say goes out month after month and is no recurring item yet (ADR-0177 개정 1, moved here by
4
+ * 개정 7-5): whom the bank and card lines paid in at least three months of the window. Pure.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.CANDIDATE_MIN_MONTHS = void 0;
8
+ exports.candidatesOf = candidatesOf;
9
+ /** At least this many months of the window paid one vendor before it looks recurring. */
10
+ exports.CANDIDATE_MIN_MONTHS = 3;
11
+ const num = (value) => (value === null || value === undefined || value === '' ? 0 : Number(value) || 0);
12
+ const isLastDay = (day) => {
13
+ const [year, month, date] = day.split('-').map(Number);
14
+ return date === new Date(Date.UTC(year, month, 0)).getUTCDate();
15
+ };
16
+ const mostOf = (values) => {
17
+ const counts = new Map();
18
+ for (const value of values)
19
+ counts.set(value, (counts.get(value) ?? 0) + 1);
20
+ return [...counts].sort((a, b) => b[1] - a[1])[0]?.[0] ?? null;
21
+ };
22
+ /**
23
+ * Whom the lines say is paid month after month - in at least `CANDIDATE_MIN_MONTHS` months, in the currency paid most -
24
+ * each with what a new item would start from. Those whose key is in `skip` (already an item, hidden) are not
25
+ * candidates. Largest first.
26
+ */
27
+ function candidatesOf(lines, skip) {
28
+ const groups = new Map();
29
+ for (const line of lines)
30
+ if (line.key && !skip.has(line.key))
31
+ groups.set(line.key, [...(groups.get(line.key) ?? []), line]);
32
+ const out = [];
33
+ for (const [key, all] of groups) {
34
+ const currency = mostOf(all.map(line => line.currency || 'KRW'));
35
+ const paid = all.filter(line => (line.currency || 'KRW') === currency).sort((a, b) => a.transactionDate.localeCompare(b.transactionDate));
36
+ const months = new Set(paid.map(line => line.transactionDate.slice(0, 7)));
37
+ if (months.size < exports.CANDIDATE_MIN_MONTHS)
38
+ continue;
39
+ const last = paid[paid.length - 1];
40
+ out.push({
41
+ key,
42
+ counterpartyId: all[0].counterpartyId ?? null,
43
+ name: mostOf(paid.map(line => line.name?.trim() || null).filter(Boolean)),
44
+ months: months.size,
45
+ average: Math.round(paid.reduce((sum, line) => sum + num(line.amount), 0) / months.size),
46
+ firstDate: paid[0].transactionDate,
47
+ lastDate: last.transactionDate,
48
+ lastAmount: num(last.amount),
49
+ currency,
50
+ subjectId: mostOf(paid.map(line => line.subjectId ?? null)),
51
+ /* A month's last day is 31 - the day a short month clamps to. */
52
+ dayOfMonth: mostOf(paid.map(line => (isLastDay(line.transactionDate) ? 31 : Number(line.transactionDate.slice(8, 10)))))
53
+ });
54
+ }
55
+ return out.sort((a, b) => b.average - a.average);
56
+ }
57
+ //# sourceMappingURL=recurring-candidates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recurring-candidates.js","sourceRoot":"","sources":["../../../server/service/recurring-cash-item/recurring-candidates.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * What the books already say goes out month after month and is no recurring item yet (ADR-0177 개정 1, moved here by\n * 개정 7-5): whom the bank and card lines paid in at least three months of the window. Pure.\n */\n\n/**\n * A line of money out - a bank withdrawal or a card's charge - and whom it paid: its counterparty, or for a line no\n * counterparty is linked to, the name written on it (`key` is the counterparty id, else `name:` and the name's key).\n */\nexport interface VendorLine {\n key: string\n counterpartyId?: string | null\n name?: string | null\n transactionDate: string\n amount: number\n currency?: string | null\n /** The account subject it is booked to. */\n subjectId?: string | null\n}\n\nexport interface CandidateFacts {\n key: string\n /** The counterparty paid; none when the lines only name it - a new item registers it. */\n counterpartyId: string | null\n /** The name written most on the lines. */\n name: string | null\n /** The months money went out in, of the window. */\n months: number\n /** What went out a month, on average over those months. */\n average: number\n /** The first line of the window - it is known to have started by then. */\n firstDate: string\n lastDate: string\n lastAmount: number\n currency: string\n /** The account subject it is booked to most. */\n subjectId: string | null\n /** The day of the month it went out on most; a month's last day is 31. */\n dayOfMonth: number | null\n}\n\n/** At least this many months of the window paid one vendor before it looks recurring. */\nexport const CANDIDATE_MIN_MONTHS = 3\n\nconst num = (value: any) => (value === null || value === undefined || value === '' ? 0 : Number(value) || 0)\n\nconst isLastDay = (day: string) => {\n const [year, month, date] = day.split('-').map(Number)\n return date === new Date(Date.UTC(year, month, 0)).getUTCDate()\n}\n\nconst mostOf = <T>(values: T[]): T | null => {\n const counts = new Map<T, number>()\n for (const value of values) counts.set(value, (counts.get(value) ?? 0) + 1)\n return [...counts].sort((a, b) => b[1] - a[1])[0]?.[0] ?? null\n}\n\n/**\n * Whom the lines say is paid month after month - in at least `CANDIDATE_MIN_MONTHS` months, in the currency paid most -\n * each with what a new item would start from. Those whose key is in `skip` (already an item, hidden) are not\n * candidates. Largest first.\n */\nexport function candidatesOf(lines: readonly VendorLine[], skip: ReadonlySet<string>): CandidateFacts[] {\n const groups = new Map<string, VendorLine[]>()\n for (const line of lines) if (line.key && !skip.has(line.key)) groups.set(line.key, [...(groups.get(line.key) ?? []), line])\n const out: CandidateFacts[] = []\n for (const [key, all] of groups) {\n const currency = mostOf(all.map(line => line.currency || 'KRW'))!\n const paid = all.filter(line => (line.currency || 'KRW') === currency).sort((a, b) => a.transactionDate.localeCompare(b.transactionDate))\n const months = new Set(paid.map(line => line.transactionDate.slice(0, 7)))\n if (months.size < CANDIDATE_MIN_MONTHS) continue\n const last = paid[paid.length - 1]\n out.push({\n key,\n counterpartyId: all[0].counterpartyId ?? null,\n name: mostOf(paid.map(line => line.name?.trim() || null).filter(Boolean)),\n months: months.size,\n average: Math.round(paid.reduce((sum, line) => sum + num(line.amount), 0) / months.size),\n firstDate: paid[0].transactionDate,\n lastDate: last.transactionDate,\n lastAmount: num(last.amount),\n currency,\n subjectId: mostOf(paid.map(line => line.subjectId ?? null)),\n /* A month's last day is 31 - the day a short month clamps to. */\n dayOfMonth: mostOf(paid.map(line => (isLastDay(line.transactionDate) ? 31 : Number(line.transactionDate.slice(8, 10)))))\n })\n }\n return out.sort((a, b) => b.average - a.average)\n}\n"]}
@@ -3,4 +3,6 @@ import { RecurringCashItemPatch } from './recurring-cash-item-type';
3
3
  export declare class RecurringCashItemMutation {
4
4
  updateMultipleRecurringCashItem(patches: RecurringCashItemPatch[], context: ResolverContext): Promise<RecurringCashItem[]>;
5
5
  deleteRecurringCashItems(ids: string[], context: ResolverContext): Promise<boolean>;
6
+ createRecurringCashItemsFromCandidates(keys: string[], context: ResolverContext): Promise<RecurringCashItem[]>;
7
+ hideRecurringCandidates(keys: string[], hide: boolean, context: ResolverContext): Promise<boolean>;
6
8
  }
@@ -3,10 +3,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RecurringCashItemMutation = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const type_graphql_1 = require("type-graphql");
6
+ const auth_base_1 = require("@things-factory/auth-base");
6
7
  const shell_1 = require("@things-factory/shell");
7
8
  const recurring_cash_item_1 = require("./recurring-cash-item");
9
+ const recurring_candidate_service_1 = require("./recurring-candidate-service");
8
10
  const recurring_cash_item_service_1 = require("./recurring-cash-item-service");
9
11
  const recurring_cash_item_type_1 = require("./recurring-cash-item-type");
12
+ /** The candidates are the bank's fact (ADR-0139) - made into items only by whoever reads bank lines. */
13
+ async function mustReadBank(state) {
14
+ const { domain, user, unsafeIP, prohibitedPrivileges } = state;
15
+ if (!(await (0, auth_base_1.checkPermission)({ category: 'bank', privilege: 'query', owner: false }, user, domain, unsafeIP, prohibitedPrivileges)))
16
+ throw new shell_1.Refusal('recurring-candidates-need-bank', {}, 'Making items from the books needs reading the bank lines');
17
+ }
10
18
  let RecurringCashItemMutation = class RecurringCashItemMutation {
11
19
  async updateMultipleRecurringCashItem(patches, context) {
12
20
  const { domain, user, tx } = context.state;
@@ -17,6 +25,15 @@ let RecurringCashItemMutation = class RecurringCashItemMutation {
17
25
  await (0, recurring_cash_item_service_1.saveRecurringCashItems)(tx, domain, user, ids.map(id => ({ id, cuFlag: '-' })));
18
26
  return true;
19
27
  }
28
+ async createRecurringCashItemsFromCandidates(keys, context) {
29
+ const { domain, user, tx } = context.state;
30
+ await mustReadBank(context.state);
31
+ return (0, recurring_candidate_service_1.createRecurringItemsFromCandidates)(tx, domain, user, keys, new Date().toISOString().slice(0, 10));
32
+ }
33
+ async hideRecurringCandidates(keys, hide, context) {
34
+ const { domain, user, tx } = context.state;
35
+ return (0, recurring_candidate_service_1.hideRecurringCandidates)(tx, domain, user, keys, hide);
36
+ }
20
37
  };
21
38
  exports.RecurringCashItemMutation = RecurringCashItemMutation;
22
39
  tslib_1.__decorate([
@@ -39,6 +56,27 @@ tslib_1.__decorate([
39
56
  tslib_1.__metadata("design:paramtypes", [Array, Object]),
40
57
  tslib_1.__metadata("design:returntype", Promise)
41
58
  ], RecurringCashItemMutation.prototype, "deleteRecurringCashItems", null);
59
+ tslib_1.__decorate([
60
+ (0, type_graphql_1.Directive)('@transaction'),
61
+ (0, type_graphql_1.Directive)('@privilege(category: "accounting", privilege: "mutation", domainOwnerGranted: true)'),
62
+ (0, type_graphql_1.Mutation)(returns => [recurring_cash_item_1.RecurringCashItem], { description: 'To make a recurring item of each candidate (by its key), its amount empty' }),
63
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('keys', type => [String])),
64
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
65
+ tslib_1.__metadata("design:type", Function),
66
+ tslib_1.__metadata("design:paramtypes", [Array, Object]),
67
+ tslib_1.__metadata("design:returntype", Promise)
68
+ ], RecurringCashItemMutation.prototype, "createRecurringCashItemsFromCandidates", null);
69
+ tslib_1.__decorate([
70
+ (0, type_graphql_1.Directive)('@transaction'),
71
+ (0, type_graphql_1.Directive)('@privilege(category: "accounting", privilege: "mutation", domainOwnerGranted: true)'),
72
+ (0, type_graphql_1.Mutation)(returns => Boolean, { description: 'To hide candidates (by their keys), or with hide false to show them again' }),
73
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('keys', type => [String])),
74
+ tslib_1.__param(1, (0, type_graphql_1.Arg)('hide')),
75
+ tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
76
+ tslib_1.__metadata("design:type", Function),
77
+ tslib_1.__metadata("design:paramtypes", [Array, Boolean, Object]),
78
+ tslib_1.__metadata("design:returntype", Promise)
79
+ ], RecurringCashItemMutation.prototype, "hideRecurringCandidates", null);
42
80
  exports.RecurringCashItemMutation = RecurringCashItemMutation = tslib_1.__decorate([
43
81
  (0, type_graphql_1.Resolver)(recurring_cash_item_1.RecurringCashItem),
44
82
  (0, type_graphql_1.UseMiddleware)(shell_1.SpeakRefusals)
@@ -1 +1 @@
1
- {"version":3,"file":"recurring-cash-item-mutation.js","sourceRoot":"","sources":["../../../server/service/recurring-cash-item/recurring-cash-item-mutation.ts"],"names":[],"mappings":";;;;AAAA,+CAAqF;AAErF,iDAAqD;AAErD,+DAAyD;AACzD,+EAAsE;AACtE,yEAAmE;AAI5D,IAAM,yBAAyB,GAA/B,MAAM,yBAAyB;IAI9B,AAAN,KAAK,CAAC,+BAA+B,CACe,OAAiC,EAC5E,OAAwB;QAE/B,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAE1C,OAAO,MAAM,IAAA,oDAAsB,EAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;IAChE,CAAC;IAKK,AAAN,KAAK,CAAC,wBAAwB,CACE,GAAa,EACpC,OAAwB;QAE/B,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAC1C,MAAM,IAAA,oDAAsB,EAC1B,EAAE,EACF,MAAM,EACN,IAAI,EACJ,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CACrC,CAAA;QAED,OAAO,IAAI,CAAA;IACb,CAAC;CACF,CAAA;AA9BY,8DAAyB;AAI9B;IAHL,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,wBAAS,EAAC,qFAAqF,CAAC;IAChG,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,CAAC,uCAAiB,CAAC,EAAE,EAAE,WAAW,EAAE,uDAAuD,EAAE,CAAC;IAEhH,mBAAA,IAAA,kBAAG,EAAC,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,iDAAsB,CAAC,CAAC,CAAA;IAChD,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;gFAKP;AAKK;IAHL,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,wBAAS,EAAC,qFAAqF,CAAC;IAChG,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,uCAAuC,EAAE,CAAC;IAEpF,mBAAA,IAAA,kBAAG,EAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;IAC5B,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;yEAWP;oCA7BU,yBAAyB;IAFrC,IAAA,uBAAQ,EAAC,uCAAiB,CAAC;IAC3B,IAAA,4BAAa,EAAC,qBAAa,CAAC;GAChB,yBAAyB,CA8BrC","sourcesContent":["import { Resolver, Mutation, Arg, Ctx, Directive, UseMiddleware } from 'type-graphql'\n\nimport { SpeakRefusals } from '@things-factory/shell'\n\nimport { RecurringCashItem } from './recurring-cash-item'\nimport { saveRecurringCashItems } from './recurring-cash-item-service'\nimport { RecurringCashItemPatch } from './recurring-cash-item-type'\n\n@Resolver(RecurringCashItem)\n@UseMiddleware(SpeakRefusals)\nexport class RecurringCashItemMutation {\n @Directive('@transaction')\n @Directive('@privilege(category: \"accounting\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => [RecurringCashItem], { description: 'To add, modify and delete multiple RecurringCashItems' })\n async updateMultipleRecurringCashItem(\n @Arg('patches', type => [RecurringCashItemPatch]) patches: RecurringCashItemPatch[],\n @Ctx() context: ResolverContext\n ): Promise<RecurringCashItem[]> {\n const { domain, user, tx } = context.state\n\n return await saveRecurringCashItems(tx, domain, user, patches)\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"accounting\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => Boolean, { description: 'To delete multiple RecurringCashItems' })\n async deleteRecurringCashItems(\n @Arg('ids', type => [String]) ids: string[],\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, user, tx } = context.state\n await saveRecurringCashItems(\n tx,\n domain,\n user,\n ids.map(id => ({ id, cuFlag: '-' }))\n )\n\n return true\n }\n}\n"]}
1
+ {"version":3,"file":"recurring-cash-item-mutation.js","sourceRoot":"","sources":["../../../server/service/recurring-cash-item/recurring-cash-item-mutation.ts"],"names":[],"mappings":"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","sourcesContent":["import { Resolver, Mutation, Arg, Ctx, Directive, UseMiddleware } from 'type-graphql'\n\nimport { checkPermission } from '@things-factory/auth-base'\nimport { Refusal, SpeakRefusals } from '@things-factory/shell'\n\nimport { RecurringCashItem } from './recurring-cash-item'\nimport { createRecurringItemsFromCandidates, hideRecurringCandidates } from './recurring-candidate-service'\nimport { saveRecurringCashItems } from './recurring-cash-item-service'\nimport { RecurringCashItemPatch } from './recurring-cash-item-type'\n\n/** The candidates are the bank's fact (ADR-0139) - made into items only by whoever reads bank lines. */\nasync function mustReadBank(state: any) {\n const { domain, user, unsafeIP, prohibitedPrivileges } = state\n if (!(await checkPermission({ category: 'bank', privilege: 'query', owner: false } as any, user, domain, unsafeIP, prohibitedPrivileges)))\n throw new Refusal('recurring-candidates-need-bank', {}, 'Making items from the books needs reading the bank lines')\n}\n\n@Resolver(RecurringCashItem)\n@UseMiddleware(SpeakRefusals)\nexport class RecurringCashItemMutation {\n @Directive('@transaction')\n @Directive('@privilege(category: \"accounting\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => [RecurringCashItem], { description: 'To add, modify and delete multiple RecurringCashItems' })\n async updateMultipleRecurringCashItem(\n @Arg('patches', type => [RecurringCashItemPatch]) patches: RecurringCashItemPatch[],\n @Ctx() context: ResolverContext\n ): Promise<RecurringCashItem[]> {\n const { domain, user, tx } = context.state\n\n return await saveRecurringCashItems(tx, domain, user, patches)\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"accounting\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => Boolean, { description: 'To delete multiple RecurringCashItems' })\n async deleteRecurringCashItems(\n @Arg('ids', type => [String]) ids: string[],\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, user, tx } = context.state\n await saveRecurringCashItems(\n tx,\n domain,\n user,\n ids.map(id => ({ id, cuFlag: '-' }))\n )\n\n return true\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"accounting\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => [RecurringCashItem], { description: 'To make a recurring item of each candidate (by its key), its amount empty' })\n async createRecurringCashItemsFromCandidates(@Arg('keys', type => [String]) keys: string[], @Ctx() context: ResolverContext): Promise<RecurringCashItem[]> {\n const { domain, user, tx } = context.state\n await mustReadBank(context.state)\n return createRecurringItemsFromCandidates(tx, domain, user, keys, new Date().toISOString().slice(0, 10))\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"accounting\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => Boolean, { description: 'To hide candidates (by their keys), or with hide false to show them again' })\n async hideRecurringCandidates(@Arg('keys', type => [String]) keys: string[], @Arg('hide') hide: boolean, @Ctx() context: ResolverContext): Promise<boolean> {\n const { domain, user, tx } = context.state\n return hideRecurringCandidates(tx, domain, user, keys, hide)\n }\n}\n"]}
@@ -4,9 +4,10 @@ import { Counterparty } from '@things-factory/biz-base';
4
4
  import { FactChange } from '@things-factory/fact-change';
5
5
  import { Account } from '../account/account';
6
6
  import { RecurringCashItem } from './recurring-cash-item';
7
- import { RecurringCashItemList } from './recurring-cash-item-type';
7
+ import { RecurringCandidate, RecurringCashItemList } from './recurring-cash-item-type';
8
8
  export declare class RecurringCashItemQuery {
9
9
  recurringCashItem(id: string, context: ResolverContext): Promise<RecurringCashItem | null>;
10
+ recurringCandidates(hidden: boolean, context: ResolverContext): Promise<RecurringCandidate[]>;
10
11
  recurringCashItems(params: ListParam, context: ResolverContext): Promise<RecurringCashItemList>;
11
12
  recurringCashItemChanges(id: string, context: ResolverContext): Promise<FactChange[]>;
12
13
  account(item: RecurringCashItem): Promise<Account | null>;
@@ -11,11 +11,16 @@ const account_1 = require("../account/account");
11
11
  const recurring_cash_item_1 = require("./recurring-cash-item");
12
12
  const recurring_cash_item_type_1 = require("./recurring-cash-item-type");
13
13
  const recurring_cash_item_service_1 = require("./recurring-cash-item-service");
14
+ const recurring_candidate_service_1 = require("./recurring-candidate-service");
14
15
  let RecurringCashItemQuery = class RecurringCashItemQuery {
15
16
  async recurringCashItem(id, context) {
16
17
  const { domain } = context.state;
17
18
  return await (0, shell_1.getRepository)(recurring_cash_item_1.RecurringCashItem).findOne({ where: { domain: { id: domain.id }, id } });
18
19
  }
20
+ /* Read from the bank and card lines (ADR-0139): the bank's door. */
21
+ async recurringCandidates(hidden, context) {
22
+ return (0, recurring_candidate_service_1.recurringCandidatesOf)((0, shell_1.getRepository)(recurring_cash_item_1.RecurringCashItem).manager, context.state.domain, new Date().toISOString().slice(0, 10), !!hidden);
23
+ }
19
24
  async recurringCashItems(params, context) {
20
25
  const { domain } = context.state;
21
26
  const queryBuilder = (0, shell_1.getQueryBuilderFromListParams)({
@@ -56,6 +61,15 @@ tslib_1.__decorate([
56
61
  tslib_1.__metadata("design:paramtypes", [String, Object]),
57
62
  tslib_1.__metadata("design:returntype", Promise)
58
63
  ], RecurringCashItemQuery.prototype, "recurringCashItem", null);
64
+ tslib_1.__decorate([
65
+ (0, type_graphql_1.Directive)('@privilege(category: "bank", privilege: "query", domainOwnerGranted: false)'),
66
+ (0, type_graphql_1.Query)(returns => [recurring_cash_item_type_1.RecurringCandidate], { description: 'The vendors the bank and card lines show paid month after month that are no recurring item yet; with hidden, the ones hidden' }),
67
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('hidden', { nullable: true })),
68
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
69
+ tslib_1.__metadata("design:type", Function),
70
+ tslib_1.__metadata("design:paramtypes", [Boolean, Object]),
71
+ tslib_1.__metadata("design:returntype", Promise)
72
+ ], RecurringCashItemQuery.prototype, "recurringCandidates", null);
59
73
  tslib_1.__decorate([
60
74
  (0, type_graphql_1.Directive)('@privilege(category: "accounting", privilege: "query", domainOwnerGranted: true)'),
61
75
  (0, type_graphql_1.Query)(returns => recurring_cash_item_type_1.RecurringCashItemList, { description: 'To fetch multiple RecurringCashItems' }),
@@ -1 +1 @@
1
- {"version":3,"file":"recurring-cash-item-query.js","sourceRoot":"","sources":["../../../server/service/recurring-cash-item/recurring-cash-item-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { Resolver, Query, FieldResolver, Root, Args, Arg, Ctx, Directive } from 'type-graphql'\n\nimport { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'\nimport { User } from '@things-factory/auth-base'\nimport { Counterparty } from '@things-factory/biz-base'\nimport { FactChange } from '@things-factory/fact-change'\n\nimport { Account } from '../account/account'\nimport { RecurringCashItem } from './recurring-cash-item'\nimport { RecurringCashItemList } from './recurring-cash-item-type'\nimport { recurringCashItemChanges } from './recurring-cash-item-service'\n\n@Resolver(RecurringCashItem)\nexport class RecurringCashItemQuery {\n @Directive('@privilege(category: \"accounting\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => RecurringCashItem, { nullable: true, description: 'To fetch a RecurringCashItem' })\n async recurringCashItem(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<RecurringCashItem | null> {\n const { domain } = context.state\n\n return await getRepository(RecurringCashItem).findOne({ where: { domain: { id: domain.id }, id } })\n }\n\n @Directive('@privilege(category: \"accounting\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => RecurringCashItemList, { description: 'To fetch multiple RecurringCashItems' })\n async recurringCashItems(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<RecurringCashItemList> {\n const { domain } = context.state\n const queryBuilder = getQueryBuilderFromListParams({\n domain,\n params,\n repository: getRepository(RecurringCashItem),\n searchables: ['name', 'notes']\n })\n const [items, total] = await queryBuilder.getManyAndCount()\n\n return { items, total }\n }\n\n @Directive('@privilege(category: \"accounting\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => [FactChange], { description: 'What moved on a recurring item, field by field, newest first (its 360)' })\n async recurringCashItemChanges(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<FactChange[]> {\n return recurringCashItemChanges(getRepository(RecurringCashItem).manager, context.state.domain, id)\n }\n\n @FieldResolver(type => Account, { nullable: true })\n async account(@Root() item: RecurringCashItem): Promise<Account | null> {\n return item.accountId ? await getRepository(Account).findOneBy({ id: item.accountId }) : null\n }\n\n @FieldResolver(type => Counterparty, { nullable: true })\n async counterparty(@Root() item: RecurringCashItem): Promise<Counterparty | null> {\n return item.counterpartyId ? await getRepository(Counterparty).findOneBy({ id: item.counterpartyId }) : null\n }\n\n @FieldResolver(type => Domain)\n async domain(@Root() item: RecurringCashItem): Promise<Domain> {\n return await getRepository(Domain).findOneBy({ id: item.domainId })\n }\n\n @FieldResolver(type => User, { nullable: true })\n async creator(@Root() item: RecurringCashItem): Promise<User | null> {\n return item.creatorId ? await getRepository(User).findOneBy({ id: item.creatorId }) : null\n }\n\n @FieldResolver(type => User, { nullable: true })\n async updater(@Root() item: RecurringCashItem): Promise<User | null> {\n return item.updaterId ? await getRepository(User).findOneBy({ id: item.updaterId }) : null\n }\n}\n"]}
1
+ {"version":3,"file":"recurring-cash-item-query.js","sourceRoot":"","sources":["../../../server/service/recurring-cash-item/recurring-cash-item-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { Resolver, Query, FieldResolver, Root, Args, Arg, Ctx, Directive } from 'type-graphql'\n\nimport { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'\nimport { User } from '@things-factory/auth-base'\nimport { Counterparty } from '@things-factory/biz-base'\nimport { FactChange } from '@things-factory/fact-change'\n\nimport { Account } from '../account/account'\nimport { RecurringCashItem } from './recurring-cash-item'\nimport { RecurringCandidate, RecurringCashItemList } from './recurring-cash-item-type'\nimport { recurringCashItemChanges } from './recurring-cash-item-service'\nimport { recurringCandidatesOf } from './recurring-candidate-service'\n\n@Resolver(RecurringCashItem)\nexport class RecurringCashItemQuery {\n @Directive('@privilege(category: \"accounting\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => RecurringCashItem, { nullable: true, description: 'To fetch a RecurringCashItem' })\n async recurringCashItem(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<RecurringCashItem | null> {\n const { domain } = context.state\n\n return await getRepository(RecurringCashItem).findOne({ where: { domain: { id: domain.id }, id } })\n }\n\n /* Read from the bank and card lines (ADR-0139): the bank's door. */\n @Directive('@privilege(category: \"bank\", privilege: \"query\", domainOwnerGranted: false)')\n @Query(returns => [RecurringCandidate], { description: 'The vendors the bank and card lines show paid month after month that are no recurring item yet; with hidden, the ones hidden' })\n async recurringCandidates(@Arg('hidden', { nullable: true }) hidden: boolean, @Ctx() context: ResolverContext): Promise<RecurringCandidate[]> {\n return recurringCandidatesOf(getRepository(RecurringCashItem).manager, context.state.domain, new Date().toISOString().slice(0, 10), !!hidden) as any\n }\n\n @Directive('@privilege(category: \"accounting\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => RecurringCashItemList, { description: 'To fetch multiple RecurringCashItems' })\n async recurringCashItems(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<RecurringCashItemList> {\n const { domain } = context.state\n const queryBuilder = getQueryBuilderFromListParams({\n domain,\n params,\n repository: getRepository(RecurringCashItem),\n searchables: ['name', 'notes']\n })\n const [items, total] = await queryBuilder.getManyAndCount()\n\n return { items, total }\n }\n\n @Directive('@privilege(category: \"accounting\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => [FactChange], { description: 'What moved on a recurring item, field by field, newest first (its 360)' })\n async recurringCashItemChanges(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<FactChange[]> {\n return recurringCashItemChanges(getRepository(RecurringCashItem).manager, context.state.domain, id)\n }\n\n @FieldResolver(type => Account, { nullable: true })\n async account(@Root() item: RecurringCashItem): Promise<Account | null> {\n return item.accountId ? await getRepository(Account).findOneBy({ id: item.accountId }) : null\n }\n\n @FieldResolver(type => Counterparty, { nullable: true })\n async counterparty(@Root() item: RecurringCashItem): Promise<Counterparty | null> {\n return item.counterpartyId ? await getRepository(Counterparty).findOneBy({ id: item.counterpartyId }) : null\n }\n\n @FieldResolver(type => Domain)\n async domain(@Root() item: RecurringCashItem): Promise<Domain> {\n return await getRepository(Domain).findOneBy({ id: item.domainId })\n }\n\n @FieldResolver(type => User, { nullable: true })\n async creator(@Root() item: RecurringCashItem): Promise<User | null> {\n return item.creatorId ? await getRepository(User).findOneBy({ id: item.creatorId }) : null\n }\n\n @FieldResolver(type => User, { nullable: true })\n async updater(@Root() item: RecurringCashItem): Promise<User | null> {\n return item.updaterId ? await getRepository(User).findOneBy({ id: item.updaterId }) : null\n }\n}\n"]}