@tasenor/common-node 1.9.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +4 -0
- package/LICENSE +21 -0
- package/dist/tasenor-common-node/src/cli.d.ts +81 -0
- package/dist/tasenor-common-node/src/cli.js +242 -0
- package/dist/tasenor-common-node/src/cli.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/account.d.ts +12 -0
- package/dist/tasenor-common-node/src/commands/account.js +58 -0
- package/dist/tasenor-common-node/src/commands/account.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/balance.d.ts +11 -0
- package/dist/tasenor-common-node/src/commands/balance.js +117 -0
- package/dist/tasenor-common-node/src/commands/balance.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/db.d.ts +14 -0
- package/dist/tasenor-common-node/src/commands/db.js +69 -0
- package/dist/tasenor-common-node/src/commands/db.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/entry.d.ts +13 -0
- package/dist/tasenor-common-node/src/commands/entry.js +106 -0
- package/dist/tasenor-common-node/src/commands/entry.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/import.d.ts +17 -0
- package/dist/tasenor-common-node/src/commands/import.js +140 -0
- package/dist/tasenor-common-node/src/commands/import.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/importer.d.ts +13 -0
- package/dist/tasenor-common-node/src/commands/importer.js +71 -0
- package/dist/tasenor-common-node/src/commands/importer.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/index.d.ts +191 -0
- package/dist/tasenor-common-node/src/commands/index.js +482 -0
- package/dist/tasenor-common-node/src/commands/index.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/period.d.ts +12 -0
- package/dist/tasenor-common-node/src/commands/period.js +48 -0
- package/dist/tasenor-common-node/src/commands/period.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/plugin.d.ts +15 -0
- package/dist/tasenor-common-node/src/commands/plugin.js +78 -0
- package/dist/tasenor-common-node/src/commands/plugin.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/report.d.ts +11 -0
- package/dist/tasenor-common-node/src/commands/report.js +96 -0
- package/dist/tasenor-common-node/src/commands/report.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/settings.d.ts +10 -0
- package/dist/tasenor-common-node/src/commands/settings.js +64 -0
- package/dist/tasenor-common-node/src/commands/settings.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/stock.d.ts +8 -0
- package/dist/tasenor-common-node/src/commands/stock.js +73 -0
- package/dist/tasenor-common-node/src/commands/stock.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/tag.d.ts +13 -0
- package/dist/tasenor-common-node/src/commands/tag.js +89 -0
- package/dist/tasenor-common-node/src/commands/tag.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/tx.d.ts +12 -0
- package/dist/tasenor-common-node/src/commands/tx.js +81 -0
- package/dist/tasenor-common-node/src/commands/tx.js.map +1 -0
- package/dist/tasenor-common-node/src/commands/user.d.ts +12 -0
- package/dist/tasenor-common-node/src/commands/user.js +52 -0
- package/dist/tasenor-common-node/src/commands/user.js.map +1 -0
- package/dist/tasenor-common-node/src/database/BookkeeperImporter.d.ts +77 -0
- package/dist/tasenor-common-node/src/database/BookkeeperImporter.js +343 -0
- package/dist/tasenor-common-node/src/database/BookkeeperImporter.js.map +1 -0
- package/dist/tasenor-common-node/src/database/DB.d.ts +51 -0
- package/dist/tasenor-common-node/src/database/DB.js +354 -0
- package/dist/tasenor-common-node/src/database/DB.js.map +1 -0
- package/dist/tasenor-common-node/src/database/index.d.ts +7 -0
- package/dist/tasenor-common-node/src/database/index.js +8 -0
- package/dist/tasenor-common-node/src/database/index.js.map +1 -0
- package/dist/tasenor-common-node/src/doccer.d.ts +29 -0
- package/dist/tasenor-common-node/src/doccer.js +30 -0
- package/dist/tasenor-common-node/src/doccer.js.map +1 -0
- package/dist/tasenor-common-node/src/error.d.ts +30 -0
- package/dist/tasenor-common-node/src/error.js +35 -0
- package/dist/tasenor-common-node/src/error.js.map +1 -0
- package/dist/tasenor-common-node/src/export/Exporter.d.ts +69 -0
- package/dist/tasenor-common-node/src/export/Exporter.js +123 -0
- package/dist/tasenor-common-node/src/export/Exporter.js.map +1 -0
- package/dist/tasenor-common-node/src/export/TasenorExporter.d.ts +55 -0
- package/dist/tasenor-common-node/src/export/TasenorExporter.js +135 -0
- package/dist/tasenor-common-node/src/export/TasenorExporter.js.map +1 -0
- package/dist/tasenor-common-node/src/export/TilitinExporter.d.ts +71 -0
- package/dist/tasenor-common-node/src/export/TilitinExporter.js +290 -0
- package/dist/tasenor-common-node/src/export/TilitinExporter.js.map +1 -0
- package/dist/tasenor-common-node/src/export/index.d.ts +8 -0
- package/dist/tasenor-common-node/src/export/index.js +9 -0
- package/dist/tasenor-common-node/src/export/index.js.map +1 -0
- package/dist/tasenor-common-node/src/import/TextFileProcessHandler.d.ts +104 -0
- package/dist/tasenor-common-node/src/import/TextFileProcessHandler.js +354 -0
- package/dist/tasenor-common-node/src/import/TextFileProcessHandler.js.map +1 -0
- package/dist/tasenor-common-node/src/import/TransactionImportConnector.d.ts +38 -0
- package/dist/tasenor-common-node/src/import/TransactionImportConnector.js +27 -0
- package/dist/tasenor-common-node/src/import/TransactionImportConnector.js.map +1 -0
- package/dist/tasenor-common-node/src/import/TransactionImportHandler.d.ts +173 -0
- package/dist/tasenor-common-node/src/import/TransactionImportHandler.js +733 -0
- package/dist/tasenor-common-node/src/import/TransactionImportHandler.js.map +1 -0
- package/dist/tasenor-common-node/src/import/TransactionRules.d.ts +238 -0
- package/dist/tasenor-common-node/src/import/TransactionRules.js +522 -0
- package/dist/tasenor-common-node/src/import/TransactionRules.js.map +1 -0
- package/dist/tasenor-common-node/src/import/TransactionUI.d.ts +181 -0
- package/dist/tasenor-common-node/src/import/TransactionUI.js +482 -0
- package/dist/tasenor-common-node/src/import/TransactionUI.js.map +1 -0
- package/dist/tasenor-common-node/src/import/TransferAnalyzer.d.ts +324 -0
- package/dist/tasenor-common-node/src/import/TransferAnalyzer.js +1379 -0
- package/dist/tasenor-common-node/src/import/TransferAnalyzer.js.map +1 -0
- package/dist/tasenor-common-node/src/import/index.d.ts +11 -0
- package/dist/tasenor-common-node/src/import/index.js +12 -0
- package/dist/tasenor-common-node/src/import/index.js.map +1 -0
- package/dist/tasenor-common-node/src/index.d.ts +12 -0
- package/dist/tasenor-common-node/src/index.js +13 -0
- package/dist/tasenor-common-node/src/index.js.map +1 -0
- package/dist/tasenor-common-node/src/net/crypto.d.ts +33 -0
- package/dist/tasenor-common-node/src/net/crypto.js +63 -0
- package/dist/tasenor-common-node/src/net/crypto.js.map +1 -0
- package/dist/tasenor-common-node/src/net/git.d.ts +49 -0
- package/dist/tasenor-common-node/src/net/git.js +137 -0
- package/dist/tasenor-common-node/src/net/git.js.map +1 -0
- package/dist/tasenor-common-node/src/net/index.d.ts +10 -0
- package/dist/tasenor-common-node/src/net/index.js +11 -0
- package/dist/tasenor-common-node/src/net/index.js.map +1 -0
- package/dist/tasenor-common-node/src/net/middleware.d.ts +61 -0
- package/dist/tasenor-common-node/src/net/middleware.js +220 -0
- package/dist/tasenor-common-node/src/net/middleware.js.map +1 -0
- package/dist/tasenor-common-node/src/net/tokens.d.ts +50 -0
- package/dist/tasenor-common-node/src/net/tokens.js +141 -0
- package/dist/tasenor-common-node/src/net/tokens.js.map +1 -0
- package/dist/tasenor-common-node/src/net/vault.d.ts +67 -0
- package/dist/tasenor-common-node/src/net/vault.js +145 -0
- package/dist/tasenor-common-node/src/net/vault.js.map +1 -0
- package/dist/tasenor-common-node/src/plugins/BackendPlugin.d.ts +91 -0
- package/dist/tasenor-common-node/src/plugins/BackendPlugin.js +165 -0
- package/dist/tasenor-common-node/src/plugins/BackendPlugin.js.map +1 -0
- package/dist/tasenor-common-node/src/plugins/DataPlugin.d.ts +13 -0
- package/dist/tasenor-common-node/src/plugins/DataPlugin.js +26 -0
- package/dist/tasenor-common-node/src/plugins/DataPlugin.js.map +1 -0
- package/dist/tasenor-common-node/src/plugins/ImportPlugin.d.ts +188 -0
- package/dist/tasenor-common-node/src/plugins/ImportPlugin.js +204 -0
- package/dist/tasenor-common-node/src/plugins/ImportPlugin.js.map +1 -0
- package/dist/tasenor-common-node/src/plugins/ReportPlugin.d.ts +132 -0
- package/dist/tasenor-common-node/src/plugins/ReportPlugin.js +393 -0
- package/dist/tasenor-common-node/src/plugins/ReportPlugin.js.map +1 -0
- package/dist/tasenor-common-node/src/plugins/SchemePlugin.d.ts +34 -0
- package/dist/tasenor-common-node/src/plugins/SchemePlugin.js +47 -0
- package/dist/tasenor-common-node/src/plugins/SchemePlugin.js.map +1 -0
- package/dist/tasenor-common-node/src/plugins/ServicePlugin.d.ts +80 -0
- package/dist/tasenor-common-node/src/plugins/ServicePlugin.js +168 -0
- package/dist/tasenor-common-node/src/plugins/ServicePlugin.js.map +1 -0
- package/dist/tasenor-common-node/src/plugins/ToolPlugin.d.ts +27 -0
- package/dist/tasenor-common-node/src/plugins/ToolPlugin.js +37 -0
- package/dist/tasenor-common-node/src/plugins/ToolPlugin.js.map +1 -0
- package/dist/tasenor-common-node/src/plugins/index.d.ts +13 -0
- package/dist/tasenor-common-node/src/plugins/index.js +14 -0
- package/dist/tasenor-common-node/src/plugins/index.js.map +1 -0
- package/dist/tasenor-common-node/src/plugins/plugins.d.ts +101 -0
- package/dist/tasenor-common-node/src/plugins/plugins.js +292 -0
- package/dist/tasenor-common-node/src/plugins/plugins.js.map +1 -0
- package/dist/tasenor-common-node/src/process/Process.d.ts +108 -0
- package/dist/tasenor-common-node/src/process/Process.js +335 -0
- package/dist/tasenor-common-node/src/process/Process.js.map +1 -0
- package/dist/tasenor-common-node/src/process/ProcessConnector.d.ts +24 -0
- package/dist/tasenor-common-node/src/process/ProcessConnector.js +28 -0
- package/dist/tasenor-common-node/src/process/ProcessConnector.js.map +1 -0
- package/dist/tasenor-common-node/src/process/ProcessFile.d.ts +69 -0
- package/dist/tasenor-common-node/src/process/ProcessFile.js +145 -0
- package/dist/tasenor-common-node/src/process/ProcessFile.js.map +1 -0
- package/dist/tasenor-common-node/src/process/ProcessHandler.d.ts +60 -0
- package/dist/tasenor-common-node/src/process/ProcessHandler.js +73 -0
- package/dist/tasenor-common-node/src/process/ProcessHandler.js.map +1 -0
- package/dist/tasenor-common-node/src/process/ProcessStep.d.ts +52 -0
- package/dist/tasenor-common-node/src/process/ProcessStep.js +78 -0
- package/dist/tasenor-common-node/src/process/ProcessStep.js.map +1 -0
- package/dist/tasenor-common-node/src/process/ProcessingSystem.d.ts +60 -0
- package/dist/tasenor-common-node/src/process/ProcessingSystem.js +182 -0
- package/dist/tasenor-common-node/src/process/ProcessingSystem.js.map +1 -0
- package/dist/tasenor-common-node/src/process/index.d.ts +11 -0
- package/dist/tasenor-common-node/src/process/index.js +12 -0
- package/dist/tasenor-common-node/src/process/index.js.map +1 -0
- package/dist/tasenor-common-node/src/reports/conversions.d.ts +8 -0
- package/dist/tasenor-common-node/src/reports/conversions.js +47 -0
- package/dist/tasenor-common-node/src/reports/conversions.js.map +1 -0
- package/dist/tasenor-common-node/src/reports/index.d.ts +6 -0
- package/dist/tasenor-common-node/src/reports/index.js +7 -0
- package/dist/tasenor-common-node/src/reports/index.js.map +1 -0
- package/dist/tasenor-common-node/src/server/ISPDemoServer.d.ts +43 -0
- package/dist/tasenor-common-node/src/server/ISPDemoServer.js +112 -0
- package/dist/tasenor-common-node/src/server/ISPDemoServer.js.map +1 -0
- package/dist/tasenor-common-node/src/server/api.d.ts +15 -0
- package/dist/tasenor-common-node/src/server/api.js +27 -0
- package/dist/tasenor-common-node/src/server/api.js.map +1 -0
- package/dist/tasenor-common-node/src/server/index.d.ts +7 -0
- package/dist/tasenor-common-node/src/server/index.js +8 -0
- package/dist/tasenor-common-node/src/server/index.js.map +1 -0
- package/dist/tasenor-common-node/src/server/router.d.ts +5 -0
- package/dist/tasenor-common-node/src/server/router.js +37 -0
- package/dist/tasenor-common-node/src/server/router.js.map +1 -0
- package/dist/tasenor-common-node/src/system.d.ts +27 -0
- package/dist/tasenor-common-node/src/system.js +95 -0
- package/dist/tasenor-common-node/src/system.js.map +1 -0
- package/dist/tasenor-common-node/src/testing/ProcessingSystemMock.d.ts +21 -0
- package/dist/tasenor-common-node/src/testing/ProcessingSystemMock.js +33 -0
- package/dist/tasenor-common-node/src/testing/ProcessingSystemMock.js.map +1 -0
- package/dist/tasenor-common-node/src/testing/UnitTestImportConnector.d.ts +24 -0
- package/dist/tasenor-common-node/src/testing/UnitTestImportConnector.js +68 -0
- package/dist/tasenor-common-node/src/testing/UnitTestImportConnector.js.map +1 -0
- package/dist/tasenor-common-node/src/testing/UnitTester.d.ts +64 -0
- package/dist/tasenor-common-node/src/testing/UnitTester.js +199 -0
- package/dist/tasenor-common-node/src/testing/UnitTester.js.map +1 -0
- package/dist/tasenor-common-node/src/testing/index.d.ts +4 -0
- package/dist/tasenor-common-node/src/testing/index.js +5 -0
- package/dist/tasenor-common-node/src/testing/index.js.map +1 -0
- package/dist/tasenor-common-node/src/testing/test-handlers.d.ts +13 -0
- package/dist/tasenor-common-node/src/testing/test-handlers.js +52 -0
- package/dist/tasenor-common-node/src/testing/test-handlers.js.map +1 -0
- package/dist/tasenor-common-node/tests/TransactionRules.spec.d.ts +1 -0
- package/dist/tasenor-common-node/tests/TransactionRules.spec.js +64 -0
- package/dist/tasenor-common-node/tests/TransactionRules.spec.js.map +1 -0
- package/dist/tasenor-common-node/tests/TransferAnalyzer-account-address.spec.d.ts +1 -0
- package/dist/tasenor-common-node/tests/TransferAnalyzer-account-address.spec.js +80 -0
- package/dist/tasenor-common-node/tests/TransferAnalyzer-account-address.spec.js.map +1 -0
- package/dist/tasenor-common-node/tests/TransferAnalyzer-buying-and-selling.spec.d.ts +1 -0
- package/dist/tasenor-common-node/tests/TransferAnalyzer-buying-and-selling.spec.js +342 -0
- package/dist/tasenor-common-node/tests/TransferAnalyzer-buying-and-selling.spec.js.map +1 -0
- package/dist/tasenor-common-node/tests/TransferAnalyzer-loans.spec.d.ts +1 -0
- package/dist/tasenor-common-node/tests/TransferAnalyzer-loans.spec.js +174 -0
- package/dist/tasenor-common-node/tests/TransferAnalyzer-loans.spec.js.map +1 -0
- package/dist/tasenor-common-node/tests/TransferAnalyzer-multiple-null-amounts.spec.d.ts +1 -0
- package/dist/tasenor-common-node/tests/TransferAnalyzer-multiple-null-amounts.spec.js +175 -0
- package/dist/tasenor-common-node/tests/TransferAnalyzer-multiple-null-amounts.spec.js.map +1 -0
- package/dist/tasenor-common-node/tests/password.spec.d.ts +1 -0
- package/dist/tasenor-common-node/tests/password.spec.js +8 -0
- package/dist/tasenor-common-node/tests/password.spec.js.map +1 -0
- package/dist/tasenor-common-node/tests/tokens.spec.d.ts +1 -0
- package/dist/tasenor-common-node/tests/tokens.spec.js +49 -0
- package/dist/tasenor-common-node/tests/tokens.spec.js.map +1 -0
- package/dist/tasenor-common-node/tests/vault.spec.d.ts +1 -0
- package/dist/tasenor-common-node/tests/vault.spec.js +19 -0
- package/dist/tasenor-common-node/tests/vault.spec.js.map +1 -0
- package/dist/tasenor-common-plugins/src/CoinbaseImport/backend/CoinbaseHandler.d.ts +11 -0
- package/dist/tasenor-common-plugins/src/CoinbaseImport/backend/CoinbaseHandler.js +30 -0
- package/dist/tasenor-common-plugins/src/CoinbaseImport/backend/CoinbaseHandler.js.map +1 -0
- package/dist/tasenor-common-plugins/src/IncomeAndExpenses/backend/index.d.ts +5 -0
- package/dist/tasenor-common-plugins/src/IncomeAndExpenses/backend/index.js +350 -0
- package/dist/tasenor-common-plugins/src/IncomeAndExpenses/backend/index.js.map +1 -0
- package/dist/tasenor-common-plugins/src/KrakenImport/backend/KrakenHandler.d.ts +23 -0
- package/dist/tasenor-common-plugins/src/KrakenImport/backend/KrakenHandler.js +83 -0
- package/dist/tasenor-common-plugins/src/KrakenImport/backend/KrakenHandler.js.map +1 -0
- package/dist/tasenor-common-plugins/src/LynxImport/backend/LynxHandler.d.ts +28 -0
- package/dist/tasenor-common-plugins/src/LynxImport/backend/LynxHandler.js +340 -0
- package/dist/tasenor-common-plugins/src/LynxImport/backend/LynxHandler.js.map +1 -0
- package/dist/tasenor-common-plugins/src/NordeaImport/backend/NordeaHandler.d.ts +11 -0
- package/dist/tasenor-common-plugins/src/NordeaImport/backend/NordeaHandler.js +39 -0
- package/dist/tasenor-common-plugins/src/NordeaImport/backend/NordeaHandler.js.map +1 -0
- package/dist/tasenor-common-plugins/src/NordnetImport/backend/NordnetHandler.d.ts +17 -0
- package/dist/tasenor-common-plugins/src/NordnetImport/backend/NordnetHandler.js +66 -0
- package/dist/tasenor-common-plugins/src/NordnetImport/backend/NordnetHandler.js.map +1 -0
- package/dist/tasenor-common-plugins/src/TITOImport/backend/TITOHandler.d.ts +13 -0
- package/dist/tasenor-common-plugins/src/TITOImport/backend/TITOHandler.js +241 -0
- package/dist/tasenor-common-plugins/src/TITOImport/backend/TITOHandler.js.map +1 -0
- package/jest.config.js +1 -0
- package/package.json +62 -0
- package/src/cli.ts +267 -0
- package/src/commands/account.ts +69 -0
- package/src/commands/balance.ts +131 -0
- package/src/commands/db.ts +84 -0
- package/src/commands/entry.ts +117 -0
- package/src/commands/import.ts +160 -0
- package/src/commands/importer.ts +84 -0
- package/src/commands/index.ts +534 -0
- package/src/commands/period.ts +59 -0
- package/src/commands/plugin.ts +95 -0
- package/src/commands/report.ts +113 -0
- package/src/commands/settings.ts +75 -0
- package/src/commands/stock.ts +80 -0
- package/src/commands/tag.ts +102 -0
- package/src/commands/tx.ts +93 -0
- package/src/commands/user.ts +65 -0
- package/src/database/BookkeeperImporter.ts +358 -0
- package/src/database/DB.ts +396 -0
- package/src/database/index.ts +7 -0
- package/src/doccer.ts +29 -0
- package/src/error.ts +32 -0
- package/src/export/Exporter.ts +136 -0
- package/src/export/TasenorExporter.ts +144 -0
- package/src/export/TilitinExporter.ts +302 -0
- package/src/export/index.ts +8 -0
- package/src/import/TextFileProcessHandler.ts +384 -0
- package/src/import/TransactionImportConnector.ts +65 -0
- package/src/import/TransactionImportHandler.ts +819 -0
- package/src/import/TransactionRules.ts +570 -0
- package/src/import/TransactionUI.ts +520 -0
- package/src/import/TransferAnalyzer.ts +1450 -0
- package/src/import/index.ts +11 -0
- package/src/index.ts +12 -0
- package/src/net/crypto.ts +69 -0
- package/src/net/git.ts +151 -0
- package/src/net/index.ts +10 -0
- package/src/net/middleware.ts +261 -0
- package/src/net/tokens.ts +140 -0
- package/src/net/vault.ts +161 -0
- package/src/plugins/BackendPlugin.ts +188 -0
- package/src/plugins/DataPlugin.ts +29 -0
- package/src/plugins/ImportPlugin.ts +211 -0
- package/src/plugins/ReportPlugin.ts +443 -0
- package/src/plugins/SchemePlugin.ts +56 -0
- package/src/plugins/ServicePlugin.ts +188 -0
- package/src/plugins/ToolPlugin.ts +44 -0
- package/src/plugins/index.ts +13 -0
- package/src/plugins/plugins.ts +345 -0
- package/src/process/Process.ts +368 -0
- package/src/process/ProcessConnector.ts +45 -0
- package/src/process/ProcessFile.ts +169 -0
- package/src/process/ProcessHandler.ts +94 -0
- package/src/process/ProcessStep.ts +100 -0
- package/src/process/ProcessingSystem.ts +202 -0
- package/src/process/index.ts +11 -0
- package/src/reports/conversions.ts +52 -0
- package/src/reports/index.ts +6 -0
- package/src/server/ISPDemoServer.ts +122 -0
- package/src/server/api.ts +37 -0
- package/src/server/index.ts +7 -0
- package/src/server/router.ts +60 -0
- package/src/system.ts +96 -0
- package/src/testing/ProcessingSystemMock.ts +45 -0
- package/src/testing/UnitTestImportConnector.ts +86 -0
- package/src/testing/UnitTester.ts +231 -0
- package/src/testing/index.ts +4 -0
- package/src/testing/test-handlers.ts +55 -0
- package/tests/TransactionRules.spec.ts +73 -0
- package/tests/TransferAnalyzer-account-address.spec.ts +87 -0
- package/tests/TransferAnalyzer-buying-and-selling.spec.ts +354 -0
- package/tests/TransferAnalyzer-loans.spec.ts +197 -0
- package/tests/TransferAnalyzer-multiple-null-amounts.spec.ts +181 -0
- package/tests/password.spec.ts +8 -0
- package/tests/tokens.spec.ts +52 -0
- package/tests/vault.spec.ts +20 -0
- package/tsconfig.json +13 -0
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
import { AccountElement, AccountAddress, FilterRule, Language, UIQuery, TasenorElement, Tag, AccountNumber, PluginCode, TransactionImportOptions, ButtonElement, MessageElement, ProcessConfig, TextFileLine, TextFileLineElement, AssetType, Asset, ImportSegment } from '@dataplug/tasenor-common'
|
|
2
|
+
import { AskUI, SystemError } from '../error'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Injected dependecies for UI query generator.
|
|
6
|
+
*/
|
|
7
|
+
export interface TransactionUIDependencies {
|
|
8
|
+
getAccountCanditates(addr: AccountAddress, config: ProcessConfig): Promise<AccountNumber[]>
|
|
9
|
+
getTranslation(text: string, language: Language): Promise<string>
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A RISP generator creating UI definitions for various questions.
|
|
14
|
+
*/
|
|
15
|
+
export class TransactionUI {
|
|
16
|
+
|
|
17
|
+
private deps: TransactionUIDependencies
|
|
18
|
+
constructor(deps: TransactionUIDependencies) {
|
|
19
|
+
this.deps = deps
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Ensure that variable is in the configuration. If not throw AskUI exception to ask it from the user.
|
|
24
|
+
* @param config
|
|
25
|
+
* @param variable
|
|
26
|
+
*/
|
|
27
|
+
async getConfigOrAsk(config: ProcessConfig, variable: string, element: TasenorElement, allowNull = true): Promise<unknown> {
|
|
28
|
+
if (variable in config && (allowNull || config[variable] !== null)) {
|
|
29
|
+
return config[variable]
|
|
30
|
+
}
|
|
31
|
+
throw new AskUI({
|
|
32
|
+
type: 'flat',
|
|
33
|
+
elements: [
|
|
34
|
+
element,
|
|
35
|
+
await this.submit('Continue', 1, config.language as Language)
|
|
36
|
+
]
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Throw a query for boolean value if not in the configuration.
|
|
42
|
+
* @param config
|
|
43
|
+
* @param variable
|
|
44
|
+
* @param description
|
|
45
|
+
*/
|
|
46
|
+
async getBoolean(config: ProcessConfig, variable: string, description: string) {
|
|
47
|
+
return this.getConfigOrAsk(config, variable, {
|
|
48
|
+
type: 'yesno',
|
|
49
|
+
name: `configure.${variable}`,
|
|
50
|
+
label: await this.getTranslation(description, config.language as Language),
|
|
51
|
+
actions: {}
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Check if we have an answer for a segment.
|
|
57
|
+
*/
|
|
58
|
+
async getSegmentAnswer(config: ProcessConfig, segment: ImportSegment, variable: string): Promise<unknown | undefined> {
|
|
59
|
+
if ('answers' in config) {
|
|
60
|
+
const answers: Record<string, Record<string, unknown>> = config.answers as Record<string, Record<string, unknown>>
|
|
61
|
+
|
|
62
|
+
const segmentAnswers = answers[segment.id]
|
|
63
|
+
if (segmentAnswers && variable in segmentAnswers) {
|
|
64
|
+
return segmentAnswers[variable]
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return undefined
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Get the cash account for quick import selections.
|
|
73
|
+
*/
|
|
74
|
+
async getCashAccount(config: ProcessConfig): Promise<AccountNumber> {
|
|
75
|
+
return await this.getConfigOrAsk(config, 'cashAccount', {
|
|
76
|
+
type: 'account',
|
|
77
|
+
filter: { type: 'ASSET' },
|
|
78
|
+
name: 'configure.cashAccount',
|
|
79
|
+
label: await this.getTranslation('Select contra account for imported transactions, i.e. cash account.', config.language as Language),
|
|
80
|
+
actions: {}
|
|
81
|
+
}, false) as AccountNumber
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Check if the question about asset renaming is answered. If not, throw a question.
|
|
86
|
+
*/
|
|
87
|
+
async askedRenamingOrThrow(config: ProcessConfig, segment: ImportSegment, type: AssetType, asset: Asset): Promise<boolean> {
|
|
88
|
+
const ans = await this.getSegmentAnswer(config, segment, `hasBeenRenamed.${type}.${asset}`) as undefined | boolean
|
|
89
|
+
|
|
90
|
+
if (ans === undefined) {
|
|
91
|
+
throw new AskUI(await this.message(`Asset renaming question not implemented (avoid error for now by setting answer 'hasBeenRenamed.${type}.${asset}' for segment '${segment.id}').`, 'error'))
|
|
92
|
+
}
|
|
93
|
+
return ans
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Get the translation for the text to the currently configured language.
|
|
98
|
+
* @param text
|
|
99
|
+
* @returns
|
|
100
|
+
*/
|
|
101
|
+
async getTranslation(text: string, language: Language): Promise<string> {
|
|
102
|
+
return this.deps.getTranslation(text, language)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Construct a translated label for an account dropdown.
|
|
107
|
+
* @param accType
|
|
108
|
+
* @returns
|
|
109
|
+
*/
|
|
110
|
+
async accountLabel(accType: AccountAddress, language: Language): Promise<string> {
|
|
111
|
+
const [reason, type, asset] = accType.split('.')
|
|
112
|
+
const text = await this.getTranslation(`account-${reason}-${type}`, language)
|
|
113
|
+
|
|
114
|
+
// Resolve name for the asset.
|
|
115
|
+
let name = asset
|
|
116
|
+
if (type === 'statement') {
|
|
117
|
+
if (reason === 'income') {
|
|
118
|
+
name = await this.getTranslation(`income-${asset}`, language)
|
|
119
|
+
} else if (reason === 'expense') {
|
|
120
|
+
name = await this.getTranslation(`expense-${asset}`, language)
|
|
121
|
+
} else if (reason === 'tax') {
|
|
122
|
+
name = await this.getTranslation(`tax-${asset}`, language)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return text.replace('{asset}', name)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Construct a filter for account family.
|
|
131
|
+
* @param config
|
|
132
|
+
* @param accType
|
|
133
|
+
* @returns
|
|
134
|
+
*/
|
|
135
|
+
accountFilter(accType: AccountAddress): FilterRule {
|
|
136
|
+
const [reason] = accType.split('.')
|
|
137
|
+
switch (`${reason}`) {
|
|
138
|
+
case 'debt':
|
|
139
|
+
return { type: ['ASSET', 'LIABILITY'] }
|
|
140
|
+
case 'deposit':
|
|
141
|
+
case 'trade':
|
|
142
|
+
case 'withdrawal':
|
|
143
|
+
return { type: 'ASSET' }
|
|
144
|
+
case 'fee':
|
|
145
|
+
return { type: 'EXPENSE' }
|
|
146
|
+
}
|
|
147
|
+
// TODO: Think about the rest combinations. Needs probably account subtypes.
|
|
148
|
+
return null
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Construct a query for an account by its address.
|
|
153
|
+
* @param missing
|
|
154
|
+
*/
|
|
155
|
+
async account(config: ProcessConfig, account: AccountAddress, defaultAccount: AccountNumber | undefined = undefined): Promise<AccountElement> {
|
|
156
|
+
const language: Language = config.language as Language
|
|
157
|
+
|
|
158
|
+
const ui: AccountElement = {
|
|
159
|
+
type: 'account',
|
|
160
|
+
name: `configure.account.${account}`,
|
|
161
|
+
actions: {},
|
|
162
|
+
label: await this.accountLabel(account, language),
|
|
163
|
+
filter: this.accountFilter(account)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (defaultAccount) {
|
|
167
|
+
ui.defaultValue = defaultAccount
|
|
168
|
+
} else {
|
|
169
|
+
const canditates = await this.deps.getAccountCanditates(account, { ...config, plugin: config.handlers instanceof Array && config.handlers.length ? config.handlers[0] as PluginCode : undefined })
|
|
170
|
+
if (canditates.length) {
|
|
171
|
+
ui.defaultValue = canditates[0]
|
|
172
|
+
if (canditates.length > 1) {
|
|
173
|
+
ui.preferred = canditates
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return ui
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Interrupt with a query asking an account.
|
|
183
|
+
* @param account
|
|
184
|
+
* @param language
|
|
185
|
+
*/
|
|
186
|
+
async throwGetAccount(config: ProcessConfig, address: AccountAddress): Promise<never> {
|
|
187
|
+
const account = await this.account(config, address)
|
|
188
|
+
const submit = await this.submit('Continue', 1, config.language as Language)
|
|
189
|
+
throw new AskUI({
|
|
190
|
+
type: 'flat',
|
|
191
|
+
elements: [
|
|
192
|
+
account as unknown as TasenorElement,
|
|
193
|
+
submit
|
|
194
|
+
]
|
|
195
|
+
})
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Ask for account to be used for negatice balance instead of the account itself.
|
|
200
|
+
* @param address
|
|
201
|
+
* @param language
|
|
202
|
+
*/
|
|
203
|
+
async throwDebtAccount(config: ProcessConfig, account: AccountNumber, address: AccountAddress): Promise<never> {
|
|
204
|
+
const language: Language = config.language as Language
|
|
205
|
+
const text = await this.getTranslation('The account below has negative balance. If you want to record it to the separate debt account, please select another account below.', language)
|
|
206
|
+
const message = await this.message(text, 'info')
|
|
207
|
+
const parts = address.split('.')
|
|
208
|
+
const debtAddr = `debt.${parts[1]}.${parts[2]}` as AccountAddress
|
|
209
|
+
const accountUI = await this.account(config, debtAddr, account)
|
|
210
|
+
const submit = await this.submit('Continue', 1, language)
|
|
211
|
+
throw new AskUI({
|
|
212
|
+
type: 'flat',
|
|
213
|
+
elements: [
|
|
214
|
+
message,
|
|
215
|
+
accountUI as unknown as TasenorElement,
|
|
216
|
+
submit
|
|
217
|
+
]
|
|
218
|
+
})
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Construct a query for asking about grouping of accounts and account number for group if selected.
|
|
223
|
+
* @param accounts
|
|
224
|
+
* @param language
|
|
225
|
+
* @returns
|
|
226
|
+
*/
|
|
227
|
+
async accountGroup(config: ProcessConfig, accounts: AccountAddress[]): Promise<TasenorElement> {
|
|
228
|
+
const [reason, type] = accounts[0].split('.')
|
|
229
|
+
const elements: AccountElement[] = []
|
|
230
|
+
const language: Language = config.language as Language
|
|
231
|
+
|
|
232
|
+
for (const account of accounts) {
|
|
233
|
+
elements.push(await this.account(config, account))
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return {
|
|
237
|
+
type: 'flat',
|
|
238
|
+
elements: [
|
|
239
|
+
{
|
|
240
|
+
type: 'boolean',
|
|
241
|
+
name: `grouping.${reason}.${type}`,
|
|
242
|
+
label: await this.getTranslation('Do you want to use the same account for all of them?', language),
|
|
243
|
+
defaultValue: false,
|
|
244
|
+
actions: {}
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
type: 'case',
|
|
248
|
+
condition: `grouping.${reason}.${type}`,
|
|
249
|
+
cases: {
|
|
250
|
+
true: await this.account(config, `${reason}.${type}.*` as AccountAddress),
|
|
251
|
+
false: {
|
|
252
|
+
type: 'flat',
|
|
253
|
+
elements
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
]
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Submit button for UI configuration.
|
|
263
|
+
* @param language
|
|
264
|
+
* @returns
|
|
265
|
+
*/
|
|
266
|
+
async submit(label: string, objectWrapLevel: number, language: Language): Promise<ButtonElement> {
|
|
267
|
+
let errorMessage = await this.getTranslation('Saving failed', language)
|
|
268
|
+
let successMessage = await this.getTranslation('Saved successfully', language)
|
|
269
|
+
if (label === 'Retry') {
|
|
270
|
+
errorMessage = await this.getTranslation('Retry failed', language)
|
|
271
|
+
successMessage = await this.getTranslation('Retried successfully', language)
|
|
272
|
+
}
|
|
273
|
+
return {
|
|
274
|
+
type: 'button',
|
|
275
|
+
label,
|
|
276
|
+
actions: {
|
|
277
|
+
onClick: {
|
|
278
|
+
type: 'post',
|
|
279
|
+
url: '',
|
|
280
|
+
objectWrapLevel,
|
|
281
|
+
errorMessage,
|
|
282
|
+
successMessage
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* A UI message.
|
|
290
|
+
* @param message
|
|
291
|
+
*/
|
|
292
|
+
async message(text: string, severity: 'info' | 'warning' | 'error' | 'success'): Promise<MessageElement> {
|
|
293
|
+
return {
|
|
294
|
+
type: 'message',
|
|
295
|
+
severity,
|
|
296
|
+
text
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Throw an error message with Retry button.
|
|
302
|
+
* @param message
|
|
303
|
+
*/
|
|
304
|
+
async throwErrorRetry(message: string, language: Language) {
|
|
305
|
+
throw new AskUI({
|
|
306
|
+
type: 'flat',
|
|
307
|
+
elements: [
|
|
308
|
+
await this.message(message, 'error'),
|
|
309
|
+
await this.submit('Retry', 0, language)
|
|
310
|
+
]
|
|
311
|
+
})
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Construct RISP element from UI query.
|
|
316
|
+
*
|
|
317
|
+
* The following questions can be expressed:
|
|
318
|
+
*
|
|
319
|
+
* ### Choose an Option
|
|
320
|
+
*
|
|
321
|
+
* A list of fixed options are given. The display text is a key and the value is the resulting value, if selected.
|
|
322
|
+
* ```json
|
|
323
|
+
* {
|
|
324
|
+
* "name": "Option Question",
|
|
325
|
+
* "label": "Choose one of the following:",
|
|
326
|
+
* "ask": {
|
|
327
|
+
* "Hardware equipment": "HARDWARE",
|
|
328
|
+
* "Software": "SOFTWARE"
|
|
329
|
+
* }
|
|
330
|
+
* }
|
|
331
|
+
* ```
|
|
332
|
+
*
|
|
333
|
+
* ### Choose a Tag
|
|
334
|
+
*
|
|
335
|
+
* An ability to select from predetermined set of tags we can use
|
|
336
|
+
* ```json
|
|
337
|
+
* {
|
|
338
|
+
* "name": "Tag Selection",
|
|
339
|
+
* "label": "Select a tag:",
|
|
340
|
+
* "chooseTag": [ "A", "B", "C" ]
|
|
341
|
+
* }
|
|
342
|
+
* ```
|
|
343
|
+
*
|
|
344
|
+
* ### Explain in Text
|
|
345
|
+
* A simple text box can be used with
|
|
346
|
+
* ```json
|
|
347
|
+
* {
|
|
348
|
+
* "name": "A Text Box",
|
|
349
|
+
* "label": "Plase enter the purchase description:",
|
|
350
|
+
* "text": true
|
|
351
|
+
* }
|
|
352
|
+
* ```
|
|
353
|
+
*
|
|
354
|
+
* @param query
|
|
355
|
+
*/
|
|
356
|
+
async parseQuery(name: string, query: UIQuery, language: Language): Promise<TasenorElement> {
|
|
357
|
+
if ('ask' in query) {
|
|
358
|
+
// This is just object mapping explanation to values.
|
|
359
|
+
return {
|
|
360
|
+
name,
|
|
361
|
+
type: 'radio',
|
|
362
|
+
label: query.label || await this.getTranslation('Select one of the following:', language),
|
|
363
|
+
actions: {},
|
|
364
|
+
options: query.ask as Record<string, string>
|
|
365
|
+
}
|
|
366
|
+
} else if ('chooseTag' in query) {
|
|
367
|
+
return {
|
|
368
|
+
name,
|
|
369
|
+
type: 'tags',
|
|
370
|
+
label: query.label || await this.getTranslation('Select one of the following:', language),
|
|
371
|
+
actions: {},
|
|
372
|
+
single: true,
|
|
373
|
+
options: query.chooseTag as Tag[]
|
|
374
|
+
}
|
|
375
|
+
} else if ('text' in query) {
|
|
376
|
+
return {
|
|
377
|
+
name,
|
|
378
|
+
type: 'text',
|
|
379
|
+
label: query.label || await this.getTranslation('Please enter text:', language),
|
|
380
|
+
actions: {}
|
|
381
|
+
}
|
|
382
|
+
} else {
|
|
383
|
+
throw new SystemError(`Unable to parse UI from query ${JSON.stringify(query)}.`)
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Construct UI for general query.
|
|
389
|
+
* @param UIQuery
|
|
390
|
+
* @param language
|
|
391
|
+
*/
|
|
392
|
+
async query(name: string, query: UIQuery | UIQuery[], lines: TextFileLine[] | null, language: Language): Promise<TasenorElement> {
|
|
393
|
+
const elements: TasenorElement[] = []
|
|
394
|
+
|
|
395
|
+
// Construct some reference if we know context.
|
|
396
|
+
if (lines && lines.length) {
|
|
397
|
+
elements.push(await this.describeLines(lines, language))
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if (query instanceof Array) {
|
|
401
|
+
for (const q of query) {
|
|
402
|
+
elements.push(await this.parseQuery(name, q, language))
|
|
403
|
+
}
|
|
404
|
+
} else {
|
|
405
|
+
elements.push(await this.parseQuery(name, query, language))
|
|
406
|
+
}
|
|
407
|
+
elements.push(await this.submit('Continue', 2, language))
|
|
408
|
+
|
|
409
|
+
return {
|
|
410
|
+
type: 'flat',
|
|
411
|
+
elements
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Construct a query and throw it immediately.
|
|
417
|
+
* @param name
|
|
418
|
+
* @param query
|
|
419
|
+
* @param lines
|
|
420
|
+
* @param language
|
|
421
|
+
*/
|
|
422
|
+
async throwQuery(name: string, query: UIQuery | UIQuery[], lines: TextFileLine[] | null, language: Language): Promise<never> {
|
|
423
|
+
const element = await this.query(name, query, lines, language)
|
|
424
|
+
this.throw(element)
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Throw UI exception in order to collect more information from UI.
|
|
429
|
+
* @param element
|
|
430
|
+
*/
|
|
431
|
+
throw(element: TasenorElement): never {
|
|
432
|
+
throw new AskUI(element as TasenorElement)
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Construct a descriptor of context lines needed to display in a question.
|
|
437
|
+
* @param lines
|
|
438
|
+
* @param language
|
|
439
|
+
* @returns
|
|
440
|
+
*/
|
|
441
|
+
async describeLines(lines: TextFileLine[], language: Language): Promise<TasenorElement> {
|
|
442
|
+
const viewer: TextFileLineElement[] = lines.map(line => ({
|
|
443
|
+
type: 'textFileLine',
|
|
444
|
+
line
|
|
445
|
+
}))
|
|
446
|
+
return {
|
|
447
|
+
type: 'box',
|
|
448
|
+
elements: [
|
|
449
|
+
{
|
|
450
|
+
type: 'html',
|
|
451
|
+
html: `<strong>${await this.getTranslation('Based on the following imported lines', language)}</strong>`
|
|
452
|
+
},
|
|
453
|
+
...viewer
|
|
454
|
+
]
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Construct a query asking one of the options in order to store to the configuration.
|
|
460
|
+
* @param text
|
|
461
|
+
* @param variable
|
|
462
|
+
* @param options
|
|
463
|
+
*/
|
|
464
|
+
async throwRadioQuestion(text, variable, options, language: Language): Promise<never> {
|
|
465
|
+
throw new AskUI({
|
|
466
|
+
type: 'flat',
|
|
467
|
+
elements: [
|
|
468
|
+
{
|
|
469
|
+
type: 'message',
|
|
470
|
+
severity: 'info',
|
|
471
|
+
text
|
|
472
|
+
},
|
|
473
|
+
{
|
|
474
|
+
type: 'radio',
|
|
475
|
+
name: `configure.${variable}`,
|
|
476
|
+
options,
|
|
477
|
+
actions: {}
|
|
478
|
+
},
|
|
479
|
+
{
|
|
480
|
+
type: 'button',
|
|
481
|
+
label: await this.deps.getTranslation('Continue', language),
|
|
482
|
+
actions: {
|
|
483
|
+
onClick: {
|
|
484
|
+
type: 'post',
|
|
485
|
+
url: '',
|
|
486
|
+
objectWrapLevel: 1
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
]
|
|
491
|
+
})
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Pass control to the rule editor when found a line not matching a filter.
|
|
496
|
+
* @param lines
|
|
497
|
+
* @param language
|
|
498
|
+
*/
|
|
499
|
+
async throwNoFilterMatchForLine(lines: TextFileLine[], config: ProcessConfig, options: TransactionImportOptions): Promise<never> {
|
|
500
|
+
const cashAccount = await this.getCashAccount(config)
|
|
501
|
+
throw new AskUI({
|
|
502
|
+
type: 'ruleEditor',
|
|
503
|
+
name: 'once',
|
|
504
|
+
actions: {
|
|
505
|
+
onContinue: {
|
|
506
|
+
type: 'post',
|
|
507
|
+
url: ''
|
|
508
|
+
},
|
|
509
|
+
onCreateRule: {
|
|
510
|
+
type: 'post',
|
|
511
|
+
url: '/rule'
|
|
512
|
+
}
|
|
513
|
+
},
|
|
514
|
+
config,
|
|
515
|
+
lines,
|
|
516
|
+
options,
|
|
517
|
+
cashAccount
|
|
518
|
+
})
|
|
519
|
+
}
|
|
520
|
+
}
|