@tailor-platform/erp-kit 0.6.0 → 0.7.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 +14 -0
- package/README.md +10 -10
- package/dist/cli.mjs +407 -69
- package/package.json +1 -1
- package/skills/erp-kit-app-1-requirements/SKILL.md +33 -17
- package/skills/erp-kit-app-2-requirements-review/SKILL.md +12 -0
- package/skills/erp-kit-app-3-plan/SKILL.md +18 -4
- package/skills/erp-kit-app-3-plan/references/resolver-extraction.md +1 -1
- package/skills/erp-kit-app-3-plan/references/screen-extraction.md +1 -1
- package/skills/erp-kit-app-4-plan-review/SKILL.md +12 -0
- package/skills/erp-kit-app-5-impl-backend/SKILL.md +12 -0
- package/skills/erp-kit-app-6-impl-frontend/SKILL.md +12 -0
- package/skills/erp-kit-app-7-impl-review/SKILL.md +13 -1
- package/skills/erp-kit-app-shared/references/progress-protocol.md +77 -0
- package/skills/erp-kit-mock-scenario/SKILL.md +1 -1
- package/skills/erp-kit-module-1-requirements/SKILL.md +1 -1
- package/skills/erp-kit-module-3-plan/SKILL.md +3 -3
- package/skills/erp-kit-module-3-update-plan/SKILL.md +3 -3
- package/skills/erp-kit-module-5-impl/SKILL.md +1 -1
- package/src/commands/app/index.ts +2 -0
- package/src/commands/app/progress/git-context.ts +16 -0
- package/src/commands/app/progress/index.ts +45 -0
- package/src/commands/app/progress/log.ts +49 -0
- package/src/commands/app/progress/progress.test.ts +128 -0
- package/src/commands/app/progress/schema-cmd.ts +10 -0
- package/src/commands/check.test.ts +4 -4
- package/src/commands/lib/discovery.test.ts +5 -7
- package/src/commands/lib/discovery.ts +8 -8
- package/src/commands/lib/sync-check-source.test.ts +1 -1
- package/src/commands/lib/sync-check-source.ts +6 -1
- package/src/commands/lib/sync-check-tests.test.ts +43 -0
- package/src/commands/lib/sync-check-tests.ts +20 -2
- package/src/commands/sync-check.ts +3 -0
- package/src/generator/generate-app-code.test.ts +0 -6
- package/src/generator/generate-app-code.ts +3 -13
- package/src/generator/generate-code.test.ts +10 -40
- package/src/generator/generate-code.ts +6 -12
- package/src/generator/stub-templates.test.ts +0 -7
- package/src/generator/stub-templates.ts +0 -14
- package/src/modules/finance-ledger/README.md +50 -0
- package/src/modules/finance-ledger/command/.gitkeep +0 -0
- package/src/modules/finance-ledger/command/addJournalLine.generated.ts +6 -0
- package/src/modules/finance-ledger/command/addJournalLine.test.ts +438 -0
- package/src/modules/finance-ledger/command/addJournalLine.ts +122 -0
- package/src/modules/finance-ledger/command/approveAndLockPeriod.generated.ts +6 -0
- package/src/modules/finance-ledger/command/approveAndLockPeriod.test.ts +107 -0
- package/src/modules/finance-ledger/command/approveAndLockPeriod.ts +72 -0
- package/src/modules/finance-ledger/command/beginClose.generated.ts +6 -0
- package/src/modules/finance-ledger/command/beginClose.test.ts +106 -0
- package/src/modules/finance-ledger/command/beginClose.ts +58 -0
- package/src/modules/finance-ledger/command/closePeriod.generated.ts +6 -0
- package/src/modules/finance-ledger/command/closePeriod.test.ts +87 -0
- package/src/modules/finance-ledger/command/closePeriod.ts +44 -0
- package/src/modules/finance-ledger/command/createAccountingPeriod.generated.ts +6 -0
- package/src/modules/finance-ledger/command/createAccountingPeriod.test.ts +425 -0
- package/src/modules/finance-ledger/command/createAccountingPeriod.ts +133 -0
- package/src/modules/finance-ledger/command/createFiscalYear.generated.ts +6 -0
- package/src/modules/finance-ledger/command/createFiscalYear.test.ts +197 -0
- package/src/modules/finance-ledger/command/createFiscalYear.ts +70 -0
- package/src/modules/finance-ledger/command/createJournalEntry.generated.ts +6 -0
- package/src/modules/finance-ledger/command/createJournalEntry.test.ts +261 -0
- package/src/modules/finance-ledger/command/createJournalEntry.ts +121 -0
- package/src/modules/finance-ledger/command/deleteAccountingPeriod.generated.ts +6 -0
- package/src/modules/finance-ledger/command/deleteAccountingPeriod.test.ts +71 -0
- package/src/modules/finance-ledger/command/deleteAccountingPeriod.ts +55 -0
- package/src/modules/finance-ledger/command/deleteFiscalYear.generated.ts +6 -0
- package/src/modules/finance-ledger/command/deleteFiscalYear.test.ts +38 -0
- package/src/modules/finance-ledger/command/deleteFiscalYear.ts +34 -0
- package/src/modules/finance-ledger/command/deleteJournalEntry.generated.ts +6 -0
- package/src/modules/finance-ledger/command/deleteJournalEntry.test.ts +58 -0
- package/src/modules/finance-ledger/command/deleteJournalEntry.ts +43 -0
- package/src/modules/finance-ledger/command/executeYearEndClose.generated.ts +6 -0
- package/src/modules/finance-ledger/command/executeYearEndClose.test.ts +239 -0
- package/src/modules/finance-ledger/command/executeYearEndClose.ts +415 -0
- package/src/modules/finance-ledger/command/finalCloseAndLockPeriod.generated.ts +6 -0
- package/src/modules/finance-ledger/command/finalCloseAndLockPeriod.test.ts +102 -0
- package/src/modules/finance-ledger/command/finalCloseAndLockPeriod.ts +76 -0
- package/src/modules/finance-ledger/command/finalizeFinancialStatement.generated.ts +6 -0
- package/src/modules/finance-ledger/command/finalizeFinancialStatement.test.ts +73 -0
- package/src/modules/finance-ledger/command/finalizeFinancialStatement.ts +73 -0
- package/src/modules/finance-ledger/command/generateFinancialStatement.generated.ts +6 -0
- package/src/modules/finance-ledger/command/generateFinancialStatement.test.ts +311 -0
- package/src/modules/finance-ledger/command/generateFinancialStatement.ts +275 -0
- package/src/modules/finance-ledger/command/generatePreliminaryStatements.generated.ts +6 -0
- package/src/modules/finance-ledger/command/generatePreliminaryStatements.test.ts +152 -0
- package/src/modules/finance-ledger/command/generatePreliminaryStatements.ts +140 -0
- package/src/modules/finance-ledger/command/generateTrialBalance.generated.ts +6 -0
- package/src/modules/finance-ledger/command/generateTrialBalance.test.ts +439 -0
- package/src/modules/finance-ledger/command/generateTrialBalance.ts +268 -0
- package/src/modules/finance-ledger/command/initiatePeriodClose.generated.ts +6 -0
- package/src/modules/finance-ledger/command/initiatePeriodClose.test.ts +153 -0
- package/src/modules/finance-ledger/command/initiatePeriodClose.ts +84 -0
- package/src/modules/finance-ledger/command/openForAdvanceEntry.generated.ts +6 -0
- package/src/modules/finance-ledger/command/openForAdvanceEntry.test.ts +87 -0
- package/src/modules/finance-ledger/command/openForAdvanceEntry.ts +44 -0
- package/src/modules/finance-ledger/command/openPeriod.generated.ts +6 -0
- package/src/modules/finance-ledger/command/openPeriod.test.ts +90 -0
- package/src/modules/finance-ledger/command/openPeriod.ts +44 -0
- package/src/modules/finance-ledger/command/permanentlyClosePeriod.generated.ts +6 -0
- package/src/modules/finance-ledger/command/permanentlyClosePeriod.test.ts +87 -0
- package/src/modules/finance-ledger/command/permanentlyClosePeriod.ts +48 -0
- package/src/modules/finance-ledger/command/postAdjustingEntries.generated.ts +6 -0
- package/src/modules/finance-ledger/command/postAdjustingEntries.test.ts +392 -0
- package/src/modules/finance-ledger/command/postAdjustingEntries.ts +156 -0
- package/src/modules/finance-ledger/command/postJournalEntry.generated.ts +6 -0
- package/src/modules/finance-ledger/command/postJournalEntry.test.ts +346 -0
- package/src/modules/finance-ledger/command/postJournalEntry.ts +160 -0
- package/src/modules/finance-ledger/command/processInventoryHandoff.generated.ts +6 -0
- package/src/modules/finance-ledger/command/processInventoryHandoff.test.ts +211 -0
- package/src/modules/finance-ledger/command/processInventoryHandoff.ts +133 -0
- package/src/modules/finance-ledger/command/processManufacturingHandoff.generated.ts +6 -0
- package/src/modules/finance-ledger/command/processManufacturingHandoff.test.ts +221 -0
- package/src/modules/finance-ledger/command/processManufacturingHandoff.ts +133 -0
- package/src/modules/finance-ledger/command/processPurchaseHandoff.generated.ts +6 -0
- package/src/modules/finance-ledger/command/processPurchaseHandoff.test.ts +222 -0
- package/src/modules/finance-ledger/command/processPurchaseHandoff.ts +133 -0
- package/src/modules/finance-ledger/command/processSalesHandoff.generated.ts +6 -0
- package/src/modules/finance-ledger/command/processSalesHandoff.test.ts +257 -0
- package/src/modules/finance-ledger/command/processSalesHandoff.ts +135 -0
- package/src/modules/finance-ledger/command/regenerateFinancialStatement.generated.ts +6 -0
- package/src/modules/finance-ledger/command/regenerateFinancialStatement.test.ts +129 -0
- package/src/modules/finance-ledger/command/regenerateFinancialStatement.ts +186 -0
- package/src/modules/finance-ledger/command/removeJournalLine.generated.ts +6 -0
- package/src/modules/finance-ledger/command/removeJournalLine.test.ts +65 -0
- package/src/modules/finance-ledger/command/removeJournalLine.ts +39 -0
- package/src/modules/finance-ledger/command/reopenPeriod.generated.ts +6 -0
- package/src/modules/finance-ledger/command/reopenPeriod.test.ts +87 -0
- package/src/modules/finance-ledger/command/reopenPeriod.ts +44 -0
- package/src/modules/finance-ledger/command/reverseJournalEntry.generated.ts +6 -0
- package/src/modules/finance-ledger/command/reverseJournalEntry.test.ts +337 -0
- package/src/modules/finance-ledger/command/reverseJournalEntry.ts +140 -0
- package/src/modules/finance-ledger/command/revertSoftLock.generated.ts +6 -0
- package/src/modules/finance-ledger/command/revertSoftLock.test.ts +96 -0
- package/src/modules/finance-ledger/command/revertSoftLock.ts +67 -0
- package/src/modules/finance-ledger/command/updateFiscalYear.generated.ts +6 -0
- package/src/modules/finance-ledger/command/updateFiscalYear.test.ts +138 -0
- package/src/modules/finance-ledger/command/updateFiscalYear.ts +85 -0
- package/src/modules/finance-ledger/command/updateJournalEntry.generated.ts +6 -0
- package/src/modules/finance-ledger/command/updateJournalEntry.test.ts +195 -0
- package/src/modules/finance-ledger/command/updateJournalEntry.ts +86 -0
- package/src/modules/finance-ledger/command/updateJournalLine.generated.ts +6 -0
- package/src/modules/finance-ledger/command/updateJournalLine.test.ts +385 -0
- package/src/modules/finance-ledger/command/updateJournalLine.ts +155 -0
- package/src/modules/finance-ledger/command/verifySubledgerTransfers.generated.ts +6 -0
- package/src/modules/finance-ledger/command/verifySubledgerTransfers.test.ts +201 -0
- package/src/modules/finance-ledger/command/verifySubledgerTransfers.ts +113 -0
- package/src/modules/finance-ledger/command/verifyTrialBalance.generated.ts +6 -0
- package/src/modules/finance-ledger/command/verifyTrialBalance.test.ts +136 -0
- package/src/modules/finance-ledger/command/verifyTrialBalance.ts +97 -0
- package/src/modules/finance-ledger/db/.gitkeep +0 -0
- package/src/modules/finance-ledger/db/accountingPeriod.ts +58 -0
- package/src/modules/finance-ledger/db/financialStatement.ts +92 -0
- package/src/modules/finance-ledger/db/financialStatementLineItem.ts +76 -0
- package/src/modules/finance-ledger/db/fiscalYear.ts +41 -0
- package/src/modules/finance-ledger/db/journalEntry.ts +101 -0
- package/src/modules/finance-ledger/db/journalLine.ts +64 -0
- package/src/modules/finance-ledger/db/periodClose.ts +97 -0
- package/src/modules/finance-ledger/db/trialBalance.ts +63 -0
- package/src/modules/finance-ledger/db/trialBalanceLine.ts +63 -0
- package/src/modules/finance-ledger/docs/commands/AddJournalLine.md +74 -0
- package/src/modules/finance-ledger/docs/commands/ApproveAndLockPeriod.md +53 -0
- package/src/modules/finance-ledger/docs/commands/BeginClose.md +47 -0
- package/src/modules/finance-ledger/docs/commands/ClosePeriod.md +45 -0
- package/src/modules/finance-ledger/docs/commands/CreateAccountingPeriod.md +69 -0
- package/src/modules/finance-ledger/docs/commands/CreateFiscalYear.md +56 -0
- package/src/modules/finance-ledger/docs/commands/CreateJournalEntry.md +63 -0
- package/src/modules/finance-ledger/docs/commands/DeleteAccountingPeriod.md +46 -0
- package/src/modules/finance-ledger/docs/commands/DeleteFiscalYear.md +40 -0
- package/src/modules/finance-ledger/docs/commands/DeleteJournalEntry.md +44 -0
- package/src/modules/finance-ledger/docs/commands/ExecuteYearEndClose.md +81 -0
- package/src/modules/finance-ledger/docs/commands/FinalCloseAndLockPeriod.md +49 -0
- package/src/modules/finance-ledger/docs/commands/FinalizeFinancialStatement.md +43 -0
- package/src/modules/finance-ledger/docs/commands/GenerateFinancialStatement.md +86 -0
- package/src/modules/finance-ledger/docs/commands/GeneratePreliminaryStatements.md +53 -0
- package/src/modules/finance-ledger/docs/commands/GenerateTrialBalance.md +75 -0
- package/src/modules/finance-ledger/docs/commands/InitiatePeriodClose.md +58 -0
- package/src/modules/finance-ledger/docs/commands/OpenForAdvanceEntry.md +44 -0
- package/src/modules/finance-ledger/docs/commands/OpenPeriod.md +45 -0
- package/src/modules/finance-ledger/docs/commands/PermanentlyClosePeriod.md +45 -0
- package/src/modules/finance-ledger/docs/commands/PostAdjustingEntries.md +61 -0
- package/src/modules/finance-ledger/docs/commands/PostJournalEntry.md +81 -0
- package/src/modules/finance-ledger/docs/commands/ProcessInventoryHandoff.md +72 -0
- package/src/modules/finance-ledger/docs/commands/ProcessManufacturingHandoff.md +68 -0
- package/src/modules/finance-ledger/docs/commands/ProcessPurchaseHandoff.md +68 -0
- package/src/modules/finance-ledger/docs/commands/ProcessSalesHandoff.md +71 -0
- package/src/modules/finance-ledger/docs/commands/RegenerateFinancialStatement.md +60 -0
- package/src/modules/finance-ledger/docs/commands/RemoveJournalLine.md +42 -0
- package/src/modules/finance-ledger/docs/commands/ReopenPeriod.md +45 -0
- package/src/modules/finance-ledger/docs/commands/ReverseJournalEntry.md +62 -0
- package/src/modules/finance-ledger/docs/commands/RevertSoftLock.md +49 -0
- package/src/modules/finance-ledger/docs/commands/UpdateFiscalYear.md +60 -0
- package/src/modules/finance-ledger/docs/commands/UpdateJournalEntry.md +50 -0
- package/src/modules/finance-ledger/docs/commands/UpdateJournalLine.md +61 -0
- package/src/modules/finance-ledger/docs/commands/VerifySubledgerTransfers.md +59 -0
- package/src/modules/finance-ledger/docs/commands/VerifyTrialBalance.md +53 -0
- package/src/modules/finance-ledger/docs/features/accounting-period-management.md +110 -0
- package/src/modules/finance-ledger/docs/features/financial-statement-generation.md +115 -0
- package/src/modules/finance-ledger/docs/features/journal-entry-management.md +138 -0
- package/src/modules/finance-ledger/docs/features/period-end-close.md +102 -0
- package/src/modules/finance-ledger/docs/features/subledger-integration.md +141 -0
- package/src/modules/finance-ledger/docs/features/trial-balance.md +99 -0
- package/src/modules/finance-ledger/docs/features/year-end-close.md +84 -0
- package/src/modules/finance-ledger/docs/models/AccountingPeriod.md +71 -0
- package/src/modules/finance-ledger/docs/models/FinancialStatement.md +76 -0
- package/src/modules/finance-ledger/docs/models/FinancialStatementLineItem.md +41 -0
- package/src/modules/finance-ledger/docs/models/FiscalYear.md +41 -0
- package/src/modules/finance-ledger/docs/models/JournalEntry.md +80 -0
- package/src/modules/finance-ledger/docs/models/JournalLine.md +47 -0
- package/src/modules/finance-ledger/docs/models/PeriodClose.md +83 -0
- package/src/modules/finance-ledger/docs/models/TrialBalance.md +56 -0
- package/src/modules/finance-ledger/docs/models/TrialBalanceLine.md +37 -0
- package/src/modules/finance-ledger/docs/queries/GetAccountingPeriod.md +35 -0
- package/src/modules/finance-ledger/docs/queries/GetFinancialStatement.md +38 -0
- package/src/modules/finance-ledger/docs/queries/GetFiscalYear.md +35 -0
- package/src/modules/finance-ledger/docs/queries/GetJournalEntry.md +37 -0
- package/src/modules/finance-ledger/docs/queries/GetPeriodByDate.md +38 -0
- package/src/modules/finance-ledger/docs/queries/GetPeriodClose.md +36 -0
- package/src/modules/finance-ledger/docs/queries/GetSubledgerTransferStatus.md +45 -0
- package/src/modules/finance-ledger/docs/queries/GetTrialBalance.md +38 -0
- package/src/modules/finance-ledger/docs/queries/ListAccountingPeriods.md +46 -0
- package/src/modules/finance-ledger/docs/queries/ListFinancialStatements.md +46 -0
- package/src/modules/finance-ledger/docs/queries/ListFiscalYears.md +42 -0
- package/src/modules/finance-ledger/docs/queries/ListJournalEntries.md +48 -0
- package/src/modules/finance-ledger/docs/queries/ListPeriodCloses.md +46 -0
- package/src/modules/finance-ledger/docs/queries/ListTrialBalances.md +51 -0
- package/src/modules/finance-ledger/executor/.gitkeep +0 -0
- package/src/modules/finance-ledger/generated/enums.ts +109 -0
- package/src/modules/finance-ledger/generated/kysely-tailordb.ts +202 -0
- package/src/modules/finance-ledger/index.ts +2 -0
- package/src/modules/finance-ledger/lib/_db_deps.ts +56 -0
- package/src/modules/finance-ledger/lib/errors.generated.ts +332 -0
- package/src/modules/finance-ledger/lib/permissions.generated.ts +41 -0
- package/src/modules/finance-ledger/lib/types.ts +66 -0
- package/src/modules/finance-ledger/module.ts +262 -0
- package/src/modules/finance-ledger/package.json +26 -0
- package/src/modules/finance-ledger/permissions.ts +3 -0
- package/src/modules/finance-ledger/query/.gitkeep +0 -0
- package/src/modules/finance-ledger/query/getAccountingPeriod.generated.ts +5 -0
- package/src/modules/finance-ledger/query/getAccountingPeriod.test.ts +31 -0
- package/src/modules/finance-ledger/query/getAccountingPeriod.ts +21 -0
- package/src/modules/finance-ledger/query/getFinancialStatement.generated.ts +5 -0
- package/src/modules/finance-ledger/query/getFinancialStatement.test.ts +35 -0
- package/src/modules/finance-ledger/query/getFinancialStatement.ts +29 -0
- package/src/modules/finance-ledger/query/getFiscalYear.generated.ts +5 -0
- package/src/modules/finance-ledger/query/getFiscalYear.test.ts +31 -0
- package/src/modules/finance-ledger/query/getFiscalYear.ts +21 -0
- package/src/modules/finance-ledger/query/getJournalEntry.generated.ts +5 -0
- package/src/modules/finance-ledger/query/getJournalEntry.test.ts +35 -0
- package/src/modules/finance-ledger/query/getJournalEntry.ts +29 -0
- package/src/modules/finance-ledger/query/getPeriodByDate.generated.ts +5 -0
- package/src/modules/finance-ledger/query/getPeriodByDate.test.ts +53 -0
- package/src/modules/finance-ledger/query/getPeriodByDate.ts +27 -0
- package/src/modules/finance-ledger/query/getPeriodClose.generated.ts +5 -0
- package/src/modules/finance-ledger/query/getPeriodClose.test.ts +31 -0
- package/src/modules/finance-ledger/query/getPeriodClose.ts +21 -0
- package/src/modules/finance-ledger/query/getSubledgerTransferStatus.generated.ts +5 -0
- package/src/modules/finance-ledger/query/getSubledgerTransferStatus.test.ts +101 -0
- package/src/modules/finance-ledger/query/getSubledgerTransferStatus.ts +68 -0
- package/src/modules/finance-ledger/query/getTrialBalance.generated.ts +5 -0
- package/src/modules/finance-ledger/query/getTrialBalance.test.ts +33 -0
- package/src/modules/finance-ledger/query/getTrialBalance.ts +30 -0
- package/src/modules/finance-ledger/query/listAccountingPeriods.generated.ts +5 -0
- package/src/modules/finance-ledger/query/listAccountingPeriods.test.ts +81 -0
- package/src/modules/finance-ledger/query/listAccountingPeriods.ts +61 -0
- package/src/modules/finance-ledger/query/listFinancialStatements.generated.ts +5 -0
- package/src/modules/finance-ledger/query/listFinancialStatements.test.ts +76 -0
- package/src/modules/finance-ledger/query/listFinancialStatements.ts +62 -0
- package/src/modules/finance-ledger/query/listFiscalYears.generated.ts +5 -0
- package/src/modules/finance-ledger/query/listFiscalYears.test.ts +63 -0
- package/src/modules/finance-ledger/query/listFiscalYears.ts +45 -0
- package/src/modules/finance-ledger/query/listJournalEntries.generated.ts +5 -0
- package/src/modules/finance-ledger/query/listJournalEntries.test.ts +91 -0
- package/src/modules/finance-ledger/query/listJournalEntries.ts +64 -0
- package/src/modules/finance-ledger/query/listPeriodCloses.generated.ts +5 -0
- package/src/modules/finance-ledger/query/listPeriodCloses.test.ts +63 -0
- package/src/modules/finance-ledger/query/listPeriodCloses.ts +64 -0
- package/src/modules/finance-ledger/query/listTrialBalances.generated.ts +5 -0
- package/src/modules/finance-ledger/query/listTrialBalances.test.ts +78 -0
- package/src/modules/finance-ledger/query/listTrialBalances.ts +56 -0
- package/src/modules/finance-ledger/seed/index.ts +19 -0
- package/src/modules/finance-ledger/tailor.config.ts +13 -0
- package/src/modules/finance-ledger/tailor.d.ts +13 -0
- package/src/modules/finance-ledger/testing/commandTestUtils.ts +35 -0
- package/src/modules/finance-ledger/testing/fixtures.ts +382 -0
- package/src/modules/finance-ledger/tsconfig.json +16 -0
- package/src/progress/schema.test.ts +161 -0
- package/src/progress/schema.ts +316 -0
- package/templates/scaffold/app/backend/package.json +1 -3
- package/templates/scaffold/app/backend/vitest.config.ts +4 -21
- package/src/generator/generate-stubs.ts +0 -35
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# VerifySubledgerTransfers
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
verifySubledgerTransfers checks that all registered subledger modules (purchase, sales, inventory, manufacturing) have completed their transaction transfers to the general ledger for the closing period. If all subledgers are reconciled, the PeriodClose transitions from IN_PROGRESS to SUBLEDGERS_VERIFIED. If any subledger has pending unposted transactions, the verification fails and the close cannot proceed.
|
|
6
|
+
|
|
7
|
+
## Business Rules
|
|
8
|
+
|
|
9
|
+
- PeriodClose record must exist and be in IN_PROGRESS status
|
|
10
|
+
- Only IN_PROGRESS records can transition to SUBLEDGERS_VERIFIED
|
|
11
|
+
- Verification checks all registered subledger modules for pending unposted transactions for the period
|
|
12
|
+
- Verification fails if any registered subledger module has pending unposted transactions
|
|
13
|
+
- Verification succeeds when all registered subledger modules confirm transfer completion
|
|
14
|
+
- Updates completionPercentage to reflect progress
|
|
15
|
+
- Records the userId of the operator who performed the verification
|
|
16
|
+
- Emits an audit event recording the acting user, timestamp, subledger verification results, and status transition
|
|
17
|
+
|
|
18
|
+
## Process Flow
|
|
19
|
+
|
|
20
|
+
```mermaid
|
|
21
|
+
flowchart TD
|
|
22
|
+
A[Receive verify subledger transfers request] --> B{PeriodClose record exists?}
|
|
23
|
+
B -->|No| C[Return error: period close not found]
|
|
24
|
+
B -->|Yes| D{PeriodClose in IN_PROGRESS status?}
|
|
25
|
+
D -->|No| E[Return error: invalid status transition]
|
|
26
|
+
D -->|Yes| F[Check all registered subledger modules for pending transactions]
|
|
27
|
+
F --> G{All subledgers reconciled?}
|
|
28
|
+
G -->|No| H[Return error: pending subledger transactions]
|
|
29
|
+
G -->|Yes| I[Transition PeriodClose to SUBLEDGERS_VERIFIED]
|
|
30
|
+
I --> J[Update completionPercentage]
|
|
31
|
+
J --> K[Emit audit event]
|
|
32
|
+
K --> L[Return updated PeriodClose]
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## External Dependencies
|
|
36
|
+
|
|
37
|
+
- purchase module — queries pending purchase transactions for the period (contract TBD by purchase module)
|
|
38
|
+
- sales module — queries pending sales transactions for the period (contract TBD by sales module)
|
|
39
|
+
- inventory module — queries pending inventory transactions for the period (contract TBD by inventory module)
|
|
40
|
+
- manufacturing module — queries pending manufacturing transactions for the period (contract TBD by manufacturing module)
|
|
41
|
+
|
|
42
|
+
## Error Scenarios
|
|
43
|
+
|
|
44
|
+
- **PERIOD_CLOSE_NOT_FOUND**: No PeriodClose record matches the given id
|
|
45
|
+
- **INVALID_STATUS_TRANSITION**: PeriodClose is not in IN_PROGRESS status; only IN_PROGRESS can transition to SUBLEDGERS_VERIFIED
|
|
46
|
+
- **PENDING_SUBLEDGER_TRANSACTIONS**: One or more subledger modules have pending unposted transactions for the period
|
|
47
|
+
|
|
48
|
+
## Test Cases
|
|
49
|
+
|
|
50
|
+
- returns error when PeriodClose record does not exist
|
|
51
|
+
- returns error when PeriodClose is in NOT_STARTED status
|
|
52
|
+
- returns error when PeriodClose is already in SUBLEDGERS_VERIFIED status
|
|
53
|
+
- returns error when purchase module has pending unposted transactions
|
|
54
|
+
- returns error when sales module has pending unposted transactions
|
|
55
|
+
- returns error when inventory module has pending unposted transactions
|
|
56
|
+
- returns error when manufacturing module has pending unposted transactions
|
|
57
|
+
- transitions IN_PROGRESS to SUBLEDGERS_VERIFIED when all subledgers are reconciled
|
|
58
|
+
- updates completionPercentage after successful verification
|
|
59
|
+
- emits audit event recording subledger verification results and status transition
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# VerifyTrialBalance
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
verifyTrialBalance checks that the period's trial balance is balanced (total debits equal total credits across all accounts) and transitions the PeriodClose from ADJUSTMENTS_POSTED to TRIAL_BALANCE_VERIFIED status. This step ensures the integrity of double-entry bookkeeping before financial statements can be generated. If the trial balance has a non-zero discrepancy, the verification fails.
|
|
6
|
+
|
|
7
|
+
## Business Rules
|
|
8
|
+
|
|
9
|
+
- PeriodClose record must exist and be in ADJUSTMENTS_POSTED status
|
|
10
|
+
- Only ADJUSTMENTS_POSTED records can transition to TRIAL_BALANCE_VERIFIED
|
|
11
|
+
- Verification generates or retrieves the trial balance for the period
|
|
12
|
+
- Verification fails if the trial balance has a non-zero difference between total debits and total credits
|
|
13
|
+
- Verification succeeds when debits equal credits across all accounts for the period
|
|
14
|
+
- Updates completionPercentage to reflect progress
|
|
15
|
+
- Records the userId of the operator who performed the verification
|
|
16
|
+
- Emits an audit event recording the acting user, timestamp, trial balance result, and status transition
|
|
17
|
+
|
|
18
|
+
## Process Flow
|
|
19
|
+
|
|
20
|
+
```mermaid
|
|
21
|
+
flowchart TD
|
|
22
|
+
A[Receive verify trial balance request] --> B{PeriodClose record exists?}
|
|
23
|
+
B -->|No| C[Return error: period close not found]
|
|
24
|
+
B -->|Yes| D{PeriodClose in ADJUSTMENTS_POSTED status?}
|
|
25
|
+
D -->|No| E[Return error: invalid status transition]
|
|
26
|
+
D -->|Yes| F[Generate or retrieve trial balance for the period]
|
|
27
|
+
F --> G{Total debits equal total credits?}
|
|
28
|
+
G -->|No| H[Return error: trial balance imbalanced with discrepancy amount]
|
|
29
|
+
G -->|Yes| I[Transition PeriodClose to TRIAL_BALANCE_VERIFIED]
|
|
30
|
+
I --> J[Update completionPercentage]
|
|
31
|
+
J --> K[Emit audit event]
|
|
32
|
+
K --> L[Return updated PeriodClose]
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## External Dependencies
|
|
36
|
+
|
|
37
|
+
- [coa-management::getChartOfAccounts](../../../coa-management/docs/queries/GetChartOfAccounts.md) - Retrieves the active CoA for trial balance generation
|
|
38
|
+
|
|
39
|
+
## Error Scenarios
|
|
40
|
+
|
|
41
|
+
- **PERIOD_CLOSE_NOT_FOUND**: No PeriodClose record matches the given id
|
|
42
|
+
- **INVALID_STATUS_TRANSITION**: PeriodClose is not in ADJUSTMENTS_POSTED status; only ADJUSTMENTS_POSTED can transition to TRIAL_BALANCE_VERIFIED
|
|
43
|
+
- **TRIAL_BALANCE_IMBALANCED**: The period's trial balance has a non-zero difference between total debits and total credits; includes the discrepancy amount
|
|
44
|
+
|
|
45
|
+
## Test Cases
|
|
46
|
+
|
|
47
|
+
- returns error when PeriodClose record does not exist
|
|
48
|
+
- returns error when PeriodClose is in SUBLEDGERS_VERIFIED status
|
|
49
|
+
- returns error when PeriodClose is already in TRIAL_BALANCE_VERIFIED status
|
|
50
|
+
- returns error when trial balance has a non-zero debit-credit discrepancy
|
|
51
|
+
- transitions ADJUSTMENTS_POSTED to TRIAL_BALANCE_VERIFIED when trial balance is balanced
|
|
52
|
+
- updates completionPercentage after successful verification
|
|
53
|
+
- emits audit event recording trial balance result and status transition
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Accounting Period Management
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Accounting Period Management defines and controls the lifecycle of fiscal periods within the finance-ledger module. Each accounting period represents a discrete time segment (typically a month, quarter, or custom interval) within a fiscal year, scoped to a single company via `companyId`. Periods carry a start date, end date, period name, period type, and a five-state status that governs whether journal entries can be posted. The five-state lifecycle (NEVER_OPENED, FUTURE_ENTERABLE, OPEN, CLOSED, PERMANENTLY_CLOSED) mirrors the industry-standard model used by Oracle Financials and provides granular control over when and how transactions flow into each period.
|
|
6
|
+
|
|
7
|
+
Accounting periods are the temporal backbone of the general ledger. Every journal entry must reference a valid period, and the period's current status determines whether that posting is accepted or rejected. This module is responsible for defining the fiscal calendar structure (including support for non-calendar fiscal years such as 4-4-5 week schemes or 13-period years), exposing period status queries that upstream modules (purchase, sales, inventory, manufacturing) use to validate posting eligibility, and enforcing the sequential integrity of period transitions. Period management is a compliance requirement under GAAP, IFRS, and most local regulations — locking closed periods prevents backdated entries that would compromise financial statement integrity.
|
|
8
|
+
|
|
9
|
+
## Business Purpose
|
|
10
|
+
|
|
11
|
+
Organizations need disciplined period management to maintain accurate, auditable, and regulation-compliant financial records:
|
|
12
|
+
|
|
13
|
+
- **Posting control**: The period status determines whether journal entries are accepted. Only periods in FUTURE_ENTERABLE or OPEN status allow postings, preventing accidental or unauthorized entries into periods that have been reconciled or reported
|
|
14
|
+
- **Five-state lifecycle granularity**: The NEVER_OPENED state distinguishes periods that have been defined but not yet activated from those that are FUTURE_ENTERABLE (accepting advance postings such as recurring journals or accruals). The distinction between CLOSED (reversible, allowing period reopening for adjustments) and PERMANENTLY_CLOSED (irreversible, enforcing hard cutoff for audited periods) gives finance teams flexibility while maintaining audit integrity
|
|
15
|
+
- **Fiscal year flexibility**: Support for non-calendar fiscal years (e.g., April-to-March, 4-4-5 week structures, 13-period years) ensures the system accommodates diverse organizational and jurisdictional requirements. A fiscal year is a logical grouping of periods scoped to a company, carrying a year name and start/end boundaries
|
|
16
|
+
- **Cross-module posting validation**: Upstream modules (purchase, sales, inventory, manufacturing) query the accounting period status before creating journal entries. This centralized validation ensures consistent enforcement of period restrictions across the entire ERP without duplicating temporal logic in each module
|
|
17
|
+
- **Period locking layers**: Periods can be locked incrementally — first for the accounting team (preventing routine postings while allowing supervisor adjustments), then fully closed, and finally permanently closed after external audit. This layered approach supports the month-end and year-end close workflow
|
|
18
|
+
- **Adjustment period support**: Special adjustment periods (period 13 or period 0) can be defined for year-end adjusting entries, audit adjustments, and closing entries without contaminating the regular operating periods
|
|
19
|
+
- **Compliance and audit trail**: Period status transitions are auditable events. Regulators and auditors rely on period locking to verify that reported financial statements were not altered after issuance. GAAP, IFRS, and local regulations require demonstrable period close controls
|
|
20
|
+
- **Company scoping**: Each fiscal year and its periods are isolated to a legal entity, supporting multi-entity deployments where subsidiaries may have different fiscal calendars and close schedules
|
|
21
|
+
|
|
22
|
+
## Process Flow
|
|
23
|
+
|
|
24
|
+
```mermaid
|
|
25
|
+
stateDiagram-v2
|
|
26
|
+
[*] --> NeverOpened: createAccountingPeriod
|
|
27
|
+
NeverOpened --> FutureEnterable: openForAdvanceEntry
|
|
28
|
+
FutureEnterable --> Open: openPeriod
|
|
29
|
+
NeverOpened --> Open: openPeriod
|
|
30
|
+
Open --> Closed: closePeriod
|
|
31
|
+
Closed --> Open: reopenPeriod
|
|
32
|
+
Closed --> PermanentlyClosed: permanentlyClosePeriod
|
|
33
|
+
PermanentlyClosed --> [*]
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```mermaid
|
|
37
|
+
flowchart TD
|
|
38
|
+
A[Define fiscal year for company] --> B[Generate accounting periods]
|
|
39
|
+
B --> C[Periods created in NEVER_OPENED status]
|
|
40
|
+
C --> D{Advance postings needed?}
|
|
41
|
+
D -- Yes --> E[Transition to FUTURE_ENTERABLE]
|
|
42
|
+
D -- No --> F[Transition directly to OPEN]
|
|
43
|
+
E --> F[Transition to OPEN when period begins]
|
|
44
|
+
F --> G[Accept journal postings]
|
|
45
|
+
G --> H[Month-end reconciliation complete]
|
|
46
|
+
H --> I[Close period]
|
|
47
|
+
I --> J{Adjustments needed?}
|
|
48
|
+
J -- Yes --> K[Reopen period]
|
|
49
|
+
K --> G
|
|
50
|
+
J -- No --> L{Audit finalized?}
|
|
51
|
+
L -- No --> M[Period remains CLOSED]
|
|
52
|
+
L -- Yes --> N[Permanently close period]
|
|
53
|
+
N --> O[No further changes permitted]
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Scenario Patterns
|
|
57
|
+
|
|
58
|
+
- **Standard Monthly Close**: A company operates on a calendar fiscal year with 12 monthly periods. At month-end, the accounting team completes reconciliations, posts final accruals, and transitions the period from OPEN to CLOSED. After the external auditor reviews Q1, periods January through March are permanently closed
|
|
59
|
+
- **Non-Calendar Fiscal Year Setup**: A retailer with a February-to-January fiscal year (aligned to post-holiday reporting) defines a fiscal year starting February 1. Twelve monthly periods are generated with date boundaries matching the non-calendar cycle. Each period follows the same five-state lifecycle regardless of the calendar alignment
|
|
60
|
+
- **4-4-5 Week Period Structure**: A retail organization uses a 4-4-5 week fiscal calendar where each quarter consists of two 4-week periods followed by one 5-week period (13 periods per year). Custom period boundaries are defined rather than calendar month boundaries, and all period lifecycle rules apply identically
|
|
61
|
+
- **Advance Posting for Recurring Journals**: Before a new fiscal year begins, the controller transitions upcoming periods to FUTURE_ENTERABLE to allow automated recurring journal entries (e.g., monthly rent, depreciation) to be posted in advance. The periods remain in FUTURE_ENTERABLE until the actual period start date, when they transition to OPEN
|
|
62
|
+
- **Year-End Adjustment Period**: An adjustment period (period 13) is created for year-end closing entries and audit adjustments. This period shares the same end date as the final regular period but is designated as an adjustment type, isolating audit-related entries from operating activity
|
|
63
|
+
- **Period Reopen for Late Invoice**: After closing March, the AP team discovers an unrecorded vendor invoice dated March 15. The controller reopens March (CLOSED to OPEN), posts the invoice, and re-closes the period. This is only possible because March was not yet permanently closed
|
|
64
|
+
- **Multi-Entity Close Coordination**: A parent company with three subsidiaries coordinates period close across all entities. Each subsidiary's periods are independently managed — subsidiary A closes March on April 5, while subsidiary B closes on April 8 — reflecting their separate fiscal period scoping by companyId
|
|
65
|
+
- **Preventing Backdated Entries**: A sales team attempts to post a revenue entry to a permanently closed period to inflate prior-quarter results. The system rejects the posting because the period status is PERMANENTLY_CLOSED, enforcing financial statement integrity
|
|
66
|
+
|
|
67
|
+
## Test Cases
|
|
68
|
+
|
|
69
|
+
- Accounting period lifecycle follows NEVER_OPENED -> FUTURE_ENTERABLE -> OPEN -> CLOSED -> PERMANENTLY_CLOSED state machine
|
|
70
|
+
- Accounting period can only be created in NEVER_OPENED status
|
|
71
|
+
- Period name is required and must be non-empty
|
|
72
|
+
- Period must have a valid start date and end date, with start date strictly before end date
|
|
73
|
+
- Period must reference a valid companyId from the organization module
|
|
74
|
+
- Period must belong to a fiscal year that is scoped to the same company
|
|
75
|
+
- Periods within the same fiscal year must not have overlapping date ranges
|
|
76
|
+
- Periods within the same fiscal year must cover the full fiscal year date range without gaps
|
|
77
|
+
- Transitioning a NEVER_OPENED period to FUTURE_ENTERABLE succeeds and allows advance postings
|
|
78
|
+
- Transitioning a NEVER_OPENED period directly to OPEN succeeds (skipping FUTURE_ENTERABLE)
|
|
79
|
+
- Transitioning a FUTURE_ENTERABLE period to OPEN succeeds
|
|
80
|
+
- Transitioning an OPEN period to CLOSED succeeds
|
|
81
|
+
- Transitioning a CLOSED period back to OPEN (reopen) succeeds
|
|
82
|
+
- Transitioning a CLOSED period to PERMANENTLY_CLOSED succeeds
|
|
83
|
+
- Transitioning a PERMANENTLY_CLOSED period to any other status is rejected with an irreversible status error
|
|
84
|
+
- Transitioning an OPEN period directly to PERMANENTLY_CLOSED (skipping CLOSED) is rejected with an invalid status transition error
|
|
85
|
+
- Transitioning a NEVER_OPENED period directly to CLOSED is rejected with an invalid status transition error
|
|
86
|
+
- Journal entries can be posted to a period in OPEN status
|
|
87
|
+
- Journal entries can be posted to a period in FUTURE_ENTERABLE status (advance postings)
|
|
88
|
+
- Journal entries are rejected when the target period is in NEVER_OPENED status
|
|
89
|
+
- Journal entries are rejected when the target period is in CLOSED status
|
|
90
|
+
- Journal entries are rejected when the target period is in PERMANENTLY_CLOSED status
|
|
91
|
+
- A period cannot be deleted if it has any associated journal entries regardless of status
|
|
92
|
+
- Reopening a CLOSED period emits an audit event recording the status transition and acting user
|
|
93
|
+
- Closing a period emits an audit event recording the status transition from OPEN to CLOSED
|
|
94
|
+
- Permanently closing a period emits an audit event recording the irreversible transition
|
|
95
|
+
- Creating a fiscal year with 12 monthly periods generates periods with correct start and end date boundaries
|
|
96
|
+
- Creating a fiscal year with 13 periods (adjustment period) generates 12 operating periods and 1 adjustment period
|
|
97
|
+
- Adjustment periods share the same end date as the final regular period but are typed as adjustment
|
|
98
|
+
- A non-calendar fiscal year (e.g., April-to-March) generates periods with correct non-calendar date boundaries
|
|
99
|
+
- Period status query returns the current status for a given date and company, enabling upstream modules to validate posting eligibility
|
|
100
|
+
- Periods are scoped to a company; period records from different companies are isolated
|
|
101
|
+
- Two periods in the same fiscal year cannot have identical start and end dates unless one is an adjustment period
|
|
102
|
+
- All period status transitions emit audit events via the audit module recording the acting user, timestamp, and previous and new status values
|
|
103
|
+
|
|
104
|
+
## Reference Links
|
|
105
|
+
|
|
106
|
+
- [Oracle Fusion Open and Close Periods](https://docs.oracle.com/en/cloud/saas/financials/24d/oafcf/manage-accounting-periods.html)
|
|
107
|
+
- [SAP S/4HANA Fiscal Year and Posting Periods](https://help.sap.com/docs/SAP_S4HANA_ON-PREMISE/ee3509643e954b3da2e0ebfa846c02e1/4cf37e593e3d2944e10000000a42189b.html)
|
|
108
|
+
- [Odoo Fiscal Year and Period Lock](https://www.odoo.com/documentation/19.0/applications/finance/accounting/get_started/opening.html)
|
|
109
|
+
- [NetSuite Accounting Period Management](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_N1553839.html)
|
|
110
|
+
- [Oracle EBS Open and Close Periods Overview](https://docs.oracle.com/en/applications/jd-edwards/cross-application/9.2/eoagl/opening-and-closing-fiscal-periods.html)
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Financial Statement Generation
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Financial statement generation produces the three core financial reports — Balance Sheet (statement of financial position), Profit & Loss (income statement), and Cash Flow Statement — from the finance-ledger module's trial balance data. Each statement is scoped to a single company, denominated in the company's base currency, and structured according to the account group hierarchy defined in the coa-management module. The Balance Sheet reports asset, liability, and equity positions as of a specific date. The Profit & Loss statement aggregates revenue and expense activity over a date range (typically a fiscal period or year-to-date). The Cash Flow Statement derives cash movements over a period using either the direct or indirect method, reconciling operating, investing, and financing activities to the net change in cash.
|
|
6
|
+
|
|
7
|
+
A `FinancialStatement` entity represents a generated report. It stores the statement type, the generation parameters (reporting date or date range, method for cash flow), a lifecycle status, and the generated output comprising line items organized by account group sections. Statement generation consumes trial balance data — specifically the period-end balances and movements for each GL account — and maps each account to the appropriate report section based on the account's type (ASSET, LIABILITY, EQUITY, REVENUE, EXPENSE) and its position within the coa-management account group hierarchy. This feature covers standard fixed-format statement generation; configurable report builders and custom financial statement versions (FSV) are out of scope and belong to a future reporting module.
|
|
8
|
+
|
|
9
|
+
## Business Purpose
|
|
10
|
+
|
|
11
|
+
Organizations need accurate, standards-compliant financial statements for external reporting, internal decision-making, and regulatory compliance:
|
|
12
|
+
|
|
13
|
+
- **Regulatory compliance**: IAS 1 (IFRS) and local GAAP frameworks require entities to produce a complete set of financial statements including a statement of financial position, income statement, and cash flow statement. This feature satisfies the core statement production requirement
|
|
14
|
+
- **Period-end reporting**: After trial balance generation and period-end close, financial statements are the primary deliverable that summarizes the company's financial position and performance for stakeholders including management, auditors, tax authorities, and investors
|
|
15
|
+
- **Account type-driven placement**: Each GL account's type (ASSET, LIABILITY, EQUITY, REVENUE, EXPENSE) determines which statement and section it appears in. This automatic classification eliminates manual mapping errors and ensures consistency between the ledger and the reports
|
|
16
|
+
- **Hierarchy-based structure**: The account group hierarchy from coa-management defines the presentation structure of each statement. Groups such as "Current Assets", "Non-Current Liabilities", or "Operating Expenses" provide the section headings and subtotals that give statements their standard shape
|
|
17
|
+
- **Comparative periods**: IAS 1 requires comparative information for the preceding period. Statement generation supports including prior-period balances alongside the current period, enabling period-over-period analysis on a single report
|
|
18
|
+
- **Cash flow method selection**: The Cash Flow Statement can be generated using the direct method (classifying actual cash receipts and payments) or the indirect method (adjusting net income for non-cash items and working capital changes). Both are permitted under IFRS and US GAAP; the indirect method is more commonly used in practice
|
|
19
|
+
- **Company scoping and currency**: Each statement is scoped to a single legal entity and denominated in the company's base currency (inherited via the CoA from the organization module), ensuring that statement figures are consistent with the underlying ledger
|
|
20
|
+
- **Audit trail**: Every statement generation event is recorded, preserving a traceable link between the report output, the trial balance data it consumed, and the parameters used to produce it
|
|
21
|
+
|
|
22
|
+
## Process Flow
|
|
23
|
+
|
|
24
|
+
The following diagram shows the end-to-end flow for generating a financial statement from trial balance data.
|
|
25
|
+
|
|
26
|
+
```mermaid
|
|
27
|
+
flowchart TD
|
|
28
|
+
A[Request statement generation] --> B{Statement type?}
|
|
29
|
+
B -- Balance Sheet --> C[Retrieve trial balance as-of date]
|
|
30
|
+
B -- Profit & Loss --> D[Retrieve trial balance for date range]
|
|
31
|
+
B -- Cash Flow --> E[Retrieve trial balance for date range]
|
|
32
|
+
C --> F[Load account group hierarchy from coa-management]
|
|
33
|
+
D --> F
|
|
34
|
+
E --> F
|
|
35
|
+
F --> G[Map accounts to statement sections by account type]
|
|
36
|
+
G --> H[Aggregate balances per account group]
|
|
37
|
+
H --> I{Include comparative period?}
|
|
38
|
+
I -- Yes --> J[Retrieve prior period trial balance]
|
|
39
|
+
J --> K[Align prior period to same sections]
|
|
40
|
+
K --> L[Assemble statement line items]
|
|
41
|
+
I -- No --> L
|
|
42
|
+
L --> M{Validation passed?}
|
|
43
|
+
M -- Yes --> N[Create FinancialStatement entity in DRAFT]
|
|
44
|
+
M -- No --> O[Return validation errors]
|
|
45
|
+
N --> P[Review and finalize]
|
|
46
|
+
P --> Q[Finalize statement]
|
|
47
|
+
Q --> R[Statement FINALIZED — immutable]
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The following diagram shows the Cash Flow Statement generation sub-process, which differs depending on the selected method.
|
|
51
|
+
|
|
52
|
+
```mermaid
|
|
53
|
+
flowchart TD
|
|
54
|
+
A[Cash Flow generation requested] --> B{Method?}
|
|
55
|
+
B -- Direct --> C[Classify cash receipts and payments from ledger entries]
|
|
56
|
+
C --> D[Group into Operating / Investing / Financing]
|
|
57
|
+
B -- Indirect --> E[Start with net income from P&L]
|
|
58
|
+
E --> F[Adjust for non-cash items: depreciation, amortization]
|
|
59
|
+
F --> G[Adjust for working capital changes]
|
|
60
|
+
G --> D
|
|
61
|
+
D --> H[Calculate net change in cash]
|
|
62
|
+
H --> I[Reconcile to opening and closing cash balances]
|
|
63
|
+
I --> J[Return cash flow line items]
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Scenario Patterns
|
|
67
|
+
|
|
68
|
+
- **Monthly Balance Sheet**: At month-end close, a controller generates a Balance Sheet as of the last day of the month. The system retrieves the trial balance closing balances for all ASSET, LIABILITY, and EQUITY accounts, structures them according to the account group hierarchy (Current Assets, Non-Current Assets, Current Liabilities, Long-Term Liabilities, Equity), and produces a report where total assets equal total liabilities plus equity
|
|
69
|
+
- **Year-End Income Statement**: At fiscal year-end, a Profit & Loss statement is generated for the full year date range. REVENUE accounts appear as income sections and EXPENSE accounts as cost/expense sections, with subtotals for gross profit, operating profit, and net income derived from the group hierarchy
|
|
70
|
+
- **Quarterly Comparative P&L**: A finance manager generates a Q3 income statement with comparative data from Q3 of the prior year. Both periods' figures appear side-by-side, enabling variance analysis of revenue growth and cost changes
|
|
71
|
+
- **Cash Flow Statement (Indirect Method)**: An auditor requests a cash flow statement for the fiscal year. The system starts with net income from the P&L, adjusts for non-cash charges (depreciation, amortization, provisions), accounts for changes in working capital (receivables, payables, inventory), and classifies investing and financing activities to arrive at the net cash movement reconciled to the opening and closing cash balances
|
|
72
|
+
- **Cash Flow Statement (Direct Method)**: A company required by its regulator to use the direct method generates a cash flow statement that classifies actual cash inflows (customer receipts, interest received) and outflows (supplier payments, wages, taxes) into operating, investing, and financing categories
|
|
73
|
+
- **Multi-Entity Consolidation Preparation**: Each subsidiary generates its own set of financial statements in its base currency. These entity-level statements serve as inputs for a future consolidation process (out of scope for this feature)
|
|
74
|
+
- **Draft Review and Correction**: A statement is generated in DRAFT status. During review, the controller identifies a missing accrual entry, posts a correcting journal entry, regenerates the trial balance, and regenerates the statement before finalizing
|
|
75
|
+
|
|
76
|
+
## Test Cases
|
|
77
|
+
|
|
78
|
+
- FinancialStatement entity requires a valid companyId referencing an ACTIVE company
|
|
79
|
+
- FinancialStatement entity requires a valid chartOfAccountsId referencing an ACTIVE CoA
|
|
80
|
+
- Statement type must be one of: BALANCE_SHEET, PROFIT_AND_LOSS, CASH_FLOW
|
|
81
|
+
- Balance Sheet generation requires a single reporting date (as-of date)
|
|
82
|
+
- Profit & Loss generation requires a date range (start date and end date)
|
|
83
|
+
- Cash Flow Statement generation requires a date range and a method (DIRECT or INDIRECT)
|
|
84
|
+
- The reporting date or date range must fall within a closed or active accounting period
|
|
85
|
+
- A Balance Sheet includes only accounts of type ASSET, LIABILITY, and EQUITY
|
|
86
|
+
- A Profit & Loss includes only accounts of type REVENUE and EXPENSE
|
|
87
|
+
- A Cash Flow Statement derives from ledger data covering all account types relevant to cash movements
|
|
88
|
+
- On a correctly generated Balance Sheet, total assets equal total liabilities plus total equity (the accounting equation holds)
|
|
89
|
+
- Statement line items are structured according to the account group hierarchy from coa-management
|
|
90
|
+
- Accounts not assigned to any account group are reported in an "Unclassified" section and flagged as warnings
|
|
91
|
+
- Comparative period data, when requested, is aligned to the same account group sections as the current period
|
|
92
|
+
- If comparative period trial balance data is unavailable, generation fails with a descriptive error
|
|
93
|
+
- FinancialStatement is created in DRAFT status
|
|
94
|
+
- A DRAFT statement can be regenerated (replaced) with updated trial balance data
|
|
95
|
+
- Finalizing a DRAFT statement transitions it to FINALIZED status
|
|
96
|
+
- A FINALIZED statement is immutable — its line items, parameters, and output cannot be modified
|
|
97
|
+
- Finalizing an already FINALIZED statement fails with an invalid status transition error
|
|
98
|
+
- Generating a statement for a period with no posted journal entries fails with a validation error
|
|
99
|
+
- Statement output includes subtotals at each level of the account group hierarchy
|
|
100
|
+
- Cash Flow Statement (indirect method) starts with net income and adjusts for non-cash items and working capital changes
|
|
101
|
+
- Cash Flow Statement reconciles to the net change between opening and closing cash balances
|
|
102
|
+
- Statement generation emits an audit event via the audit module recording the acting user, timestamp, statement type, and parameters
|
|
103
|
+
- Finalizing a statement emits an audit event recording the status transition from DRAFT to FINALIZED
|
|
104
|
+
- All monetary amounts in the statement are denominated in the company's base currency
|
|
105
|
+
- Statement generation for a company with no trial balance data for the requested period returns a validation error
|
|
106
|
+
- Each statement records a reference to the trial balance snapshot it was generated from, ensuring traceability
|
|
107
|
+
|
|
108
|
+
## Reference Links
|
|
109
|
+
|
|
110
|
+
- [IAS 1 Presentation of Financial Statements (IFRS)](https://www.ifrs.org/issued-standards/list-of-standards/ias-1-presentation-of-financial-statements/)
|
|
111
|
+
- [IAS 7 Statement of Cash Flows (IFRS)](https://www.ifrs.org/issued-standards/list-of-standards/ias-7-statement-of-cash-flows/)
|
|
112
|
+
- [SAP Financial Statement Versions (FSV)](https://help.sap.com/docs/SAP_S4HANA_ON-PREMISE/ee5c9e37ff4f4e33a6c7e2c32f8fc3b5/577f8c2a397b4ce589e1ad03a64eb1ae.html)
|
|
113
|
+
- [Oracle Financial Statement Generator (FSG)](https://docs.oracle.com/en/cloud/saas/financials/24d/oaglg/financial-reporting.html)
|
|
114
|
+
- [Odoo Financial Reporting](https://www.odoo.com/documentation/19.0/applications/finance/accounting/reporting.html)
|
|
115
|
+
- [NetSuite Financial Statements](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_N1583498.html)
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# Journal Entry Management
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Journal Entry Management is the core transactional capability of the finance-ledger module, implementing double-entry bookkeeping for all financial postings. A journal entry consists of a header record (JournalEntry) carrying the entry date, journal type, reference number, status, posting period, description, and optional source document reference, along with one or more line records (JournalLine) that each specify a GL account (from coa-management), debit or credit amount, currency, exchange rate, functional currency amount, and line-level description. Every journal entry must satisfy the fundamental accounting constraint: total debits must equal total credits in the functional currency before it can be posted.
|
|
6
|
+
|
|
7
|
+
Journal entries follow a lifecycle of DRAFT to POSTED, with posted entries eligible for reversal via a mirror entry that produces a REVERSED status on the original. The feature supports six journal types (Sales, Purchase, Cash, Bank, Miscellaneous, Opening) to categorize entries by their business origin, and handles multi-currency postings by converting foreign currency amounts to the company's functional currency using a specified exchange rate. All mutations are recorded in an immutable audit trail, ensuring regulatory compliance and full traceability from entry creation through posting and reversal.
|
|
8
|
+
|
|
9
|
+
## Business Purpose
|
|
10
|
+
|
|
11
|
+
Organizations need a rigorous, auditable journal entry system to record financial transactions and maintain the integrity of their general ledger:
|
|
12
|
+
|
|
13
|
+
- **Double-entry enforcement**: Every journal entry must balance total debits against total credits in the functional currency, preventing one-sided postings that would corrupt the trial balance and financial statements
|
|
14
|
+
- **Journal type categorization**: Classifying entries by type (Sales, Purchase, Cash, Bank, Miscellaneous, Opening) mirrors the journal/book structure used by all major ERPs (Odoo, SAP, Oracle) and enables filtering, reporting, and access control by transaction origin
|
|
15
|
+
- **Lifecycle gating**: The DRAFT to POSTED progression ensures entries can be reviewed and corrected before they affect account balances. Only posted entries contribute to the general ledger, trial balance, and financial statements
|
|
16
|
+
- **Immutable posted entries**: Once posted, a journal entry cannot be modified or deleted — only reversed. This preserves the audit trail required by GAAP, IFRS, and local accounting regulations
|
|
17
|
+
- **Reversal via mirror entry**: Reversing a posted entry creates a new journal entry with inverted debit/credit lines rather than deleting the original, maintaining a complete history of all postings and corrections
|
|
18
|
+
- **Multi-currency support**: Companies operating across borders must record transactions in the original foreign currency while converting to the functional (base) currency for consolidated reporting. Exchange rate capture at posting time ensures accurate currency translation
|
|
19
|
+
- **Period-aware posting**: Journal entries reference an accounting period and can only be posted to periods that are in OPEN or FUTURE_ENTERABLE status, enforcing the period lifecycle managed by the accounting-period-management feature
|
|
20
|
+
- **Source document traceability**: Optional source document references (e.g., invoice number, bill ID) link journal entries back to their originating business transactions, supporting audit inquiries and subledger reconciliation
|
|
21
|
+
- **GL account validation with successor mapping**: Journal lines must reference active GL accounts from an active Chart of Accounts. When a GL account has been deprecated with a successor account mapping (from coa-management), postings are redirected to the successor account, ensuring continuity without manual re-entry
|
|
22
|
+
- **Audit trail**: Every state change — creation, update, posting, reversal — is recorded with the acting user, timestamp, and field-level details via the audit module, satisfying internal control and external audit requirements
|
|
23
|
+
|
|
24
|
+
## Process Flow
|
|
25
|
+
|
|
26
|
+
```mermaid
|
|
27
|
+
stateDiagram-v2
|
|
28
|
+
[*] --> Draft: createJournalEntry
|
|
29
|
+
Draft --> Draft: updateJournalEntry / addJournalLine / removeJournalLine
|
|
30
|
+
Draft --> Posted: postJournalEntry
|
|
31
|
+
Posted --> Reversed: reverseJournalEntry
|
|
32
|
+
Draft --> [*]: deleteJournalEntry
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
```mermaid
|
|
36
|
+
flowchart TD
|
|
37
|
+
A[Identify transaction to record] --> B[Create JournalEntry header in DRAFT]
|
|
38
|
+
B --> C[Add JournalLine records with debit/credit amounts]
|
|
39
|
+
C --> D{Multi-currency?}
|
|
40
|
+
D -- Yes --> E[Specify foreign currency and exchange rate per line]
|
|
41
|
+
E --> F[System converts to functional currency amounts]
|
|
42
|
+
D -- No --> F
|
|
43
|
+
F --> G{Debits = Credits in functional currency?}
|
|
44
|
+
G -- No --> C
|
|
45
|
+
G -- Yes --> H{GL accounts valid and active?}
|
|
46
|
+
H -- No --> I[Resolve account issues]
|
|
47
|
+
I --> C
|
|
48
|
+
H -- Yes --> J{Target period OPEN or FUTURE_ENTERABLE?}
|
|
49
|
+
J -- No --> K[Select valid posting period]
|
|
50
|
+
K --> J
|
|
51
|
+
J -- Yes --> L[Post journal entry]
|
|
52
|
+
L --> M[Account balances updated]
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
```mermaid
|
|
56
|
+
flowchart TD
|
|
57
|
+
A[Select posted journal entry to reverse] --> B[Create mirror entry with inverted debits/credits]
|
|
58
|
+
B --> C{Reversal period OPEN or FUTURE_ENTERABLE?}
|
|
59
|
+
C -- No --> D[Select valid reversal period]
|
|
60
|
+
D --> C
|
|
61
|
+
C -- Yes --> E[Post reversal entry]
|
|
62
|
+
E --> F[Original entry status set to REVERSED]
|
|
63
|
+
F --> G[Original entry balances offset to zero]
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Scenario Patterns
|
|
67
|
+
|
|
68
|
+
- **Manual Miscellaneous Entry**: An accountant creates a miscellaneous journal entry to record an adjusting entry (e.g., accrual or reclassification) that does not originate from a subledger. The entry is created in DRAFT, journal lines are added with appropriate debit/credit accounts and amounts, the balance is verified, and the entry is posted to the current open period
|
|
69
|
+
- **Sales Invoice Posting**: The sales module generates a journal entry of type Sales with a debit to Accounts Receivable and a credit to Revenue, referencing the sales invoice as the source document. The entry flows through the subledger integration contract and is posted automatically upon invoice confirmation
|
|
70
|
+
- **Purchase Bill Recording**: A purchase bill triggers a journal entry of type Purchase with a debit to the relevant expense or inventory account and a credit to Accounts Payable. The source document reference links back to the purchase bill for reconciliation
|
|
71
|
+
- **Multi-Currency Transaction**: A company records a purchase invoice denominated in a foreign currency. The journal lines capture both the foreign currency amount and the exchange rate, with the system computing the functional currency equivalent. The entry balances in the functional currency, and any rounding difference is posted to a designated exchange gain/loss account
|
|
72
|
+
- **Opening Balance Entry**: During initial system setup or at the start of a new fiscal year, an Opening-type journal entry is created to establish beginning balances for all balance sheet accounts. This entry typically carries a posting date matching the first day of the new fiscal period
|
|
73
|
+
- **Error Correction via Reversal**: A posted journal entry is discovered to contain an incorrect account assignment. The accountant reverses the original entry (creating a mirror posting that offsets all amounts) and then creates a new corrective entry with the correct accounts. The original entry, its reversal, and the correction all remain in the ledger for full auditability
|
|
74
|
+
- **Cash Receipt Recording**: A cash payment received from a customer is recorded as a Cash-type journal entry, debiting the bank/cash account and crediting Accounts Receivable. The source document reference links to the customer payment record
|
|
75
|
+
- **Bank Transaction Entry**: A bank fee or interest charge is recorded as a Bank-type journal entry, debiting bank charges expense and crediting the bank account, referencing the bank statement line as the source document
|
|
76
|
+
- **Successor Account Redirect**: An accountant creates a journal line referencing a GL account that has been deprecated with a successor mapping in coa-management. The system automatically redirects the posting to the successor account, logs the redirect in the audit trail, and posts the entry without requiring manual correction
|
|
77
|
+
- **Period Boundary Posting**: An entry needs to be recorded in a future accounting period that is in FUTURE_ENTERABLE status. The entry is created and posted to that period, allowing advance preparation of known transactions before the current period closes
|
|
78
|
+
|
|
79
|
+
## Test Cases
|
|
80
|
+
|
|
81
|
+
- Journal entry lifecycle follows DRAFT -> POSTED state machine; posted entries can transition to REVERSED
|
|
82
|
+
- Journal entry can only be created in DRAFT status
|
|
83
|
+
- Journal entry requires a valid journal type (Sales, Purchase, Cash, Bank, Miscellaneous, Opening)
|
|
84
|
+
- Journal entry requires a valid entry date
|
|
85
|
+
- Journal entry requires a reference number that is unique within the company scope
|
|
86
|
+
- Journal entry must reference a valid companyId; the company must be in ACTIVE status
|
|
87
|
+
- Journal entry must reference a valid accounting period; the period must be in OPEN or FUTURE_ENTERABLE status for posting
|
|
88
|
+
- Journal entry description is optional and can be updated while in DRAFT status
|
|
89
|
+
- Source document reference is optional and can be set on creation or update in DRAFT status
|
|
90
|
+
- A journal entry must have at least two journal lines before it can be posted
|
|
91
|
+
- Each journal line must reference a valid GL account from an ACTIVE Chart of Accounts
|
|
92
|
+
- Each journal line must specify either a debit amount or a credit amount (not both, and not zero for both)
|
|
93
|
+
- Debit and credit amounts must be positive values
|
|
94
|
+
- Total debits must equal total credits in the functional currency for posting to succeed
|
|
95
|
+
- An unbalanced journal entry (debits != credits in functional currency) cannot be posted
|
|
96
|
+
- Posting a balanced DRAFT journal entry transitions its status to POSTED
|
|
97
|
+
- Posting an already POSTED journal entry fails with an invalid status transition error
|
|
98
|
+
- Posted journal entries cannot be modified (no field updates, no line additions or removals)
|
|
99
|
+
- Posted journal entries cannot be deleted; only reversal is permitted
|
|
100
|
+
- DRAFT journal entries can be deleted; deletion removes all associated journal lines
|
|
101
|
+
- Deleting a DRAFT journal entry emits an audit event recording the deletion and acting user
|
|
102
|
+
- Journal lines can be added to or removed from a DRAFT journal entry
|
|
103
|
+
- Journal lines cannot be added to or removed from a POSTED or REVERSED journal entry
|
|
104
|
+
- Updating a journal line (account, amount, description) is only permitted while the parent entry is in DRAFT status
|
|
105
|
+
- Reversing a posted entry creates a new journal entry with all debit/credit amounts inverted
|
|
106
|
+
- The reversal entry references the original entry and is automatically posted
|
|
107
|
+
- The original entry status transitions from POSTED to REVERSED upon successful reversal
|
|
108
|
+
- Reversing an entry that is already REVERSED fails with an invalid status transition error
|
|
109
|
+
- Reversing a DRAFT entry fails with an invalid status transition error
|
|
110
|
+
- The reversal entry must target a period that is in OPEN or FUTURE_ENTERABLE status
|
|
111
|
+
- Multi-currency journal lines must specify a currency code and exchange rate
|
|
112
|
+
- The functional currency amount is computed as the foreign amount multiplied by the exchange rate
|
|
113
|
+
- Journal lines without an explicit currency default to the company's functional (base) currency with an exchange rate of 1.0
|
|
114
|
+
- Balance validation for multi-currency entries is performed on the functional currency amounts, not the foreign currency amounts
|
|
115
|
+
- Posting a journal entry to a CLOSED or PERMANENTLY_CLOSED period is rejected
|
|
116
|
+
- Posting a journal entry to a NEVER_OPENED period is rejected
|
|
117
|
+
- Journal lines referencing an inactive or draft GL account are rejected at posting time
|
|
118
|
+
- Journal lines referencing a deprecated GL account with a successor mapping are redirected to the successor account at posting time
|
|
119
|
+
- Successor account redirect is recorded in the audit trail with the original and successor account references
|
|
120
|
+
- If the successor account is itself inactive or deprecated without a further successor, the posting is rejected
|
|
121
|
+
- Creating a journal entry emits an audit event via the audit module recording the acting user, timestamp, and initial field values
|
|
122
|
+
- Updating a journal entry (header fields or line changes) emits an audit event recording previous and new field values
|
|
123
|
+
- Posting a journal entry emits an audit event recording the status transition from DRAFT to POSTED and the posting user
|
|
124
|
+
- Reversing a journal entry emits an audit event recording the status transition from POSTED to REVERSED, the reversal entry reference, and the acting user
|
|
125
|
+
- Journal entries are scoped to a company; entries from different companies are fully isolated
|
|
126
|
+
- Only users with appropriate permissions (from user-management) can create, post, or reverse journal entries
|
|
127
|
+
- Unauthorized users receive a permission denied error when attempting journal entry operations
|
|
128
|
+
- A journal entry with a single line (only debit or only credit) cannot be posted
|
|
129
|
+
- Journal type cannot be changed after the entry is posted
|
|
130
|
+
- The entry date cannot be changed after the entry is posted
|
|
131
|
+
|
|
132
|
+
## Reference Links
|
|
133
|
+
|
|
134
|
+
- [Odoo Journal Entries and Journal Types](https://www.odoo.com/documentation/19.0/applications/finance/accounting/get_started/cheat_sheet.html)
|
|
135
|
+
- [SAP S/4HANA Journal Entry Processing](https://help.sap.com/docs/SAP_S4HANA_ON-PREMISE/ee3509643e954b3da2e0ebfa846c02e1/4cae4cc1ecaa7286e10000000a42189b.html)
|
|
136
|
+
- [Oracle Fusion General Ledger Journal Entries](https://docs.oracle.com/en/cloud/saas/financials/24d/oafcf/journal-entries.html)
|
|
137
|
+
- [NetSuite Journal Entry Overview](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_N3444641.html)
|
|
138
|
+
- [Sage Intacct Journal Entries](https://www.sage.com/en-us/blog/what-is-a-journal-entry-in-accounting/)
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# Period End Close
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Period-end close is a structured, checklist-driven workflow that transitions an accounting period from open (accepting postings) to permanently closed (immutable). The process is modeled through a `PeriodClose` entity that tracks the close status, the user who initiated and completed each step, timestamps, and overall checklist completion percentage. Each close operation is scoped to a single `AccountingPeriod` within a company's active Chart of Accounts, ensuring that all financial activity for the period has been captured, verified, and reconciled before the period is locked. The workflow enforces a deterministic sequence of steps: subledger transfer verification, pending journal batch posting, adjusting entry creation (accruals, deferrals, reclassifications), trial balance verification, preliminary financial statement generation, review and approval, soft lock for the accounting team, final advisor adjustments, and permanent close.
|
|
6
|
+
|
|
7
|
+
Adjusting entries created during the close process are flagged with an `adjustingEntryType` (ACCRUAL, DEFERRAL, or RECLASSIFICATION) to distinguish them from regular operational entries for reporting and audit purposes. The soft-lock stage supports segregation of duties by allowing the accounting team to finalize routine entries while reserving a window for external auditors or advisors to post final adjustments before the period is permanently closed. Once permanently closed, no further journal entries can be posted regardless of role, preserving the immutability and auditability of the period's financial data.
|
|
8
|
+
|
|
9
|
+
## Business Purpose
|
|
10
|
+
|
|
11
|
+
Organizations require a disciplined period-close process to ensure the accuracy and integrity of their financial records:
|
|
12
|
+
|
|
13
|
+
- **Financial statement reliability**: A structured close checklist ensures all transactions are captured and verified before financial statements are generated, preventing material misstatements and supporting accurate reporting to stakeholders
|
|
14
|
+
- **Regulatory compliance**: Public companies and regulated entities must close periods within defined timelines (e.g., SEC 10-Q/10-K deadlines). A tracked, step-by-step workflow provides evidence of due diligence and process adherence for external auditors
|
|
15
|
+
- **Subledger completeness**: Verifying that all subledger modules (accounts payable, accounts receivable, inventory, manufacturing) have transferred their transactions to the general ledger prevents omissions that would distort the trial balance
|
|
16
|
+
- **Adjusting entry transparency**: Separating accruals, deferrals, and reclassifications from regular entries allows auditors and management to isolate period-end adjustments and assess their impact on reported figures
|
|
17
|
+
- **Data immutability after close**: Locking a closed period prevents accidental or unauthorized postings that would alter previously reported figures, preserving the audit trail and historical comparability
|
|
18
|
+
- **Multi-step approval**: The soft-lock and final-advisor-adjustment stages support segregation of duties, allowing the accounting team to finalize routine entries while reserving a window for external auditors or advisors to post final adjustments before permanent close
|
|
19
|
+
- **Cross-module coordination**: Period close status is consumed by other modules (purchase, sales, inventory, manufacturing) to determine whether they can post transactions to a given period, creating a unified control point for posting eligibility
|
|
20
|
+
|
|
21
|
+
## Process Flow
|
|
22
|
+
|
|
23
|
+
The period-close lifecycle follows a linear state machine with defined checkpoints at each stage:
|
|
24
|
+
|
|
25
|
+
```mermaid
|
|
26
|
+
stateDiagram-v2
|
|
27
|
+
[*] --> NotStarted: initiatePeriodClose
|
|
28
|
+
NotStarted --> InProgress: beginClose
|
|
29
|
+
InProgress --> SubledgersVerified: verifySubledgerTransfers
|
|
30
|
+
SubledgersVerified --> AdjustmentsPosted: postAdjustingEntries
|
|
31
|
+
AdjustmentsPosted --> TrialBalanceVerified: verifyTrialBalance
|
|
32
|
+
TrialBalanceVerified --> UnderReview: generatePreliminaryStatements
|
|
33
|
+
UnderReview --> SoftLocked: approveAndLockPeriod
|
|
34
|
+
SoftLocked --> PermanentlyClosed: finalCloseAndLockPeriod
|
|
35
|
+
PermanentlyClosed --> [*]
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The following flowchart details the end-to-end close checklist:
|
|
39
|
+
|
|
40
|
+
```mermaid
|
|
41
|
+
flowchart TD
|
|
42
|
+
A[Initiate period close for AccountingPeriod] --> B[Verify all subledger transactions transferred to GL]
|
|
43
|
+
B --> C{All subledgers reconciled?}
|
|
44
|
+
C -- No --> B
|
|
45
|
+
C -- Yes --> D[Post all pending journal batches]
|
|
46
|
+
D --> E[Create adjusting entries: accruals, deferrals, reclassifications]
|
|
47
|
+
E --> F[Run trial balance and verify debits equal credits]
|
|
48
|
+
F --> G{Trial balance balanced?}
|
|
49
|
+
G -- No --> E
|
|
50
|
+
G -- Yes --> H[Generate preliminary financial statements]
|
|
51
|
+
H --> I[Management review and approval]
|
|
52
|
+
I --> J[Soft-lock period: block accounting team postings]
|
|
53
|
+
J --> K[Final advisor/auditor adjustments]
|
|
54
|
+
K --> L[Permanently close period]
|
|
55
|
+
L --> M[Period is immutable - no further postings allowed]
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Scenario Patterns
|
|
59
|
+
|
|
60
|
+
- **Standard Monthly Close**: The accounting team initiates the close for January, verifies that AP and AR subledgers have posted all invoices, creates accrual entries for unbilled services received, verifies the trial balance, obtains controller approval, and permanently closes the period within five business days of month-end
|
|
61
|
+
- **Quarter-End Close with Reclassifications**: At the end of Q1, the accounting team identifies that certain expenses were posted to the wrong cost center. They create reclassification adjusting entries during the close process, rerun the trial balance, and generate preliminary quarterly financial statements for management review before soft-locking the period
|
|
62
|
+
- **Soft Lock with Auditor Adjustments**: The accounting team completes the monthly close checklist and soft-locks the period. An external auditor identifies a material adjustment and posts a correcting entry during the advisor-adjustment window. The period is then permanently closed with the auditor's entry included
|
|
63
|
+
- **Failed Subledger Verification**: During the close process, the system detects that the inventory module has pending cost-of-goods-sold entries that have not been transferred to the GL. The close cannot proceed past the subledger verification step until the inventory team completes the transfer and the close operator re-verifies
|
|
64
|
+
- **Reopening a Soft-Locked Period**: The controller discovers that an accrual was double-counted after the period was soft-locked but before permanent close. The period is reverted from soft-locked to in-progress, the duplicate accrual is reversed, the trial balance is re-verified, and the period is re-locked and permanently closed
|
|
65
|
+
- **Adjusting Entry for Deferred Revenue**: During the close, the accounting team recognizes a portion of deferred revenue that was earned during the period. They create an adjusting entry flagged as DEFERRAL that debits the deferred revenue liability and credits the revenue account, ensuring the income statement reflects revenue earned in the correct period
|
|
66
|
+
|
|
67
|
+
## Test Cases
|
|
68
|
+
|
|
69
|
+
- PeriodClose can only be initiated for an AccountingPeriod that is in OPEN status
|
|
70
|
+
- PeriodClose cannot be initiated for an AccountingPeriod that is already CLOSED or has an existing close in progress
|
|
71
|
+
- PeriodClose lifecycle follows NOT_STARTED -> IN_PROGRESS -> SUBLEDGERS_VERIFIED -> ADJUSTMENTS_POSTED -> TRIAL_BALANCE_VERIFIED -> UNDER_REVIEW -> SOFT_LOCKED -> PERMANENTLY_CLOSED state machine
|
|
72
|
+
- PeriodClose cannot skip steps; transitioning from NOT_STARTED directly to TRIAL_BALANCE_VERIFIED is rejected
|
|
73
|
+
- Subledger verification step fails if any registered subledger module has pending unposted transactions for the period
|
|
74
|
+
- Subledger verification step succeeds when all registered subledger modules confirm transfer completion
|
|
75
|
+
- Adjusting entries created during the close process must have a valid adjustingEntryType (ACCRUAL, DEFERRAL, or RECLASSIFICATION)
|
|
76
|
+
- Adjusting entries are flagged distinctly from regular journal entries for audit trail purposes
|
|
77
|
+
- Adjusting entries must be balanced (total debits equal total credits) before the close can proceed
|
|
78
|
+
- Trial balance verification step fails if the period's trial balance has a non-zero difference between total debits and total credits
|
|
79
|
+
- Trial balance verification step succeeds when debits equal credits across all accounts for the period
|
|
80
|
+
- Preliminary financial statements can only be generated after the trial balance is verified
|
|
81
|
+
- Approval step requires a user with the appropriate authorization role (e.g., controller or finance manager)
|
|
82
|
+
- Soft-locking a period prevents the accounting team from posting new journal entries to that period
|
|
83
|
+
- Soft-locked period still allows postings from users with the advisor/auditor role
|
|
84
|
+
- Final advisor adjustments posted during the soft-locked phase are recorded with an audit trail identifying the advisor
|
|
85
|
+
- Permanently closing a period makes it fully immutable; no further journal entries can be posted regardless of role
|
|
86
|
+
- Attempting to post a journal entry to a permanently closed period is rejected with a period-closed error
|
|
87
|
+
- PeriodClose records the userId of the operator who initiated the close and the userId who completed each checklist step
|
|
88
|
+
- PeriodClose tracks a completionPercentage that increments as each checklist step is completed
|
|
89
|
+
- Each state transition in the PeriodClose lifecycle emits an audit event recording the acting user, timestamp, previous status, and new status
|
|
90
|
+
- Reverting a soft-locked period to in-progress is permitted only before permanent close and emits an audit event
|
|
91
|
+
- Reverting a permanently closed period is not permitted
|
|
92
|
+
- PeriodClose is scoped to a single AccountingPeriod; each period has at most one active PeriodClose record
|
|
93
|
+
- Cross-module posting eligibility check: other modules (purchase, sales, inventory) receive a period-closed signal and reject postings to closed periods
|
|
94
|
+
- Concurrent close attempts for the same period are rejected with a conflict error
|
|
95
|
+
|
|
96
|
+
## Reference Links
|
|
97
|
+
|
|
98
|
+
- [SAP Period-End Closing in Financial Accounting](https://help.sap.com/docs/SAP_S4HANA_ON-PREMISE/ee3509643e954b3da2e0ebfa846c02e1/4588dcd34eab6e37e10000000a42189b.html)
|
|
99
|
+
- [Oracle Fusion General Ledger Close Process](https://docs.oracle.com/en/cloud/saas/financials/24d/oafcf/general-ledger-close.html)
|
|
100
|
+
- [NetSuite Period Close Checklist](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_N1581498.html)
|
|
101
|
+
- [Odoo Fiscal Year End and Closing](https://www.odoo.com/documentation/19.0/applications/finance/accounting/get_started/cheat_sheet.html)
|
|
102
|
+
- [Sage Intacct Period-End Close](https://www.sage.com/en-us/sage-business-cloud/intacct/features/general-ledger/)
|