@tailor-platform/erp-kit 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/README.md +35 -7
- package/dist/cli.mjs +779 -268
- package/package.json +5 -4
- package/skills/erp-kit-app-1-requirements/SKILL.md +8 -9
- package/skills/erp-kit-app-2-requirements-review/references/best-practices-check.md +4 -0
- package/skills/erp-kit-app-2-requirements-review/references/boundary-consistency-check.md +4 -0
- package/skills/erp-kit-app-3-plan/SKILL.md +27 -27
- package/skills/erp-kit-app-3-plan/references/resolver-extraction.md +21 -17
- package/skills/erp-kit-app-3-plan/references/screen-extraction.md +15 -1
- package/skills/erp-kit-app-3-plan/references/story-extraction.md +8 -2
- package/skills/erp-kit-app-5-impl-backend/SKILL.md +9 -11
- package/skills/erp-kit-app-5-impl-backend/references/app-config.md +1 -22
- package/skills/erp-kit-app-5-impl-backend/references/module-wiring.md +0 -1
- package/skills/erp-kit-app-5-impl-backend/references/resolver-patterns.md +13 -4
- package/skills/erp-kit-app-6-impl-frontend/SKILL.md +5 -0
- package/skills/erp-kit-app-6-impl-frontend/references/pages.md +16 -46
- package/skills/erp-kit-app-7-impl-review/SKILL.md +13 -11
- package/skills/erp-kit-app-7-impl-review/references/resolver-doc-code-parity.md +16 -17
- package/skills/erp-kit-module-1-requirements/SKILL.md +6 -12
- package/skills/erp-kit-module-2-requirements-review/SKILL.md +21 -5
- package/skills/erp-kit-module-2-requirements-review/references/requirements-report-format.md +19 -0
- package/skills/erp-kit-module-3-plan/SKILL.md +2 -4
- package/skills/erp-kit-module-4-plan-review/SKILL.md +21 -5
- package/skills/erp-kit-module-4-plan-review/references/parity-report-format.md +15 -0
- package/skills/erp-kit-module-6-impl-review/SKILL.md +21 -7
- package/skills/erp-kit-module-6-impl-review/references/impl-parity-report-format.md +15 -0
- package/skills/erp-kit-module-shared/SKILL.md +4 -0
- package/src/commands/app/index.ts +28 -17
- package/src/commands/check.test.ts +1 -1
- package/src/commands/check.ts +2 -35
- package/src/commands/doc/index.ts +83 -0
- package/src/commands/doc/module.test.ts +119 -0
- package/src/commands/doc/module.ts +114 -0
- package/src/commands/doc/modules.test.ts +103 -0
- package/src/commands/doc/modules.ts +98 -0
- package/src/commands/doc/search.test.ts +94 -0
- package/src/commands/doc/search.ts +111 -0
- package/src/commands/generate-doc.ts +17 -10
- package/src/commands/index.ts +20 -8
- package/src/commands/lib/command-result.ts +30 -0
- package/src/commands/lib/discovery.test.ts +74 -0
- package/src/commands/lib/discovery.ts +106 -0
- package/src/commands/lib/paths.ts +22 -0
- package/src/commands/lib/sync-check-source.test.ts +197 -0
- package/src/commands/lib/sync-check-source.ts +100 -0
- package/src/commands/lib/sync-check-tests.test.ts +178 -0
- package/src/commands/lib/sync-check-tests.ts +69 -0
- package/src/commands/mock/index.ts +11 -6
- package/src/commands/module/generate.ts +13 -8
- package/src/commands/module/index.ts +17 -21
- package/src/commands/parse-doc-test-cases.ts +13 -2
- package/src/commands/sync-check.test.ts +6 -364
- package/src/commands/sync-check.ts +7 -251
- package/src/generator/generate-app-code.test.ts +121 -0
- package/src/generator/generate-app-code.ts +51 -0
- package/src/generator/generate-code-boilerplate.test.ts +1 -1
- package/src/generator/generate-code.test.ts +33 -6
- package/src/generator/generate-code.ts +12 -226
- package/src/generator/generate-errors.ts +34 -0
- package/src/generator/generate-permissions.ts +12 -0
- package/src/generator/generate-shells.ts +28 -0
- package/src/generator/generate-stubs.ts +31 -0
- package/src/generator/parse-resolver-doc.test.ts +89 -0
- package/src/generator/parse-resolver-doc.ts +125 -0
- package/src/generator/scaffold.ts +57 -0
- package/src/generator/stub-templates.test.ts +55 -0
- package/src/generator/stub-templates.ts +145 -0
- package/src/modules/audit/README.md +46 -0
- package/src/modules/audit/command/activateAuditPolicy.generated.ts +6 -0
- package/src/modules/audit/command/activateAuditPolicy.test.ts +186 -0
- package/src/modules/audit/command/activateAuditPolicy.ts +97 -0
- package/src/modules/audit/command/createAuditPolicy.generated.ts +6 -0
- package/src/modules/audit/command/createAuditPolicy.test.ts +395 -0
- package/src/modules/audit/command/createAuditPolicy.ts +131 -0
- package/src/modules/audit/command/deactivateAuditPolicy.generated.ts +6 -0
- package/src/modules/audit/command/deactivateAuditPolicy.test.ts +138 -0
- package/src/modules/audit/command/deactivateAuditPolicy.ts +58 -0
- package/src/modules/audit/command/deleteAuditPolicy.generated.ts +6 -0
- package/src/modules/audit/command/deleteAuditPolicy.test.ts +121 -0
- package/src/modules/audit/command/deleteAuditPolicy.ts +52 -0
- package/src/modules/audit/command/logAuditEvent.generated.ts +6 -0
- package/src/modules/audit/command/logAuditEvent.test.ts +991 -0
- package/src/modules/audit/command/logAuditEvent.ts +357 -0
- package/src/modules/audit/command/reactivateAuditPolicy.generated.ts +6 -0
- package/src/modules/audit/command/reactivateAuditPolicy.test.ts +143 -0
- package/src/modules/audit/command/reactivateAuditPolicy.ts +79 -0
- package/src/modules/audit/command/registerAuditableEntity.generated.ts +6 -0
- package/src/modules/audit/command/registerAuditableEntity.test.ts +268 -0
- package/src/modules/audit/command/registerAuditableEntity.ts +94 -0
- package/src/modules/audit/command/replaceAuditPolicy.generated.ts +6 -0
- package/src/modules/audit/command/replaceAuditPolicy.test.ts +242 -0
- package/src/modules/audit/command/replaceAuditPolicy.ts +91 -0
- package/src/modules/audit/command/updateAuditPolicy.generated.ts +6 -0
- package/src/modules/audit/command/updateAuditPolicy.test.ts +284 -0
- package/src/modules/audit/command/updateAuditPolicy.ts +151 -0
- package/src/modules/audit/db/auditEntry.ts +47 -0
- package/src/modules/audit/db/auditPolicy.ts +33 -0
- package/src/modules/audit/db/auditableEntity.ts +22 -0
- package/src/modules/audit/db/changeDetail.ts +28 -0
- package/src/modules/audit/db/policyFieldRule.ts +23 -0
- package/src/modules/audit/docs/commands/ActivateAuditPolicy.md +69 -0
- package/src/modules/audit/docs/commands/CreateAuditPolicy.md +79 -0
- package/src/modules/audit/docs/commands/DeactivateAuditPolicy.md +55 -0
- package/src/modules/audit/docs/commands/DeleteAuditPolicy.md +55 -0
- package/src/modules/audit/docs/commands/LogAuditEvent.md +137 -0
- package/src/modules/audit/docs/commands/ReactivateAuditPolicy.md +58 -0
- package/src/modules/audit/docs/commands/RegisterAuditableEntity.md +62 -0
- package/src/modules/audit/docs/commands/ReplaceAuditPolicy.md +72 -0
- package/src/modules/audit/docs/commands/UpdateAuditPolicy.md +77 -0
- package/src/modules/audit/docs/features/audit-event-logging.md +126 -0
- package/src/modules/audit/docs/features/audit-policy-configuration.md +135 -0
- package/src/modules/audit/docs/features/field-level-change-tracking.md +95 -0
- package/src/modules/audit/docs/models/AuditEntry.md +55 -0
- package/src/modules/audit/docs/models/AuditPolicy.md +79 -0
- package/src/modules/audit/docs/models/AuditableEntity.md +38 -0
- package/src/modules/audit/docs/models/ChangeDetail.md +55 -0
- package/src/modules/audit/docs/models/PolicyFieldRule.md +45 -0
- package/src/modules/audit/docs/queries/GetAuditEntry.md +49 -0
- package/src/modules/audit/docs/queries/GetAuditPolicy.md +54 -0
- package/src/modules/audit/docs/queries/GetAuditSummary.md +84 -0
- package/src/modules/audit/docs/queries/GetChangeDetails.md +56 -0
- package/src/modules/audit/docs/queries/ListAuditPolicies.md +58 -0
- package/src/modules/audit/docs/queries/SearchAuditEntries.md +91 -0
- package/src/modules/audit/generated/kysely-tailordb.ts +92 -0
- package/src/modules/audit/index.ts +2 -0
- package/src/modules/audit/lib/_db_deps.ts +13 -0
- package/src/modules/audit/lib/errors.generated.ts +120 -0
- package/src/modules/audit/lib/permissions.generated.ts +14 -0
- package/src/modules/audit/lib/types.ts +28 -0
- package/src/modules/audit/module.ts +57 -0
- package/src/modules/audit/permissions.ts +39 -0
- package/src/modules/audit/query/getAuditEntry.generated.ts +5 -0
- package/src/modules/audit/query/getAuditEntry.test.ts +123 -0
- package/src/modules/audit/query/getAuditEntry.ts +36 -0
- package/src/modules/audit/query/getAuditPolicy.generated.ts +5 -0
- package/src/modules/audit/query/getAuditPolicy.test.ts +169 -0
- package/src/modules/audit/query/getAuditPolicy.ts +42 -0
- package/src/modules/audit/query/getAuditSummary.generated.ts +5 -0
- package/src/modules/audit/query/getAuditSummary.test.ts +632 -0
- package/src/modules/audit/query/getAuditSummary.ts +164 -0
- package/src/modules/audit/query/getChangeDetails.generated.ts +5 -0
- package/src/modules/audit/query/getChangeDetails.test.ts +195 -0
- package/src/modules/audit/query/getChangeDetails.ts +42 -0
- package/src/modules/audit/query/listAuditPolicies.generated.ts +5 -0
- package/src/modules/audit/query/listAuditPolicies.test.ts +239 -0
- package/src/modules/audit/query/listAuditPolicies.ts +100 -0
- package/src/modules/audit/query/searchAuditEntries.generated.ts +5 -0
- package/src/modules/audit/query/searchAuditEntries.test.ts +424 -0
- package/src/modules/audit/query/searchAuditEntries.ts +121 -0
- package/src/modules/audit/tailor.config.ts +13 -0
- package/src/modules/audit/tailor.d.ts +13 -0
- package/src/modules/audit/testing/fixtures.ts +215 -0
- package/src/modules/business-partner/README.md +60 -0
- package/src/modules/business-partner/command/.gitkeep +0 -0
- package/src/modules/business-partner/command/activatePartner.generated.ts +6 -0
- package/src/modules/business-partner/command/activatePartner.test.ts +59 -0
- package/src/modules/business-partner/command/activatePartner.ts +45 -0
- package/src/modules/business-partner/command/assignRoleToPartner.generated.ts +6 -0
- package/src/modules/business-partner/command/assignRoleToPartner.test.ts +113 -0
- package/src/modules/business-partner/command/assignRoleToPartner.ts +72 -0
- package/src/modules/business-partner/command/createContactPerson.generated.ts +6 -0
- package/src/modules/business-partner/command/createContactPerson.test.ts +193 -0
- package/src/modules/business-partner/command/createContactPerson.ts +98 -0
- package/src/modules/business-partner/command/createPartner.generated.ts +6 -0
- package/src/modules/business-partner/command/createPartner.test.ts +179 -0
- package/src/modules/business-partner/command/createPartner.ts +83 -0
- package/src/modules/business-partner/command/createPartnerAddress.generated.ts +6 -0
- package/src/modules/business-partner/command/createPartnerAddress.test.ts +195 -0
- package/src/modules/business-partner/command/createPartnerAddress.ts +119 -0
- package/src/modules/business-partner/command/createPartnerBankAccount.generated.ts +6 -0
- package/src/modules/business-partner/command/createPartnerBankAccount.test.ts +297 -0
- package/src/modules/business-partner/command/createPartnerBankAccount.ts +114 -0
- package/src/modules/business-partner/command/createPartnerIdentification.generated.ts +6 -0
- package/src/modules/business-partner/command/createPartnerIdentification.test.ts +255 -0
- package/src/modules/business-partner/command/createPartnerIdentification.ts +97 -0
- package/src/modules/business-partner/command/deactivateContactPerson.generated.ts +6 -0
- package/src/modules/business-partner/command/deactivateContactPerson.test.ts +70 -0
- package/src/modules/business-partner/command/deactivateContactPerson.ts +54 -0
- package/src/modules/business-partner/command/deactivatePartner.generated.ts +6 -0
- package/src/modules/business-partner/command/deactivatePartner.test.ts +59 -0
- package/src/modules/business-partner/command/deactivatePartner.ts +46 -0
- package/src/modules/business-partner/command/deleteContactPerson.generated.ts +6 -0
- package/src/modules/business-partner/command/deleteContactPerson.test.ts +61 -0
- package/src/modules/business-partner/command/deleteContactPerson.ts +48 -0
- package/src/modules/business-partner/command/deletePartner.generated.ts +6 -0
- package/src/modules/business-partner/command/deletePartner.test.ts +58 -0
- package/src/modules/business-partner/command/deletePartner.ts +46 -0
- package/src/modules/business-partner/command/deletePartnerAddress.generated.ts +6 -0
- package/src/modules/business-partner/command/deletePartnerAddress.test.ts +74 -0
- package/src/modules/business-partner/command/deletePartnerAddress.ts +52 -0
- package/src/modules/business-partner/command/deletePartnerBankAccount.generated.ts +6 -0
- package/src/modules/business-partner/command/deletePartnerBankAccount.test.ts +55 -0
- package/src/modules/business-partner/command/deletePartnerBankAccount.ts +36 -0
- package/src/modules/business-partner/command/deletePartnerIdentification.generated.ts +6 -0
- package/src/modules/business-partner/command/deletePartnerIdentification.test.ts +47 -0
- package/src/modules/business-partner/command/deletePartnerIdentification.ts +37 -0
- package/src/modules/business-partner/command/reactivateContactPerson.generated.ts +6 -0
- package/src/modules/business-partner/command/reactivateContactPerson.test.ts +48 -0
- package/src/modules/business-partner/command/reactivateContactPerson.ts +48 -0
- package/src/modules/business-partner/command/reactivatePartner.generated.ts +6 -0
- package/src/modules/business-partner/command/reactivatePartner.test.ts +59 -0
- package/src/modules/business-partner/command/reactivatePartner.ts +46 -0
- package/src/modules/business-partner/command/removeRoleFromPartner.generated.ts +6 -0
- package/src/modules/business-partner/command/removeRoleFromPartner.test.ts +82 -0
- package/src/modules/business-partner/command/removeRoleFromPartner.ts +73 -0
- package/src/modules/business-partner/command/setDefaultPartnerAddress.generated.ts +6 -0
- package/src/modules/business-partner/command/setDefaultPartnerAddress.test.ts +60 -0
- package/src/modules/business-partner/command/setDefaultPartnerAddress.ts +48 -0
- package/src/modules/business-partner/command/setDefaultPartnerBankAccount.generated.ts +6 -0
- package/src/modules/business-partner/command/setDefaultPartnerBankAccount.test.ts +56 -0
- package/src/modules/business-partner/command/setDefaultPartnerBankAccount.ts +51 -0
- package/src/modules/business-partner/command/setPrimaryContactPerson.generated.ts +6 -0
- package/src/modules/business-partner/command/setPrimaryContactPerson.test.ts +63 -0
- package/src/modules/business-partner/command/setPrimaryContactPerson.ts +55 -0
- package/src/modules/business-partner/command/updateContactPerson.generated.ts +6 -0
- package/src/modules/business-partner/command/updateContactPerson.test.ts +193 -0
- package/src/modules/business-partner/command/updateContactPerson.ts +92 -0
- package/src/modules/business-partner/command/updatePartner.generated.ts +6 -0
- package/src/modules/business-partner/command/updatePartner.test.ts +101 -0
- package/src/modules/business-partner/command/updatePartner.ts +76 -0
- package/src/modules/business-partner/command/updatePartnerAddress.generated.ts +6 -0
- package/src/modules/business-partner/command/updatePartnerAddress.test.ts +148 -0
- package/src/modules/business-partner/command/updatePartnerAddress.ts +64 -0
- package/src/modules/business-partner/command/updatePartnerBankAccount.generated.ts +6 -0
- package/src/modules/business-partner/command/updatePartnerBankAccount.test.ts +249 -0
- package/src/modules/business-partner/command/updatePartnerBankAccount.ts +109 -0
- package/src/modules/business-partner/command/updatePartnerIdentification.generated.ts +6 -0
- package/src/modules/business-partner/command/updatePartnerIdentification.test.ts +162 -0
- package/src/modules/business-partner/command/updatePartnerIdentification.ts +105 -0
- package/src/modules/business-partner/db/.gitkeep +0 -0
- package/src/modules/business-partner/db/businessPartner.ts +59 -0
- package/src/modules/business-partner/db/contactPerson.ts +49 -0
- package/src/modules/business-partner/db/partnerAddress.ts +45 -0
- package/src/modules/business-partner/db/partnerBankAccount.ts +53 -0
- package/src/modules/business-partner/db/partnerIdentification.ts +53 -0
- package/src/modules/business-partner/db/partnerRole.ts +43 -0
- package/src/modules/business-partner/docs/commands/ActivatePartner.md +39 -0
- package/src/modules/business-partner/docs/commands/AssignRoleToPartner.md +49 -0
- package/src/modules/business-partner/docs/commands/CreateContactPerson.md +59 -0
- package/src/modules/business-partner/docs/commands/CreatePartner.md +54 -0
- package/src/modules/business-partner/docs/commands/CreatePartnerAddress.md +60 -0
- package/src/modules/business-partner/docs/commands/CreatePartnerBankAccount.md +68 -0
- package/src/modules/business-partner/docs/commands/CreatePartnerIdentification.md +59 -0
- package/src/modules/business-partner/docs/commands/DeactivateContactPerson.md +42 -0
- package/src/modules/business-partner/docs/commands/DeactivatePartner.md +39 -0
- package/src/modules/business-partner/docs/commands/DeleteContactPerson.md +43 -0
- package/src/modules/business-partner/docs/commands/DeletePartner.md +40 -0
- package/src/modules/business-partner/docs/commands/DeletePartnerAddress.md +40 -0
- package/src/modules/business-partner/docs/commands/DeletePartnerBankAccount.md +35 -0
- package/src/modules/business-partner/docs/commands/DeletePartnerIdentification.md +33 -0
- package/src/modules/business-partner/docs/commands/ReactivateContactPerson.md +38 -0
- package/src/modules/business-partner/docs/commands/ReactivatePartner.md +39 -0
- package/src/modules/business-partner/docs/commands/RemoveRoleFromPartner.md +46 -0
- package/src/modules/business-partner/docs/commands/SetDefaultPartnerAddress.md +38 -0
- package/src/modules/business-partner/docs/commands/SetDefaultPartnerBankAccount.md +38 -0
- package/src/modules/business-partner/docs/commands/SetPrimaryContactPerson.md +43 -0
- package/src/modules/business-partner/docs/commands/UpdateContactPerson.md +66 -0
- package/src/modules/business-partner/docs/commands/UpdatePartner.md +48 -0
- package/src/modules/business-partner/docs/commands/UpdatePartnerAddress.md +46 -0
- package/src/modules/business-partner/docs/commands/UpdatePartnerBankAccount.md +64 -0
- package/src/modules/business-partner/docs/commands/UpdatePartnerIdentification.md +52 -0
- package/src/modules/business-partner/docs/features/contact-person-management.md +70 -0
- package/src/modules/business-partner/docs/features/partner-address-management.md +96 -0
- package/src/modules/business-partner/docs/features/partner-bank-account.md +70 -0
- package/src/modules/business-partner/docs/features/partner-identification.md +76 -0
- package/src/modules/business-partner/docs/features/partner-lifecycle.md +59 -0
- package/src/modules/business-partner/docs/features/partner-role-classification.md +73 -0
- package/src/modules/business-partner/docs/models/BusinessPartner.md +64 -0
- package/src/modules/business-partner/docs/models/ContactPerson.md +62 -0
- package/src/modules/business-partner/docs/models/PartnerAddress.md +52 -0
- package/src/modules/business-partner/docs/models/PartnerBankAccount.md +50 -0
- package/src/modules/business-partner/docs/models/PartnerIdentification.md +46 -0
- package/src/modules/business-partner/docs/models/PartnerRole.md +42 -0
- package/src/modules/business-partner/docs/queries/GetContactPerson.md +34 -0
- package/src/modules/business-partner/docs/queries/GetDefaultPartnerAddress.md +40 -0
- package/src/modules/business-partner/docs/queries/GetDefaultPartnerBankAccount.md +36 -0
- package/src/modules/business-partner/docs/queries/GetPartner.md +35 -0
- package/src/modules/business-partner/docs/queries/GetPartnerAddress.md +34 -0
- package/src/modules/business-partner/docs/queries/GetPartnerBankAccount.md +34 -0
- package/src/modules/business-partner/docs/queries/GetPartnerIdentification.md +34 -0
- package/src/modules/business-partner/docs/queries/GetPartnerRole.md +34 -0
- package/src/modules/business-partner/docs/queries/GetPrimaryContactPerson.md +36 -0
- package/src/modules/business-partner/docs/queries/ListContactPersonsByPartner.md +39 -0
- package/src/modules/business-partner/docs/queries/ListPartnerAddressesByPartner.md +41 -0
- package/src/modules/business-partner/docs/queries/ListPartnerBankAccountsByPartner.md +39 -0
- package/src/modules/business-partner/docs/queries/ListPartnerIdentificationsByPartner.md +41 -0
- package/src/modules/business-partner/docs/queries/ListPartnersByRole.md +47 -0
- package/src/modules/business-partner/executor/.gitkeep +0 -0
- package/src/modules/business-partner/generated/.gitkeep +0 -0
- package/src/modules/business-partner/generated/enums.ts +60 -0
- package/src/modules/business-partner/generated/kysely-tailordb.ts +114 -0
- package/src/modules/business-partner/index.ts +2 -0
- package/src/modules/business-partner/lib/_db_deps.ts +17 -0
- package/src/modules/business-partner/lib/errors.generated.ts +172 -0
- package/src/modules/business-partner/lib/errors.ts +2 -0
- package/src/modules/business-partner/lib/permissions.generated.ts +30 -0
- package/src/modules/business-partner/lib/types.ts +53 -0
- package/src/modules/business-partner/module.ts +181 -0
- package/src/modules/business-partner/permissions.ts +3 -0
- package/src/modules/business-partner/query/.gitkeep +0 -0
- package/src/modules/business-partner/query/getContactPerson.generated.ts +5 -0
- package/src/modules/business-partner/query/getContactPerson.test.ts +31 -0
- package/src/modules/business-partner/query/getContactPerson.ts +16 -0
- package/src/modules/business-partner/query/getDefaultPartnerAddress.generated.ts +5 -0
- package/src/modules/business-partner/query/getDefaultPartnerAddress.test.ts +45 -0
- package/src/modules/business-partner/query/getDefaultPartnerAddress.ts +30 -0
- package/src/modules/business-partner/query/getDefaultPartnerBankAccount.generated.ts +5 -0
- package/src/modules/business-partner/query/getDefaultPartnerBankAccount.test.ts +43 -0
- package/src/modules/business-partner/query/getDefaultPartnerBankAccount.ts +17 -0
- package/src/modules/business-partner/query/getPartner.generated.ts +5 -0
- package/src/modules/business-partner/query/getPartner.test.ts +31 -0
- package/src/modules/business-partner/query/getPartner.ts +16 -0
- package/src/modules/business-partner/query/getPartnerAddress.generated.ts +5 -0
- package/src/modules/business-partner/query/getPartnerAddress.test.ts +31 -0
- package/src/modules/business-partner/query/getPartnerAddress.ts +16 -0
- package/src/modules/business-partner/query/getPartnerBankAccount.generated.ts +5 -0
- package/src/modules/business-partner/query/getPartnerBankAccount.test.ts +31 -0
- package/src/modules/business-partner/query/getPartnerBankAccount.ts +16 -0
- package/src/modules/business-partner/query/getPartnerIdentification.generated.ts +5 -0
- package/src/modules/business-partner/query/getPartnerIdentification.test.ts +31 -0
- package/src/modules/business-partner/query/getPartnerIdentification.ts +16 -0
- package/src/modules/business-partner/query/getPartnerRole.generated.ts +5 -0
- package/src/modules/business-partner/query/getPartnerRole.test.ts +31 -0
- package/src/modules/business-partner/query/getPartnerRole.ts +19 -0
- package/src/modules/business-partner/query/getPrimaryContactPerson.generated.ts +5 -0
- package/src/modules/business-partner/query/getPrimaryContactPerson.test.ts +43 -0
- package/src/modules/business-partner/query/getPrimaryContactPerson.ts +17 -0
- package/src/modules/business-partner/query/listContactPersonsByPartner.generated.ts +5 -0
- package/src/modules/business-partner/query/listContactPersonsByPartner.test.ts +77 -0
- package/src/modules/business-partner/query/listContactPersonsByPartner.ts +32 -0
- package/src/modules/business-partner/query/listPartnerAddressesByPartner.generated.ts +5 -0
- package/src/modules/business-partner/query/listPartnerAddressesByPartner.test.ts +71 -0
- package/src/modules/business-partner/query/listPartnerAddressesByPartner.ts +37 -0
- package/src/modules/business-partner/query/listPartnerBankAccountsByPartner.generated.ts +5 -0
- package/src/modules/business-partner/query/listPartnerBankAccountsByPartner.test.ts +59 -0
- package/src/modules/business-partner/query/listPartnerBankAccountsByPartner.ts +32 -0
- package/src/modules/business-partner/query/listPartnerIdentificationsByPartner.generated.ts +5 -0
- package/src/modules/business-partner/query/listPartnerIdentificationsByPartner.test.ts +72 -0
- package/src/modules/business-partner/query/listPartnerIdentificationsByPartner.ts +40 -0
- package/src/modules/business-partner/query/listPartnersByRole.generated.ts +5 -0
- package/src/modules/business-partner/query/listPartnersByRole.test.ts +103 -0
- package/src/modules/business-partner/query/listPartnersByRole.ts +47 -0
- package/src/modules/business-partner/tailor.config.ts +13 -0
- package/src/modules/business-partner/tailor.d.ts +13 -0
- package/src/modules/business-partner/testing/fixtures.ts +204 -0
- package/src/modules/coa-management/README.md +61 -0
- package/src/modules/coa-management/command/.gitkeep +0 -0
- package/src/modules/coa-management/command/activateAccount.generated.ts +6 -0
- package/src/modules/coa-management/command/activateAccount.test.ts +125 -0
- package/src/modules/coa-management/command/activateAccount.ts +105 -0
- package/src/modules/coa-management/command/activateChartOfAccounts.generated.ts +6 -0
- package/src/modules/coa-management/command/activateChartOfAccounts.test.ts +113 -0
- package/src/modules/coa-management/command/activateChartOfAccounts.ts +104 -0
- package/src/modules/coa-management/command/createAccount.generated.ts +6 -0
- package/src/modules/coa-management/command/createAccount.test.ts +767 -0
- package/src/modules/coa-management/command/createAccount.ts +247 -0
- package/src/modules/coa-management/command/createAccountGroup.generated.ts +6 -0
- package/src/modules/coa-management/command/createAccountGroup.test.ts +494 -0
- package/src/modules/coa-management/command/createAccountGroup.ts +207 -0
- package/src/modules/coa-management/command/createChartOfAccounts.generated.ts +6 -0
- package/src/modules/coa-management/command/createChartOfAccounts.test.ts +502 -0
- package/src/modules/coa-management/command/createChartOfAccounts.ts +267 -0
- package/src/modules/coa-management/command/deactivateAccount.generated.ts +6 -0
- package/src/modules/coa-management/command/deactivateAccount.test.ts +199 -0
- package/src/modules/coa-management/command/deactivateAccount.ts +142 -0
- package/src/modules/coa-management/command/deactivateChartOfAccounts.generated.ts +6 -0
- package/src/modules/coa-management/command/deactivateChartOfAccounts.test.ts +91 -0
- package/src/modules/coa-management/command/deactivateChartOfAccounts.ts +88 -0
- package/src/modules/coa-management/command/deleteAccount.generated.ts +6 -0
- package/src/modules/coa-management/command/deleteAccount.test.ts +122 -0
- package/src/modules/coa-management/command/deleteAccount.ts +103 -0
- package/src/modules/coa-management/command/deleteAccountGroup.generated.ts +6 -0
- package/src/modules/coa-management/command/deleteAccountGroup.test.ts +120 -0
- package/src/modules/coa-management/command/deleteAccountGroup.ts +113 -0
- package/src/modules/coa-management/command/deleteChartOfAccounts.generated.ts +6 -0
- package/src/modules/coa-management/command/deleteChartOfAccounts.test.ts +154 -0
- package/src/modules/coa-management/command/deleteChartOfAccounts.ts +133 -0
- package/src/modules/coa-management/command/moveAccountGroup.generated.ts +6 -0
- package/src/modules/coa-management/command/moveAccountGroup.test.ts +199 -0
- package/src/modules/coa-management/command/moveAccountGroup.ts +145 -0
- package/src/modules/coa-management/command/reactivateAccount.generated.ts +6 -0
- package/src/modules/coa-management/command/reactivateAccount.test.ts +126 -0
- package/src/modules/coa-management/command/reactivateAccount.ts +123 -0
- package/src/modules/coa-management/command/updateAccount.generated.ts +6 -0
- package/src/modules/coa-management/command/updateAccount.test.ts +669 -0
- package/src/modules/coa-management/command/updateAccount.ts +370 -0
- package/src/modules/coa-management/command/updateAccountGroup.generated.ts +6 -0
- package/src/modules/coa-management/command/updateAccountGroup.test.ts +253 -0
- package/src/modules/coa-management/command/updateAccountGroup.ts +191 -0
- package/src/modules/coa-management/command/updateChartOfAccounts.generated.ts +6 -0
- package/src/modules/coa-management/command/updateChartOfAccounts.test.ts +153 -0
- package/src/modules/coa-management/command/updateChartOfAccounts.ts +133 -0
- package/src/modules/coa-management/db/.gitkeep +0 -0
- package/src/modules/coa-management/db/account.ts +119 -0
- package/src/modules/coa-management/db/accountGroup.ts +57 -0
- package/src/modules/coa-management/db/chartOfAccounts.ts +55 -0
- package/src/modules/coa-management/docs/commands/ActivateAccount.md +49 -0
- package/src/modules/coa-management/docs/commands/ActivateChartOfAccounts.md +47 -0
- package/src/modules/coa-management/docs/commands/CreateAccount.md +94 -0
- package/src/modules/coa-management/docs/commands/CreateAccountGroup.md +70 -0
- package/src/modules/coa-management/docs/commands/CreateChartOfAccounts.md +72 -0
- package/src/modules/coa-management/docs/commands/DeactivateAccount.md +65 -0
- package/src/modules/coa-management/docs/commands/DeactivateChartOfAccounts.md +44 -0
- package/src/modules/coa-management/docs/commands/DeleteAccount.md +52 -0
- package/src/modules/coa-management/docs/commands/DeleteAccountGroup.md +50 -0
- package/src/modules/coa-management/docs/commands/DeleteChartOfAccounts.md +48 -0
- package/src/modules/coa-management/docs/commands/MoveAccountGroup.md +57 -0
- package/src/modules/coa-management/docs/commands/ReactivateAccount.md +50 -0
- package/src/modules/coa-management/docs/commands/UpdateAccount.md +102 -0
- package/src/modules/coa-management/docs/commands/UpdateAccountGroup.md +62 -0
- package/src/modules/coa-management/docs/commands/UpdateChartOfAccounts.md +49 -0
- package/src/modules/coa-management/docs/features/account-group-hierarchy.md +81 -0
- package/src/modules/coa-management/docs/features/account-lifecycle.md +80 -0
- package/src/modules/coa-management/docs/features/account-management.md +114 -0
- package/src/modules/coa-management/docs/features/chart-of-accounts-setup.md +86 -0
- package/src/modules/coa-management/docs/models/Account.md +84 -0
- package/src/modules/coa-management/docs/models/AccountGroup.md +55 -0
- package/src/modules/coa-management/docs/models/ChartOfAccounts.md +65 -0
- package/src/modules/coa-management/docs/queries/DetectCircularReference.md +52 -0
- package/src/modules/coa-management/docs/queries/GetAccount.md +42 -0
- package/src/modules/coa-management/docs/queries/GetAccountGroup.md +42 -0
- package/src/modules/coa-management/docs/queries/GetChartOfAccounts.md +48 -0
- package/src/modules/coa-management/docs/queries/ListAccountGroups.md +42 -0
- package/src/modules/coa-management/docs/queries/ListAccounts.md +54 -0
- package/src/modules/coa-management/docs/queries/ListUnassignedAccounts.md +40 -0
- package/src/modules/coa-management/executor/.gitkeep +0 -0
- package/src/modules/coa-management/generated/.gitkeep +0 -0
- package/src/modules/coa-management/generated/enums.ts +45 -0
- package/src/modules/coa-management/generated/kysely-tailordb.ts +81 -0
- package/src/modules/coa-management/index.ts +2 -0
- package/src/modules/coa-management/lib/_db_deps.ts +17 -0
- package/src/modules/coa-management/lib/errors.generated.ts +162 -0
- package/src/modules/coa-management/lib/errors.ts +0 -0
- package/src/modules/coa-management/lib/permissions.generated.ts +20 -0
- package/src/modules/coa-management/lib/types.ts +22 -0
- package/src/modules/coa-management/module.ts +136 -0
- package/src/modules/coa-management/permissions.ts +3 -0
- package/src/modules/coa-management/query/.gitkeep +0 -0
- package/src/modules/coa-management/query/detectCircularReference.generated.ts +5 -0
- package/src/modules/coa-management/query/detectCircularReference.test.ts +88 -0
- package/src/modules/coa-management/query/detectCircularReference.ts +46 -0
- package/src/modules/coa-management/query/getAccount.generated.ts +5 -0
- package/src/modules/coa-management/query/getAccount.test.ts +55 -0
- package/src/modules/coa-management/query/getAccount.ts +25 -0
- package/src/modules/coa-management/query/getAccountGroup.generated.ts +5 -0
- package/src/modules/coa-management/query/getAccountGroup.test.ts +55 -0
- package/src/modules/coa-management/query/getAccountGroup.ts +25 -0
- package/src/modules/coa-management/query/getChartOfAccounts.generated.ts +5 -0
- package/src/modules/coa-management/query/getChartOfAccounts.test.ts +79 -0
- package/src/modules/coa-management/query/getChartOfAccounts.ts +28 -0
- package/src/modules/coa-management/query/listAccountGroups.generated.ts +5 -0
- package/src/modules/coa-management/query/listAccountGroups.test.ts +72 -0
- package/src/modules/coa-management/query/listAccountGroups.ts +49 -0
- package/src/modules/coa-management/query/listAccounts.generated.ts +5 -0
- package/src/modules/coa-management/query/listAccounts.test.ts +136 -0
- package/src/modules/coa-management/query/listAccounts.ts +82 -0
- package/src/modules/coa-management/query/listUnassignedAccounts.generated.ts +5 -0
- package/src/modules/coa-management/query/listUnassignedAccounts.test.ts +96 -0
- package/src/modules/coa-management/query/listUnassignedAccounts.ts +39 -0
- package/src/modules/coa-management/tailor.config.ts +13 -0
- package/src/modules/coa-management/tailor.d.ts +13 -0
- package/src/modules/coa-management/testing/fixtures.ts +201 -0
- package/src/modules/item-management/README.md +1 -1
- package/src/modules/organization/README.md +57 -0
- package/src/modules/organization/command/.gitkeep +0 -0
- package/src/modules/organization/command/activateCompany.generated.ts +6 -0
- package/src/modules/organization/command/activateCompany.test.ts +184 -0
- package/src/modules/organization/command/activateCompany.ts +92 -0
- package/src/modules/organization/command/createCompany.generated.ts +6 -0
- package/src/modules/organization/command/createCompany.test.ts +156 -0
- package/src/modules/organization/command/createCompany.ts +80 -0
- package/src/modules/organization/command/createDepartment.generated.ts +6 -0
- package/src/modules/organization/command/createDepartment.test.ts +239 -0
- package/src/modules/organization/command/createDepartment.ts +98 -0
- package/src/modules/organization/command/createSite.generated.ts +6 -0
- package/src/modules/organization/command/createSite.test.ts +262 -0
- package/src/modules/organization/command/createSite.ts +155 -0
- package/src/modules/organization/command/deactivateCompany.generated.ts +6 -0
- package/src/modules/organization/command/deactivateCompany.test.ts +58 -0
- package/src/modules/organization/command/deactivateCompany.ts +47 -0
- package/src/modules/organization/command/deactivateDepartment.generated.ts +6 -0
- package/src/modules/organization/command/deactivateDepartment.test.ts +115 -0
- package/src/modules/organization/command/deactivateDepartment.ts +63 -0
- package/src/modules/organization/command/deactivateSite.generated.ts +6 -0
- package/src/modules/organization/command/deactivateSite.test.ts +53 -0
- package/src/modules/organization/command/deactivateSite.ts +47 -0
- package/src/modules/organization/command/deleteCompany.generated.ts +6 -0
- package/src/modules/organization/command/deleteCompany.test.ts +99 -0
- package/src/modules/organization/command/deleteCompany.ts +66 -0
- package/src/modules/organization/command/reactivateCompany.generated.ts +6 -0
- package/src/modules/organization/command/reactivateCompany.test.ts +58 -0
- package/src/modules/organization/command/reactivateCompany.ts +47 -0
- package/src/modules/organization/command/reactivateDepartment.generated.ts +6 -0
- package/src/modules/organization/command/reactivateDepartment.test.ts +59 -0
- package/src/modules/organization/command/reactivateDepartment.ts +47 -0
- package/src/modules/organization/command/reactivateSite.generated.ts +6 -0
- package/src/modules/organization/command/reactivateSite.test.ts +53 -0
- package/src/modules/organization/command/reactivateSite.ts +47 -0
- package/src/modules/organization/command/updateCompany.generated.ts +6 -0
- package/src/modules/organization/command/updateCompany.test.ts +239 -0
- package/src/modules/organization/command/updateCompany.ts +127 -0
- package/src/modules/organization/command/updateDepartment.generated.ts +6 -0
- package/src/modules/organization/command/updateDepartment.test.ts +232 -0
- package/src/modules/organization/command/updateDepartment.ts +120 -0
- package/src/modules/organization/command/updateSite.generated.ts +6 -0
- package/src/modules/organization/command/updateSite.test.ts +274 -0
- package/src/modules/organization/command/updateSite.ts +176 -0
- package/src/modules/organization/db/.gitkeep +0 -0
- package/src/modules/organization/db/company.ts +44 -0
- package/src/modules/organization/db/department.ts +46 -0
- package/src/modules/organization/db/site.ts +44 -0
- package/src/modules/organization/docs/commands/ActivateCompany.md +62 -0
- package/src/modules/organization/docs/commands/CreateCompany.md +49 -0
- package/src/modules/organization/docs/commands/CreateDepartment.md +62 -0
- package/src/modules/organization/docs/commands/CreateSite.md +74 -0
- package/src/modules/organization/docs/commands/DeactivateCompany.md +40 -0
- package/src/modules/organization/docs/commands/DeactivateDepartment.md +44 -0
- package/src/modules/organization/docs/commands/DeactivateSite.md +38 -0
- package/src/modules/organization/docs/commands/DeleteCompany.md +50 -0
- package/src/modules/organization/docs/commands/ReactivateCompany.md +39 -0
- package/src/modules/organization/docs/commands/ReactivateDepartment.md +37 -0
- package/src/modules/organization/docs/commands/ReactivateSite.md +37 -0
- package/src/modules/organization/docs/commands/UpdateCompany.md +58 -0
- package/src/modules/organization/docs/commands/UpdateDepartment.md +64 -0
- package/src/modules/organization/docs/commands/UpdateSite.md +80 -0
- package/src/modules/organization/docs/features/company-lifecycle.md +76 -0
- package/src/modules/organization/docs/features/department-management.md +66 -0
- package/src/modules/organization/docs/features/site-management.md +86 -0
- package/src/modules/organization/docs/models/Company.md +60 -0
- package/src/modules/organization/docs/models/Department.md +57 -0
- package/src/modules/organization/docs/models/Site.md +57 -0
- package/src/modules/organization/docs/queries/DetectDepartmentCircularReference.md +50 -0
- package/src/modules/organization/docs/queries/GetCompany.md +40 -0
- package/src/modules/organization/docs/queries/GetDepartment.md +44 -0
- package/src/modules/organization/docs/queries/GetDepartmentChildren.md +40 -0
- package/src/modules/organization/docs/queries/GetSite.md +37 -0
- package/src/modules/organization/docs/queries/ListDepartmentsByCompany.md +54 -0
- package/src/modules/organization/docs/queries/ListSitesByCompany.md +54 -0
- package/src/modules/organization/executor/.gitkeep +0 -0
- package/src/modules/organization/generated/.gitkeep +0 -0
- package/src/modules/organization/generated/kysely-tailordb.ts +77 -0
- package/src/modules/organization/index.ts +2 -0
- package/src/modules/organization/lib/_db_deps.ts +10 -0
- package/src/modules/organization/lib/errors.generated.ts +117 -0
- package/src/modules/organization/lib/errors.ts +1 -0
- package/src/modules/organization/lib/permissions.generated.ts +19 -0
- package/src/modules/organization/lib/types.ts +16 -0
- package/src/modules/organization/module.ts +89 -0
- package/src/modules/organization/permissions.ts +3 -0
- package/src/modules/organization/query/.gitkeep +0 -0
- package/src/modules/organization/query/detectDepartmentCircularReference.generated.ts +5 -0
- package/src/modules/organization/query/detectDepartmentCircularReference.test.ts +102 -0
- package/src/modules/organization/query/detectDepartmentCircularReference.ts +27 -0
- package/src/modules/organization/query/getCompany.generated.ts +5 -0
- package/src/modules/organization/query/getCompany.test.ts +70 -0
- package/src/modules/organization/query/getCompany.ts +16 -0
- package/src/modules/organization/query/getDepartment.generated.ts +5 -0
- package/src/modules/organization/query/getDepartment.test.ts +85 -0
- package/src/modules/organization/query/getDepartment.ts +17 -0
- package/src/modules/organization/query/getDepartmentChildren.generated.ts +5 -0
- package/src/modules/organization/query/getDepartmentChildren.test.ts +75 -0
- package/src/modules/organization/query/getDepartmentChildren.ts +21 -0
- package/src/modules/organization/query/getSite.generated.ts +5 -0
- package/src/modules/organization/query/getSite.test.ts +55 -0
- package/src/modules/organization/query/getSite.ts +16 -0
- package/src/modules/organization/query/listDepartmentsByCompany.generated.ts +5 -0
- package/src/modules/organization/query/listDepartmentsByCompany.test.ts +124 -0
- package/src/modules/organization/query/listDepartmentsByCompany.ts +43 -0
- package/src/modules/organization/query/listSitesByCompany.generated.ts +5 -0
- package/src/modules/organization/query/listSitesByCompany.test.ts +126 -0
- package/src/modules/organization/query/listSitesByCompany.ts +41 -0
- package/src/modules/organization/tailor.config.ts +13 -0
- package/src/modules/organization/tailor.d.ts +13 -0
- package/src/modules/organization/testing/fixtures.ts +155 -0
- package/src/modules/primitives/README.md +1 -1
- package/src/modules/primitives/command/setBaseCurrency.test.ts +8 -64
- package/src/modules/primitives/command/setBaseCurrency.ts +6 -64
- package/src/modules/primitives/docs/commands/ActivateCategory.md +1 -1
- package/src/modules/primitives/docs/commands/ActivateCurrency.md +1 -1
- package/src/modules/primitives/docs/commands/ActivateUnit.md +1 -1
- package/src/modules/primitives/docs/commands/CreateExchangeRate.md +2 -2
- package/src/modules/primitives/docs/commands/CreateUnit.md +1 -1
- package/src/modules/primitives/docs/commands/DeactivateCategory.md +1 -1
- package/src/modules/primitives/docs/commands/DeactivateCurrency.md +1 -1
- package/src/modules/primitives/docs/commands/DeactivateUnit.md +1 -1
- package/src/modules/primitives/docs/commands/SetBaseCurrency.md +13 -23
- package/src/modules/primitives/docs/commands/SetReferenceUnit.md +1 -1
- package/src/modules/primitives/docs/features/currency-definitions.md +13 -14
- package/src/modules/primitives/docs/models/Currency.md +3 -4
- package/src/modules/primitives/docs/queries/ConvertAmount.md +2 -2
- package/src/modules/primitives/docs/queries/ConvertQuantity.md +2 -2
- package/src/modules/primitives/lib/errors.generated.ts +5 -0
- package/src/modules/product-management/README.md +1 -1
- package/src/modules/user-management/docs/commands/CreatePermission.md +3 -3
- package/src/modules/user-management/docs/commands/CreateRole.md +1 -1
- package/src/modules/user-management/docs/queries/ListRolePermissionsByRole.md +39 -0
- package/src/modules/user-management/docs/queries/ListUserRolesByUser.md +39 -0
- package/src/modules/user-management/generated/enums.ts +0 -15
- package/src/modules/user-management/generated/kysely-tailordb.ts +0 -11
- package/src/shared/createContext.ts +2 -1
- package/src/shared/defineQuery.ts +36 -1
- package/src/shared/requirePermission.ts +3 -3
- package/src/shared/types.ts +3 -0
- package/templates/scaffold/app/backend/package.json +4 -3
- package/templates/scaffold/app/frontend/eslint.config.js +12 -0
- package/templates/scaffold/app/frontend/package.json +10 -7
- package/templates/scaffold/app/frontend/src/hooks/use-toast.ts +30 -0
- package/templates/scaffold/app/frontend/src/pages/user-management/user/create/components/create-user-form.tsx +3 -2
- package/templates/scaffold/app/frontend/vite.config.ts +5 -5
- package/src/commands/module/list.test.ts +0 -57
- package/src/commands/module/list.ts +0 -64
- /package/src/modules/{accounting → audit/db}/.gitkeep +0 -0
- /package/src/modules/audit/{.gitkeep → executor/.gitkeep} +0 -0
- /package/src/modules/{coa-management/.gitkeep → audit/lib/errors.ts} +0 -0
- /package/src/modules/{supplier-management → business-partner}/.gitkeep +0 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { fromMarkdown } from "mdast-util-from-markdown";
|
|
2
|
+
import { toString } from "mdast-util-to-string";
|
|
3
|
+
import type { Heading, RootContent, Root } from "mdast";
|
|
4
|
+
|
|
5
|
+
export interface ParsedModuleCommand {
|
|
6
|
+
module: string;
|
|
7
|
+
command: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface ParsedResolverError {
|
|
11
|
+
code: string;
|
|
12
|
+
description: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ParsedResolverDoc {
|
|
16
|
+
resolverName: string;
|
|
17
|
+
moduleCommands: ParsedModuleCommand[];
|
|
18
|
+
errors: ParsedResolverError[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const MODULE_COMMAND_PATTERN = /([a-z][\w-]*)\.(\w+)/;
|
|
22
|
+
const TABLE_ROW_PATTERN = /^\|(.+)\|(.+)\|$/;
|
|
23
|
+
|
|
24
|
+
export function parseResolverDoc(fileName: string, markdown: string): ParsedResolverDoc {
|
|
25
|
+
const resolverName = fileName.charAt(0).toLowerCase() + fileName.slice(1);
|
|
26
|
+
const tree = fromMarkdown(markdown);
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
resolverName,
|
|
30
|
+
moduleCommands: parseModuleCommands(tree),
|
|
31
|
+
errors: parseExceptionHandlingFromRaw(markdown),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function isHeading(node: RootContent): node is Heading {
|
|
36
|
+
return node.type === "heading";
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function getNodesUnderHeading(tree: Root, headingText: string): RootContent[] {
|
|
40
|
+
const nodes: RootContent[] = [];
|
|
41
|
+
let collecting = false;
|
|
42
|
+
|
|
43
|
+
for (const node of tree.children) {
|
|
44
|
+
if (isHeading(node)) {
|
|
45
|
+
if (collecting) break;
|
|
46
|
+
if (node.depth === 2 && toString(node) === headingText) {
|
|
47
|
+
collecting = true;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (collecting) {
|
|
52
|
+
nodes.push(node);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return nodes;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function parseModuleCommands(tree: Root): ParsedModuleCommand[] {
|
|
60
|
+
const nodes = getNodesUnderHeading(tree, "Modules Commands Used");
|
|
61
|
+
const commands: ParsedModuleCommand[] = [];
|
|
62
|
+
|
|
63
|
+
for (const node of nodes) {
|
|
64
|
+
if (node.type !== "list") continue;
|
|
65
|
+
|
|
66
|
+
for (const item of node.children) {
|
|
67
|
+
const text = toString(item);
|
|
68
|
+
const match = MODULE_COMMAND_PATTERN.exec(text);
|
|
69
|
+
if (match) {
|
|
70
|
+
commands.push({ module: match[1], command: match[2] });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return commands;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function parseExceptionHandlingFromRaw(markdown: string): ParsedResolverError[] {
|
|
79
|
+
const lines = markdown.split("\n");
|
|
80
|
+
const errors: ParsedResolverError[] = [];
|
|
81
|
+
|
|
82
|
+
// Find the "## Exception Handling" heading
|
|
83
|
+
let inSection = false;
|
|
84
|
+
let headerSkipped = false;
|
|
85
|
+
let separatorSkipped = false;
|
|
86
|
+
|
|
87
|
+
for (const line of lines) {
|
|
88
|
+
const trimmed = line.trim();
|
|
89
|
+
|
|
90
|
+
if (trimmed.startsWith("## Exception Handling")) {
|
|
91
|
+
inSection = true;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (!inSection) continue;
|
|
96
|
+
|
|
97
|
+
// Stop at next heading
|
|
98
|
+
if (trimmed.startsWith("#")) break;
|
|
99
|
+
|
|
100
|
+
// Skip empty lines
|
|
101
|
+
if (!trimmed) continue;
|
|
102
|
+
|
|
103
|
+
// Parse table rows
|
|
104
|
+
const match = TABLE_ROW_PATTERN.exec(trimmed);
|
|
105
|
+
if (!match) continue;
|
|
106
|
+
|
|
107
|
+
// Skip header row and separator row
|
|
108
|
+
if (!headerSkipped) {
|
|
109
|
+
headerSkipped = true;
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
if (!separatorSkipped) {
|
|
113
|
+
separatorSkipped = true;
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const code = match[1].trim();
|
|
118
|
+
const description = match[2].trim();
|
|
119
|
+
if (code) {
|
|
120
|
+
errors.push({ code, description });
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return errors;
|
|
125
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { PACKAGE_ROOT, readErpKitVersion } from "../util";
|
|
4
|
+
|
|
5
|
+
// npm renames .gitignore during pack (npm/cli#5756).
|
|
6
|
+
// prepack copies .gitignore to __dot__gitignore to preserve it.
|
|
7
|
+
export function copyTemplateDir(
|
|
8
|
+
srcDir: string,
|
|
9
|
+
destDir: string,
|
|
10
|
+
replacements: Record<string, string>,
|
|
11
|
+
placeholderFiles: Set<string>,
|
|
12
|
+
): void {
|
|
13
|
+
for (const entry of fs.readdirSync(srcDir, { withFileTypes: true })) {
|
|
14
|
+
const srcPath = path.join(srcDir, entry.name);
|
|
15
|
+
const destName = entry.name === "__dot__gitignore" ? ".gitignore" : entry.name;
|
|
16
|
+
const destPath = path.join(destDir, destName);
|
|
17
|
+
|
|
18
|
+
if (entry.name === "node_modules") continue;
|
|
19
|
+
|
|
20
|
+
if (entry.isDirectory()) {
|
|
21
|
+
fs.mkdirSync(destPath, { recursive: true });
|
|
22
|
+
copyTemplateDir(srcPath, destPath, replacements, placeholderFiles);
|
|
23
|
+
} else {
|
|
24
|
+
if (fs.existsSync(destPath)) continue;
|
|
25
|
+
fs.mkdirSync(path.dirname(destPath), { recursive: true });
|
|
26
|
+
if (placeholderFiles.has(entry.name)) {
|
|
27
|
+
let content = fs.readFileSync(srcPath, "utf-8");
|
|
28
|
+
for (const [from, to] of Object.entries(replacements)) {
|
|
29
|
+
content = content.replaceAll(from, to);
|
|
30
|
+
}
|
|
31
|
+
fs.writeFileSync(destPath, content);
|
|
32
|
+
} else {
|
|
33
|
+
fs.copyFileSync(srcPath, destPath);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function scaffoldModuleBoilerplate(moduleDir: string, moduleName: string): void {
|
|
40
|
+
const templateDir = path.join(PACKAGE_ROOT, "templates", "scaffold", "module");
|
|
41
|
+
const replacements = { "template-module": moduleName };
|
|
42
|
+
const placeholderFiles = new Set(["permissions.ts", "tailor.config.ts"]);
|
|
43
|
+
copyTemplateDir(templateDir, moduleDir, replacements, placeholderFiles);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function scaffoldAppBoilerplate(appDir: string, appName: string): void {
|
|
47
|
+
const templateDir = path.join(PACKAGE_ROOT, "templates", "scaffold", "app");
|
|
48
|
+
const erpKitVersion = readErpKitVersion();
|
|
49
|
+
const replacements = {
|
|
50
|
+
"template-app-frontend": `${appName}-frontend`,
|
|
51
|
+
"template-app-backend": appName,
|
|
52
|
+
"template-app": appName,
|
|
53
|
+
'"workspace:*"': `"${erpKitVersion}"`,
|
|
54
|
+
};
|
|
55
|
+
const placeholderFiles = new Set(["package.json", "tailor.config.ts", "index.html"]);
|
|
56
|
+
copyTemplateDir(templateDir, appDir, replacements, placeholderFiles);
|
|
57
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { renderStub } from "./stub-templates";
|
|
3
|
+
|
|
4
|
+
describe("renderStub", () => {
|
|
5
|
+
it("command: generates input interface and run function", () => {
|
|
6
|
+
const result = renderStub("command", "createItem");
|
|
7
|
+
expect(result).toContain("export interface CreateItemInput");
|
|
8
|
+
expect(result).toContain(
|
|
9
|
+
"export async function run(db: Transaction, input: CreateItemInput, ctx: CommandContext)",
|
|
10
|
+
);
|
|
11
|
+
expect(result).toContain("return ok({})");
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it("commandTest: generates test with createMockDb", () => {
|
|
15
|
+
const result = renderStub("commandTest", "createItem");
|
|
16
|
+
expect(result).toContain('describe("createItem - test scenario"');
|
|
17
|
+
expect(result).toContain("createMockDb<Transaction>()");
|
|
18
|
+
expect(result).toContain("CreateItemInput");
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("query: generates ReadonlyDB-based stub", () => {
|
|
22
|
+
const result = renderStub("query", "getProduct");
|
|
23
|
+
expect(result).toContain("export interface GetProductInput");
|
|
24
|
+
expect(result).toContain("ReadonlyDB<DB>");
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("queryTest: generates test with DB type", () => {
|
|
28
|
+
const result = renderStub("queryTest", "getProduct");
|
|
29
|
+
expect(result).toContain('describe("getProduct"');
|
|
30
|
+
expect(result).toContain("createMockDb<DB>()");
|
|
31
|
+
expect(result).toContain("type GetProductInput");
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("db: generates model type definition", () => {
|
|
35
|
+
const result = renderStub("db", "item");
|
|
36
|
+
expect(result).toContain("export const item = db");
|
|
37
|
+
expect(result).toContain('.type("Item"');
|
|
38
|
+
expect(result).toContain("unsafeAllowAllTypePermission");
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("resolver: generates createResolver stub with SDK imports", () => {
|
|
42
|
+
const result = renderStub("resolver", "createItem");
|
|
43
|
+
expect(result).toContain("createResolver");
|
|
44
|
+
expect(result).toContain('name: "createItem"');
|
|
45
|
+
expect(result).toContain('operation: "mutation"');
|
|
46
|
+
expect(result).toContain('getDB("main-db")');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("resolverTest: generates test that imports resolver", () => {
|
|
50
|
+
const result = renderStub("resolverTest", "createItem");
|
|
51
|
+
expect(result).toContain('describe("createItem"');
|
|
52
|
+
expect(result).toContain('import("./createItem")');
|
|
53
|
+
expect(result).toContain("resolver.default");
|
|
54
|
+
});
|
|
55
|
+
});
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
function toPascal(name: string): string {
|
|
2
|
+
return name.charAt(0).toUpperCase() + name.slice(1);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
const templates = {
|
|
6
|
+
command: {
|
|
7
|
+
render: (name: string) => {
|
|
8
|
+
const inputType = `${toPascal(name)}Input`;
|
|
9
|
+
return `import { ok, type CommandContext } from "../../../shared";
|
|
10
|
+
import type { Transaction } from "../generated/kysely-tailordb";
|
|
11
|
+
|
|
12
|
+
export interface ${inputType} {
|
|
13
|
+
// TODO: define input fields
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function run(db: Transaction, input: ${inputType}, ctx: CommandContext) {
|
|
17
|
+
// TODO: implement
|
|
18
|
+
return ok({});
|
|
19
|
+
}
|
|
20
|
+
`;
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
commandTest: {
|
|
24
|
+
render: (name: string) => {
|
|
25
|
+
const pascal = toPascal(name);
|
|
26
|
+
return `import { describe, expect, it } from "vitest";
|
|
27
|
+
import { createMockDb } from "../../../testing/index";
|
|
28
|
+
import type { CommandContext } from "../../../shared";
|
|
29
|
+
import type { Transaction } from "../generated/kysely-tailordb";
|
|
30
|
+
import { run, ${pascal}Input } from "./${name}";
|
|
31
|
+
|
|
32
|
+
describe("${name} - test scenario", () => {
|
|
33
|
+
const ctx: CommandContext = {
|
|
34
|
+
actorId: "test-actor",
|
|
35
|
+
permissions: ["TODO:${name}"],
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
it("should be implemented", async () => {
|
|
39
|
+
const { db } = createMockDb<Transaction>();
|
|
40
|
+
const result = await run(db, {} as ${pascal}Input, ctx);
|
|
41
|
+
expect(result.ok).toBe(true);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
`;
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
query: {
|
|
48
|
+
render: (name: string) => {
|
|
49
|
+
const inputType = `${toPascal(name)}Input`;
|
|
50
|
+
return `import type { ReadonlyDB } from "../../../shared";
|
|
51
|
+
import type { DB } from "../generated/kysely-tailordb";
|
|
52
|
+
|
|
53
|
+
export interface ${inputType} {
|
|
54
|
+
// TODO: define input fields
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export async function run(db: ReadonlyDB<DB>, input: ${inputType}) {
|
|
58
|
+
// TODO: implement
|
|
59
|
+
return {};
|
|
60
|
+
}
|
|
61
|
+
`;
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
queryTest: {
|
|
65
|
+
render: (name: string) => {
|
|
66
|
+
const pascal = toPascal(name);
|
|
67
|
+
const inputType = `${pascal}Input`;
|
|
68
|
+
return `import { describe, expect, it } from "vitest";
|
|
69
|
+
import { createMockDb } from "../../../testing/index";
|
|
70
|
+
import type { DB } from "../generated/kysely-tailordb";
|
|
71
|
+
import { run, type ${inputType} } from "./${name}";
|
|
72
|
+
|
|
73
|
+
describe("${name}", () => {
|
|
74
|
+
it("should be implemented", async () => {
|
|
75
|
+
const { db } = createMockDb<DB>();
|
|
76
|
+
const result = await run(db, {} as ${inputType});
|
|
77
|
+
expect(result).toBeDefined();
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
`;
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
db: {
|
|
84
|
+
render: (name: string) => {
|
|
85
|
+
return `import { db, unsafeAllowAllGqlPermission, unsafeAllowAllTypePermission } from "@tailor-platform/sdk";
|
|
86
|
+
|
|
87
|
+
export const ${name} = db
|
|
88
|
+
.type("${toPascal(name)}", {
|
|
89
|
+
// TODO: define fields
|
|
90
|
+
...db.fields.timestamps(),
|
|
91
|
+
})
|
|
92
|
+
.permission(unsafeAllowAllTypePermission)
|
|
93
|
+
.gqlPermission(unsafeAllowAllGqlPermission);
|
|
94
|
+
`;
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
resolver: {
|
|
98
|
+
render: (name: string) => {
|
|
99
|
+
return `import { createResolver, t } from "@tailor-platform/sdk";
|
|
100
|
+
import { createContext } from "@tailor-platform/erp-kit/app";
|
|
101
|
+
import { getDB } from "@/generated/kysely-tailordb";
|
|
102
|
+
|
|
103
|
+
export default createResolver({
|
|
104
|
+
name: "${name}",
|
|
105
|
+
operation: "mutation",
|
|
106
|
+
input: {
|
|
107
|
+
// TODO: define input fields
|
|
108
|
+
},
|
|
109
|
+
body: async (context) => {
|
|
110
|
+
const db = getDB("main-db");
|
|
111
|
+
return db.transaction().execute(async (trx) => {
|
|
112
|
+
// TODO: implement
|
|
113
|
+
return {};
|
|
114
|
+
});
|
|
115
|
+
},
|
|
116
|
+
output: t
|
|
117
|
+
.object({
|
|
118
|
+
// TODO: define output fields
|
|
119
|
+
})
|
|
120
|
+
.description("${toPascal(name)} response"),
|
|
121
|
+
});
|
|
122
|
+
`;
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
resolverTest: {
|
|
126
|
+
render: (name: string) => {
|
|
127
|
+
return `import { describe, expect, it } from "vitest";
|
|
128
|
+
|
|
129
|
+
describe("${name}", () => {
|
|
130
|
+
it("should be implemented", async () => {
|
|
131
|
+
const resolver = await import("./${name}");
|
|
132
|
+
expect(resolver.default).toBeDefined();
|
|
133
|
+
expect(resolver.default.name).toBe("${name}");
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
`;
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
} as const;
|
|
140
|
+
|
|
141
|
+
export type StubType = keyof typeof templates;
|
|
142
|
+
|
|
143
|
+
export function renderStub(type: StubType, name: string): string {
|
|
144
|
+
return templates[type].render(name);
|
|
145
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# README
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The Audit module provides a centralized, append-only audit trail for tracking data changes across all ERP modules. It records who or what performed an action, when it occurred, and what data changed — capturing both the old and new values at the field level. The module is designed as cross-cutting infrastructure: other modules emit structured audit events that the Audit module stores, indexes, and exposes for query. All audit entries are append-only and immutable once written, ensuring that stored records cannot be retroactively altered or deleted. Note: because ingestion is eventually consistent and decoupled from the emitting module's transaction, the module provides best-effort delivery — it does not guarantee that every mutation is captured (see [Audit Event Logging](docs/features/audit-event-logging.md) for the ingestion contract and failure semantics).
|
|
6
|
+
|
|
7
|
+
The module supports both company-scoped entities (e.g., sales orders, invoices) and global entities (e.g., user accounts, currencies) — entries for global entities omit companyId and are queryable without company scope.
|
|
8
|
+
|
|
9
|
+
Access to audit data and policy management is controlled by explicit permissions. Because audit entries can contain sensitive before/after values, viewing and administering the audit trail requires dedicated privileges separate from the permissions on the audited entities themselves. The module defines four coarse permissions: `viewAuditHistory` (query audit entries and change details), `viewAuditSummary` (view aggregated audit summaries without field-level details), `manageAuditPolicies` (create, update, activate, deactivate, delete audit policies, query policies, and register auditable entities), and `logAuditEvent` (ingest audit events from emitting modules). At runtime, command shells enforce per-command permission keys (e.g., `audit:createAuditPolicy`, `audit:registerAuditableEntity`), and policy query endpoints (`getAuditPolicy`, `listAuditPolicies`) require the coarse `audit:manageAuditPolicies` key directly. The `manageAuditPolicies` alias (defined in `permissions.ts`) expands to both the coarse `manageAuditPolicies` key itself and all per-command keys; the application's RBAC layer should use this alias when populating `ctx.permissions` to ensure both command and query authorization work correctly. Each permission is company-scoped — holders can only access entries and policies for their assigned companies — or global-scoped for company-unscoped entries and policies. The audit module does not define its own roles; it exposes permissions that the application's role-based access control system assigns to roles as needed.
|
|
10
|
+
|
|
11
|
+
## Key Features
|
|
12
|
+
|
|
13
|
+
- **Audit Event Logging** — Captures create, update, and delete operations as immutable audit entries with unique eventId, optional correlationId for operation grouping, actor identity (actorType + actorId), timestamp, entity reference, and operation type
|
|
14
|
+
- **Field-Level Change Tracking** — Records old and new values for each changed field within an audit entry, with configurable sensitivity modes (capture, mask, hash, exclude) to protect sensitive data
|
|
15
|
+
- **Audit Policy Configuration** — Allows administrators to define which entities, fields, and operation types are audited, controlling granularity, sensitivity handling, and performance impact
|
|
16
|
+
|
|
17
|
+
## Module Scope
|
|
18
|
+
|
|
19
|
+
### In Scope
|
|
20
|
+
|
|
21
|
+
- Immutable storage of audit log entries (append-only, no update or delete)
|
|
22
|
+
- Field-level change detail recording (old value / new value pairs) with sensitivity-aware value processing
|
|
23
|
+
- Configurable audit policies at entity and field granularity with sensitivity modes
|
|
24
|
+
- Query and filtering of audit logs by actor, entity, record, operation type, and date range
|
|
25
|
+
- Record-level change history retrieval
|
|
26
|
+
- Actor identity capture supporting multiple actor types (USER, SYSTEM, SERVICE) with optional delegation (onBehalfOf)
|
|
27
|
+
- Company-scoped and global (company-unscoped) audit entries
|
|
28
|
+
- Permission-based access control for audit viewing and policy administration
|
|
29
|
+
|
|
30
|
+
### Out of Scope
|
|
31
|
+
|
|
32
|
+
- User authentication and session tracking (owned by user-management / infrastructure layer)
|
|
33
|
+
- Compliance framework mapping and automated evidence collection (application-level concern)
|
|
34
|
+
- Anomaly detection, alerting, and real-time notifications
|
|
35
|
+
- Log archival, long-term retention policies, and storage tiering
|
|
36
|
+
- Dashboard visualizations and audit analytics
|
|
37
|
+
|
|
38
|
+
### Scope Decision Rationale
|
|
39
|
+
|
|
40
|
+
The module focuses on the foundational audit trail capabilities that all ERP deployments require: capturing changes, storing them immutably once written, and making them queryable. The ingestion contract is best-effort — applications that require guaranteed delivery for strict compliance scenarios should layer an outbox or replay mechanism on top of this module. Authentication logging is excluded because it belongs to the identity/infrastructure layer, not the domain data change layer. Compliance framework mapping, anomaly detection, and retention management are excluded as application-level or operational concerns that can be layered on top of the core audit trail. This separation keeps the module focused, testable, and reusable across different compliance contexts.
|
|
41
|
+
|
|
42
|
+
## Module Dependencies
|
|
43
|
+
|
|
44
|
+
- **user-management** — References userId as one type of actorId on audit entries (data reference only; no domain logic dependency)
|
|
45
|
+
- **organization** — References companyId for multi-company scoping of company-bound audit entries (data reference only; companyId is optional for global entities)
|
|
46
|
+
- **all emitting modules** (reverse dependency) — The audit module is cross-cutting: other modules depend on it, not the other way around. Emitting modules register their auditable entities (name, scope, field list) at initialization time and submit structured audit event payloads (including a unique `eventId` for idempotency) after committing their own transactions. The ingestion contract is idempotent on `eventId` for safe retries, and the audit module does not participate in the emitting module's transaction (eventually consistent). See the [Audit Event Logging](docs/features/audit-event-logging.md) feature documentation for the full ingestion contract.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// @generated — do not edit
|
|
2
|
+
import { defineCommand } from "../../../shared";
|
|
3
|
+
import { permissions } from "../lib/permissions.generated";
|
|
4
|
+
import { run } from "./activateAuditPolicy";
|
|
5
|
+
|
|
6
|
+
export const activateAuditPolicy = defineCommand(permissions.activateAuditPolicy, run);
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { createMockDb } from "../../../testing/index";
|
|
3
|
+
import { type CommandContext, InsufficientPermissionError } from "../../../shared";
|
|
4
|
+
import type { Transaction } from "../generated/kysely-tailordb";
|
|
5
|
+
import {
|
|
6
|
+
PolicyNotFoundError,
|
|
7
|
+
InvalidStateError,
|
|
8
|
+
IncompletePolicyError,
|
|
9
|
+
ConflictingActivePolicyError,
|
|
10
|
+
EntityTypeNotRegisteredError,
|
|
11
|
+
UnauthorizedError,
|
|
12
|
+
} from "../lib/errors.generated";
|
|
13
|
+
import { draftPolicy, activePolicy, inactivePolicy, companyBoundEntity } from "../testing/fixtures";
|
|
14
|
+
import { run } from "./activateAuditPolicy";
|
|
15
|
+
import { activateAuditPolicy } from "./activateAuditPolicy.generated";
|
|
16
|
+
|
|
17
|
+
const ctx: CommandContext = {
|
|
18
|
+
actorId: "test-actor",
|
|
19
|
+
permissions: ["audit:activateAuditPolicy"],
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
describe("activateAuditPolicy", () => {
|
|
23
|
+
it("activates DRAFT policy to ACTIVE", async () => {
|
|
24
|
+
const { db, spies } = createMockDb<Transaction>();
|
|
25
|
+
spies.select.mockReturnValueOnce(draftPolicy); // policy lookup
|
|
26
|
+
spies.select.mockReturnValueOnce(companyBoundEntity); // entity registration check
|
|
27
|
+
spies.select.mockReturnValueOnce(undefined); // no conflicting policy
|
|
28
|
+
spies.update.mockReturnValue({ ...draftPolicy, status: "ACTIVE" });
|
|
29
|
+
|
|
30
|
+
const result = await run(db, { policyId: "policy-1" }, ctx);
|
|
31
|
+
|
|
32
|
+
expect(result.ok).toBe(true);
|
|
33
|
+
if (result.ok) {
|
|
34
|
+
expect(result.value.policy.status).toBe("ACTIVE");
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("begins audit capture after activation", async () => {
|
|
39
|
+
const { db, spies } = createMockDb<Transaction>();
|
|
40
|
+
spies.select.mockReturnValueOnce(draftPolicy);
|
|
41
|
+
spies.select.mockReturnValueOnce(companyBoundEntity); // entity registration check
|
|
42
|
+
spies.select.mockReturnValueOnce(undefined);
|
|
43
|
+
spies.update.mockReturnValue({ ...draftPolicy, status: "ACTIVE" });
|
|
44
|
+
|
|
45
|
+
const result = await run(db, { policyId: "policy-1" }, ctx);
|
|
46
|
+
|
|
47
|
+
expect(result.ok).toBe(true);
|
|
48
|
+
if (result.ok) {
|
|
49
|
+
expect(result.value.policy.status).toBe("ACTIVE");
|
|
50
|
+
}
|
|
51
|
+
// Verify that the DB update sets status to ACTIVE, which is the gate for logAuditEvent to capture events
|
|
52
|
+
expect(spies.set).toHaveBeenCalledWith(expect.objectContaining({ status: "ACTIVE" }));
|
|
53
|
+
expect(spies.update).toHaveBeenCalledTimes(1);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("rejects activation of ACTIVE policy", async () => {
|
|
57
|
+
const { db, spies } = createMockDb<Transaction>();
|
|
58
|
+
spies.select.mockReturnValueOnce(activePolicy);
|
|
59
|
+
|
|
60
|
+
const result = await run(db, { policyId: activePolicy.id }, ctx);
|
|
61
|
+
|
|
62
|
+
expect(result.ok).toBe(false);
|
|
63
|
+
if (!result.ok) {
|
|
64
|
+
expect(result.error).toBeInstanceOf(InvalidStateError);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("rejects activation of INACTIVE policy", async () => {
|
|
69
|
+
const { db, spies } = createMockDb<Transaction>();
|
|
70
|
+
spies.select.mockReturnValueOnce(inactivePolicy);
|
|
71
|
+
|
|
72
|
+
const result = await run(db, { policyId: inactivePolicy.id }, ctx);
|
|
73
|
+
|
|
74
|
+
expect(result.ok).toBe(false);
|
|
75
|
+
if (!result.ok) {
|
|
76
|
+
expect(result.error).toBeInstanceOf(InvalidStateError);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("rejects activation when conflicting ACTIVE policy exists", async () => {
|
|
81
|
+
const { db, spies } = createMockDb<Transaction>();
|
|
82
|
+
spies.select.mockReturnValueOnce(draftPolicy); // policy lookup
|
|
83
|
+
spies.select.mockReturnValueOnce(companyBoundEntity); // entity registration check
|
|
84
|
+
spies.select.mockReturnValueOnce(activePolicy); // conflicting policy
|
|
85
|
+
|
|
86
|
+
const result = await run(db, { policyId: "policy-1" }, ctx);
|
|
87
|
+
|
|
88
|
+
expect(result.ok).toBe(false);
|
|
89
|
+
if (!result.ok) {
|
|
90
|
+
expect(result.error).toBeInstanceOf(ConflictingActivePolicyError);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("rejects activation when entity name is missing", async () => {
|
|
95
|
+
const { db, spies } = createMockDb<Transaction>();
|
|
96
|
+
const policyNoEntity = { ...draftPolicy, entityName: "" };
|
|
97
|
+
spies.select.mockReturnValueOnce(policyNoEntity);
|
|
98
|
+
|
|
99
|
+
const result = await run(db, { policyId: "policy-1" }, ctx);
|
|
100
|
+
|
|
101
|
+
expect(result.ok).toBe(false);
|
|
102
|
+
if (!result.ok) {
|
|
103
|
+
expect(result.error).toBeInstanceOf(IncompletePolicyError);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it("rejects activation when operation type is missing", async () => {
|
|
108
|
+
const { db, spies } = createMockDb<Transaction>();
|
|
109
|
+
const policyNoOp = { ...draftPolicy, operationType: "" };
|
|
110
|
+
spies.select.mockReturnValueOnce(policyNoOp);
|
|
111
|
+
|
|
112
|
+
const result = await run(db, { policyId: "policy-1" }, ctx);
|
|
113
|
+
|
|
114
|
+
expect(result.ok).toBe(false);
|
|
115
|
+
if (!result.ok) {
|
|
116
|
+
expect(result.error).toBeInstanceOf(IncompletePolicyError);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it("rejects when policy does not exist", async () => {
|
|
121
|
+
const { db, spies } = createMockDb<Transaction>();
|
|
122
|
+
spies.select.mockReturnValueOnce(undefined);
|
|
123
|
+
|
|
124
|
+
const result = await run(db, { policyId: "nonexistent" }, ctx);
|
|
125
|
+
|
|
126
|
+
expect(result.ok).toBe(false);
|
|
127
|
+
if (!result.ok) {
|
|
128
|
+
expect(result.error).toBeInstanceOf(PolicyNotFoundError);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("rejects when caller lacks manageAuditPolicies permission", async () => {
|
|
133
|
+
const { db } = createMockDb<Transaction>();
|
|
134
|
+
const command = activateAuditPolicy();
|
|
135
|
+
const noPermCtx: CommandContext = {
|
|
136
|
+
actorId: "test-actor",
|
|
137
|
+
permissions: [],
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const result = await command(db, { policyId: "policy-1" }, noPermCtx);
|
|
141
|
+
|
|
142
|
+
expect(result.ok).toBe(false);
|
|
143
|
+
if (!result.ok) {
|
|
144
|
+
expect(result.error).toBeInstanceOf(InsufficientPermissionError);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it("rejects when company-scoped caller activates policy for a different company", async () => {
|
|
149
|
+
const { db, spies } = createMockDb<Transaction>();
|
|
150
|
+
spies.select.mockReturnValueOnce(draftPolicy); // policy with companyId: "company-1"
|
|
151
|
+
const scopedCtx = { ...ctx, companyId: "company-2" };
|
|
152
|
+
|
|
153
|
+
const result = await run(db, { policyId: "policy-1" }, scopedCtx);
|
|
154
|
+
|
|
155
|
+
expect(result.ok).toBe(false);
|
|
156
|
+
if (!result.ok) {
|
|
157
|
+
expect(result.error).toBeInstanceOf(UnauthorizedError);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it("rejects when global-scoped caller activates company-scoped policy", async () => {
|
|
162
|
+
const { db, spies } = createMockDb<Transaction>();
|
|
163
|
+
spies.select.mockReturnValueOnce(draftPolicy); // policy with companyId: "company-1"
|
|
164
|
+
const globalCtx = { ...ctx, companyId: null };
|
|
165
|
+
|
|
166
|
+
const result = await run(db, { policyId: "policy-1" }, globalCtx);
|
|
167
|
+
|
|
168
|
+
expect(result.ok).toBe(false);
|
|
169
|
+
if (!result.ok) {
|
|
170
|
+
expect(result.error).toBeInstanceOf(UnauthorizedError);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it("rejects when target entity is no longer registered", async () => {
|
|
175
|
+
const { db, spies } = createMockDb<Transaction>();
|
|
176
|
+
spies.select.mockReturnValueOnce(draftPolicy); // policy lookup
|
|
177
|
+
spies.select.mockReturnValueOnce(undefined); // entity not found
|
|
178
|
+
|
|
179
|
+
const result = await run(db, { policyId: "policy-1" }, ctx);
|
|
180
|
+
|
|
181
|
+
expect(result.ok).toBe(false);
|
|
182
|
+
if (!result.ok) {
|
|
183
|
+
expect(result.error).toBeInstanceOf(EntityTypeNotRegisteredError);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
});
|