ekwo-os 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (361) hide show
  1. package/README.md +873 -0
  2. package/dist/args.d.ts +57 -0
  3. package/dist/args.d.ts.map +1 -0
  4. package/dist/args.js +134 -0
  5. package/dist/args.js.map +1 -0
  6. package/dist/assets/expected-objects.json +9432 -0
  7. package/dist/assets/migrations/20260911120000_core_companies.sql +260 -0
  8. package/dist/assets/migrations/20260911120100_accounts_journals.sql +211 -0
  9. package/dist/assets/migrations/20260911120200_contacts.sql +90 -0
  10. package/dist/assets/migrations/20260911120300_taxes.sql +146 -0
  11. package/dist/assets/migrations/20260911120400_entries.sql +338 -0
  12. package/dist/assets/migrations/20260911120500_documents.sql +279 -0
  13. package/dist/assets/migrations/20260911120600_payments_reconciliation.sql +251 -0
  14. package/dist/assets/migrations/20260911120700_bank.sql +178 -0
  15. package/dist/assets/migrations/20260911120800_analytics_attachments.sql +128 -0
  16. package/dist/assets/migrations/20260911120900_post_document.sql +279 -0
  17. package/dist/assets/migrations/20260911121000_reporting.sql +235 -0
  18. package/dist/assets/migrations/20260911121100_country_templates.sql +226 -0
  19. package/dist/assets/migrations/20260911121200_fec.sql +71 -0
  20. package/dist/assets/migrations/20260911130000_instance.sql +77 -0
  21. package/dist/assets/migrations/20260911130100_instance_members.sql +224 -0
  22. package/dist/assets/migrations/20260911140000_instance_admins.sql +112 -0
  23. package/dist/assets/migrations/20260911160000_tax_posting_templates_unique.sql +17 -0
  24. package/dist/assets/migrations/20260911170000_document_amount_paid.sql +82 -0
  25. package/dist/assets/migrations/20260911173000_post_payment.sql +122 -0
  26. package/dist/assets/migrations/20260911173100_sequence_counters_under_rls.sql +84 -0
  27. package/dist/assets/migrations/20260911183000_country_journal_defaults.sql +143 -0
  28. package/dist/assets/migrations/20260911193853_line_account_defaults.sql +274 -0
  29. package/dist/assets/migrations/20260911195054_products.sql +221 -0
  30. package/dist/assets/migrations/20260911210131_anon_surface.sql +85 -0
  31. package/dist/assets/migrations/20260912074712_country_packs.sql +318 -0
  32. package/dist/assets/migrations/20260912080311_report_code_and_region.sql +198 -0
  33. package/dist/assets/migrations/20260912081014_pack_certification_maintained.sql +31 -0
  34. package/dist/assets/migrations/20260912081015_pack_certification_backfill.sql +16 -0
  35. package/dist/assets/migrations/20260912090407_tax_report_boxes.sql +329 -0
  36. package/dist/assets/migrations/20260912091917_tax_on_base_value.sql +25 -0
  37. package/dist/assets/migrations/20260912091918_tax_engine_columns.sql +776 -0
  38. package/dist/assets/migrations/20260912094412_opening_and_closing.sql +759 -0
  39. package/dist/assets/migrations/20260912095825_charts_of_accounts.sql +326 -0
  40. package/dist/assets/migrations/20260912100412_financial_statements.sql +632 -0
  41. package/dist/assets/migrations/20260912104719_one_formula_evaluator.sql +209 -0
  42. package/dist/assets/migrations/20260912105720_entry_kind_appropriation.sql +26 -0
  43. package/dist/assets/migrations/20260912105721_appropriation_entry_kind.sql +444 -0
  44. package/dist/assets/migrations/20260912111751_document_rules.sql +274 -0
  45. package/dist/assets/migrations/20260912112132_cash_basis_vat_and_fx.sql +1189 -0
  46. package/dist/assets/migrations/20260913074512_modules.sql +493 -0
  47. package/dist/assets/migrations/20260913075903_asset_disposal_roles.sql +47 -0
  48. package/dist/assets/migrations/20260913083216_capabilities.sql +637 -0
  49. package/dist/assets/migrations/20260913083901_company_invitations.sql +262 -0
  50. package/dist/assets/migrations/20260913084402_user_preferences.sql +376 -0
  51. package/dist/assets/migrations/20260913084847_company_profile.sql +261 -0
  52. package/dist/assets/migrations/20260913085436_numbering_reads_the_pack.sql +235 -0
  53. package/dist/assets/migrations/20260913085932_api_keys.sql +303 -0
  54. package/dist/assets/migrations/20260913090216_fiscal_year_bounds.sql +159 -0
  55. package/dist/assets/migrations/20260913092527_entries_import.sql +219 -0
  56. package/dist/assets/migrations/20260913101536_null_safe_guards.sql +188 -0
  57. package/dist/assets/migrations/20260913102115_installer_is_named.sql +462 -0
  58. package/dist/assets/migrations/20260913102758_no_currency_default.sql +138 -0
  59. package/dist/assets/migrations/20260913103355_cash_basis_needs_a_box.sql +453 -0
  60. package/dist/assets/migrations/20260913104014_aged_balance_named_group.sql +79 -0
  61. package/dist/assets/migrations/20260913104232_foreign_key_indexes.sql +144 -0
  62. package/dist/assets/migrations/20260913105120_declared_no_reader.sql +41 -0
  63. package/dist/assets/migrations/20260913111407_pack_languages.sql +223 -0
  64. package/dist/assets/migrations/20260913112233_schema_comments_for_a_reader.sql +27 -0
  65. package/dist/assets/migrations/20260913114535_fec_opening_balances.sql +307 -0
  66. package/dist/assets/migrations/20260914103412_audit_log.sql +509 -0
  67. package/dist/assets/migrations/20260914111907_pack_upgrade.sql +428 -0
  68. package/dist/assets/migrations/20260914120500_rounding_reads_the_currency.sql +206 -0
  69. package/dist/assets/migrations/20260914121200_amounts_round_at_the_currency.sql +2403 -0
  70. package/dist/assets/migrations/20260914134325_schema_version_0_2_0.sql +36 -0
  71. package/dist/assets/migrations/20260914143915_accounts_in_use.sql +428 -0
  72. package/dist/assets/migrations/20260914144731_account_code_frozen.sql +99 -0
  73. package/dist/assets/migrations/20260914151207_schema_grants_its_own_rights.sql +284 -0
  74. package/dist/assets/migrations/20260914152840_pack_upgrade_records_its_own_line.sql +237 -0
  75. package/dist/assets/migrations/20260914163943_declaration_periodicity.sql +349 -0
  76. package/dist/assets/migrations/20260915094000_foreign_services_received.sql +37 -0
  77. package/dist/assets/migrations/20260915094500_mentions_read_a_foreign_service.sql +72 -0
  78. package/dist/assets/migrations/20260915153000_document_shares.sql +568 -0
  79. package/dist/assets/migrations/20260915160000_ec_sales_list.sql +181 -0
  80. package/dist/assets/migrations/20260915161842_pack_sources.sql +56 -0
  81. package/dist/assets/migrations/20260915170500_schema_version_0_3_0.sql +45 -0
  82. package/dist/assets/migrations/20260915174500_a_vat_category_is_a_code.sql +177 -0
  83. package/dist/assets/migrations/20260915180000_document_rule_references.sql +85 -0
  84. package/dist/assets/migrations/20260915181000_territories.sql +342 -0
  85. package/dist/assets/migrations/20260915181500_ec_sales_list_reads_the_territories.sql +222 -0
  86. package/dist/assets/migrations/20260915182000_intracom_triangular.sql +53 -0
  87. package/dist/assets/migrations/20260915182500_a_triangular_supply_says_reverse_charge.sql +99 -0
  88. package/dist/assets/migrations/20260915191200_a_document_knows_its_language.sql +633 -0
  89. package/dist/assets/migrations/20260915195000_a_price_that_holds_its_tax.sql +649 -0
  90. package/dist/assets/migrations/20260915200000_a_posting_names_its_boxes.sql +1004 -0
  91. package/dist/assets/migrations/20260916094500_a_company_files_more_than_one_declaration.sql +795 -0
  92. package/dist/assets/migrations/20260916103000_a_ledger_line_names_its_posting.sql +902 -0
  93. package/dist/assets/migrations/20260916123000_a_vocabulary_for_a_tax_that_is_not_a_vat.sql +144 -0
  94. package/dist/assets/migrations/20260916124000_a_box_can_be_a_rate_of_a_box.sql +525 -0
  95. package/dist/assets/migrations/20260916125000_a_tax_follows_the_territory.sql +1318 -0
  96. package/dist/assets/migrations/20260916126000_a_tax_point_and_its_exception.sql +1211 -0
  97. package/dist/assets/migrations/20260917090000_a_counterparty_that_learns.sql +561 -0
  98. package/dist/assets/migrations/20260917120000_what_the_money_pays.sql +545 -0
  99. package/dist/assets/migrations/20260917150000_a_filing_is_a_row.sql +488 -0
  100. package/dist/assets/migrations/20260917170000_when_it_is_due.sql +194 -0
  101. package/dist/assets/migrations/20260917180000_a_box_is_a_number_and_a_kind.sql +213 -0
  102. package/dist/assets/migrations/20260917190000_what_a_declaration_owes.sql +486 -0
  103. package/dist/assets/migrations/20260917200000_what_moved_after_it_went.sql +227 -0
  104. package/dist/assets/migrations/20260918090000_a_form_names_its_file.sql +27 -0
  105. package/dist/assets/migrations/20260918110000_a_deposit_and_what_came_back.sql +286 -0
  106. package/dist/assets/migrations/20260918113741_a_fourth_preset_is_named.sql +9 -0
  107. package/dist/assets/migrations/20260918113807_a_client_reads_and_hands_over.sql +96 -0
  108. package/dist/assets/migrations/20260918114322_two_definer_functions_check_their_caller.sql +75 -0
  109. package/dist/assets/migrations/20260918130000_every_company_somebody_keeps.sql +177 -0
  110. package/dist/assets/migrations/20260918140000_a_session_nobody_prepared.sql +40 -0
  111. package/dist/assets/migrations/20260918141107_a_line_keeps_the_tax_it_was_posted_with.sql +256 -0
  112. package/dist/assets/migrations/20260918141342_a_company_has_an_electronic_address.sql +66 -0
  113. package/dist/assets/migrations/20260918141605_an_invoice_reads_whole_from_the_views.sql +313 -0
  114. package/dist/assets/migrations/20260918141627_a_policy_asks_once.sql +132 -0
  115. package/dist/assets/migrations/20260918143352_a_suggestion_reads_the_words_once.sql +204 -0
  116. package/dist/assets/migrations/20260918143417_a_reference_of_the_caller_and_a_rehearsal.sql +115 -0
  117. package/dist/assets/migrations/20260918150712_a_company_leaves_with_its_books.sql +1119 -0
  118. package/dist/assets/migrations/20260918150931_a_statement_is_imported_once.sql +654 -0
  119. package/dist/assets/migrations/20260918161204_a_posted_document_does_not_move.sql +437 -0
  120. package/dist/assets/migrations/20260918161538_a_posted_entry_does_not_move.sql +252 -0
  121. package/dist/assets/migrations/20260918171946_an_entry_is_posted_by_post_entry.sql +289 -0
  122. package/dist/assets/migrations/20260918174312_schema_version_0_4_0.sql +53 -0
  123. package/dist/assets/modules/assets/module.json +13 -0
  124. package/dist/assets/modules/assets/supabase/migrations/20260913081447_assets.sql +1190 -0
  125. package/dist/assets/modules/assets/supabase/migrations/20260913104234_foreign_key_indexes.sql +47 -0
  126. package/dist/assets/modules/assets/supabase/migrations/20260913104500_assets_capabilities.sql +145 -0
  127. package/dist/assets/modules/assets/supabase/migrations/20260914122100_assets_round_at_the_currency.sql +564 -0
  128. package/dist/assets/modules/assets/supabase/migrations/20260914145012_assets_accounts_in_use.sql +37 -0
  129. package/dist/assets/modules/assets/supabase/migrations/20260914151530_assets_grants_its_own_rights.sql +63 -0
  130. package/dist/assets/modules/assets/supabase/migrations/20260918113912_assets_client_reads.sql +20 -0
  131. package/dist/assets/modules/assets/supabase/migrations/20260918150801_assets_leave_with_the_company.sql +41 -0
  132. package/dist/assets/modules/budgets/module.json +12 -0
  133. package/dist/assets/modules/budgets/supabase/migrations/20260913083012_budgets.sql +210 -0
  134. package/dist/assets/modules/budgets/supabase/migrations/20260913104233_foreign_key_indexes.sql +37 -0
  135. package/dist/assets/modules/budgets/supabase/migrations/20260913104501_budgets_capabilities.sql +72 -0
  136. package/dist/assets/modules/budgets/supabase/migrations/20260914122400_budgets_round_at_the_currency.sql +68 -0
  137. package/dist/assets/modules/budgets/supabase/migrations/20260914145048_budgets_accounts_in_use.sql +30 -0
  138. package/dist/assets/modules/budgets/supabase/migrations/20260914151812_budgets_grants_its_own_rights.sql +31 -0
  139. package/dist/assets/modules/budgets/supabase/migrations/20260918113954_budgets_client_reads.sql +20 -0
  140. package/dist/assets/modules/budgets/supabase/migrations/20260918150823_budgets_leave_with_the_company.sql +37 -0
  141. package/dist/assets/modules/schema/module.1.json +69 -0
  142. package/dist/assets/seed/00_currencies.sql +15 -0
  143. package/dist/assets/seed/00_territories.sql +280 -0
  144. package/dist/assets/seed/05_framework_generic.sql +110 -0
  145. package/dist/assets/seed/10_pack_be.sql +1284 -0
  146. package/dist/assets/seed/11_pack_fr.sql +1112 -0
  147. package/dist/assets/seed/12_pack_lu.sql +2484 -0
  148. package/dist/assets/seed/13_pack_ee.sql +733 -0
  149. package/dist/assets/seed/14_pack_gb.sql +796 -0
  150. package/dist/assets/seed/15_pack_us.sql +751 -0
  151. package/dist/assets/seed/90_demo_company.sql +368 -0
  152. package/dist/assets/seed/modules/assets/10_pack_be.sql +58 -0
  153. package/dist/assets/seed/modules/assets/11_pack_fr.sql +57 -0
  154. package/dist/assets/seed/modules/assets/14_pack_gb.sql +58 -0
  155. package/dist/assets/seed/modules/assets/15_pack_us.sql +60 -0
  156. package/dist/auth.d.ts +59 -0
  157. package/dist/auth.d.ts.map +1 -0
  158. package/dist/auth.js +134 -0
  159. package/dist/auth.js.map +1 -0
  160. package/dist/bin.d.ts +6 -0
  161. package/dist/bin.d.ts.map +1 -0
  162. package/dist/bin.js +8 -0
  163. package/dist/bin.js.map +1 -0
  164. package/dist/books.d.ts +60 -0
  165. package/dist/books.d.ts.map +1 -0
  166. package/dist/books.js +168 -0
  167. package/dist/books.js.map +1 -0
  168. package/dist/bootstrap.d.ts +236 -0
  169. package/dist/bootstrap.d.ts.map +1 -0
  170. package/dist/bootstrap.js +459 -0
  171. package/dist/bootstrap.js.map +1 -0
  172. package/dist/bundle.d.ts +27 -0
  173. package/dist/bundle.d.ts.map +1 -0
  174. package/dist/bundle.js +47 -0
  175. package/dist/bundle.js.map +1 -0
  176. package/dist/checklist.d.ts +35 -0
  177. package/dist/checklist.d.ts.map +1 -0
  178. package/dist/checklist.js +64 -0
  179. package/dist/checklist.js.map +1 -0
  180. package/dist/cli.d.ts +14 -0
  181. package/dist/cli.d.ts.map +1 -0
  182. package/dist/cli.js +318 -0
  183. package/dist/cli.js.map +1 -0
  184. package/dist/commands/company.d.ts +59 -0
  185. package/dist/commands/company.d.ts.map +1 -0
  186. package/dist/commands/company.js +287 -0
  187. package/dist/commands/company.js.map +1 -0
  188. package/dist/commands/contact.d.ts +9 -0
  189. package/dist/commands/contact.d.ts.map +1 -0
  190. package/dist/commands/contact.js +82 -0
  191. package/dist/commands/contact.js.map +1 -0
  192. package/dist/commands/demo.d.ts +19 -0
  193. package/dist/commands/demo.d.ts.map +1 -0
  194. package/dist/commands/demo.js +72 -0
  195. package/dist/commands/demo.js.map +1 -0
  196. package/dist/commands/doctor.d.ts +12 -0
  197. package/dist/commands/doctor.d.ts.map +1 -0
  198. package/dist/commands/doctor.js +68 -0
  199. package/dist/commands/doctor.js.map +1 -0
  200. package/dist/commands/document.d.ts +17 -0
  201. package/dist/commands/document.d.ts.map +1 -0
  202. package/dist/commands/document.js +217 -0
  203. package/dist/commands/document.js.map +1 -0
  204. package/dist/commands/init.d.ts +31 -0
  205. package/dist/commands/init.d.ts.map +1 -0
  206. package/dist/commands/init.js +535 -0
  207. package/dist/commands/init.js.map +1 -0
  208. package/dist/commands/login.d.ts +24 -0
  209. package/dist/commands/login.d.ts.map +1 -0
  210. package/dist/commands/login.js +128 -0
  211. package/dist/commands/login.js.map +1 -0
  212. package/dist/commands/migrate.d.ts +30 -0
  213. package/dist/commands/migrate.d.ts.map +1 -0
  214. package/dist/commands/migrate.js +115 -0
  215. package/dist/commands/migrate.js.map +1 -0
  216. package/dist/commands/module.d.ts +32 -0
  217. package/dist/commands/module.d.ts.map +1 -0
  218. package/dist/commands/module.js +285 -0
  219. package/dist/commands/module.js.map +1 -0
  220. package/dist/commands/pack.d.ts +22 -0
  221. package/dist/commands/pack.d.ts.map +1 -0
  222. package/dist/commands/pack.js +481 -0
  223. package/dist/commands/pack.js.map +1 -0
  224. package/dist/commands/payment.d.ts +15 -0
  225. package/dist/commands/payment.d.ts.map +1 -0
  226. package/dist/commands/payment.js +97 -0
  227. package/dist/commands/payment.js.map +1 -0
  228. package/dist/commands/register.d.ts +20 -0
  229. package/dist/commands/register.d.ts.map +1 -0
  230. package/dist/commands/register.js +134 -0
  231. package/dist/commands/register.js.map +1 -0
  232. package/dist/commands/status.d.ts +8 -0
  233. package/dist/commands/status.d.ts.map +1 -0
  234. package/dist/commands/status.js +134 -0
  235. package/dist/commands/status.js.map +1 -0
  236. package/dist/commands/whoami.d.ts +21 -0
  237. package/dist/commands/whoami.d.ts.map +1 -0
  238. package/dist/commands/whoami.js +133 -0
  239. package/dist/commands/whoami.js.map +1 -0
  240. package/dist/company.d.ts +16 -0
  241. package/dist/company.d.ts.map +1 -0
  242. package/dist/company.js +26 -0
  243. package/dist/company.js.map +1 -0
  244. package/dist/config.d.ts +24 -0
  245. package/dist/config.d.ts.map +1 -0
  246. package/dist/config.js +50 -0
  247. package/dist/config.js.map +1 -0
  248. package/dist/connection.d.ts +79 -0
  249. package/dist/connection.d.ts.map +1 -0
  250. package/dist/connection.js +116 -0
  251. package/dist/connection.js.map +1 -0
  252. package/dist/context.d.ts +47 -0
  253. package/dist/context.d.ts.map +1 -0
  254. package/dist/context.js +93 -0
  255. package/dist/context.js.map +1 -0
  256. package/dist/doctor.d.ts +45 -0
  257. package/dist/doctor.d.ts.map +1 -0
  258. package/dist/doctor.js +448 -0
  259. package/dist/doctor.js.map +1 -0
  260. package/dist/grants.d.ts +88 -0
  261. package/dist/grants.d.ts.map +1 -0
  262. package/dist/grants.js +174 -0
  263. package/dist/grants.js.map +1 -0
  264. package/dist/identity.d.ts +54 -0
  265. package/dist/identity.d.ts.map +1 -0
  266. package/dist/identity.js +132 -0
  267. package/dist/identity.js.map +1 -0
  268. package/dist/index.d.ts +44 -0
  269. package/dist/index.d.ts.map +1 -0
  270. package/dist/index.js +43 -0
  271. package/dist/index.js.map +1 -0
  272. package/dist/inventory.d.ts +155 -0
  273. package/dist/inventory.d.ts.map +1 -0
  274. package/dist/inventory.js +303 -0
  275. package/dist/inventory.js.map +1 -0
  276. package/dist/migrations.d.ts +76 -0
  277. package/dist/migrations.d.ts.map +1 -0
  278. package/dist/migrations.js +226 -0
  279. package/dist/migrations.js.map +1 -0
  280. package/dist/module/read.d.ts +91 -0
  281. package/dist/module/read.d.ts.map +1 -0
  282. package/dist/module/read.js +172 -0
  283. package/dist/module/read.js.map +1 -0
  284. package/dist/output.d.ts +110 -0
  285. package/dist/output.d.ts.map +1 -0
  286. package/dist/output.js +173 -0
  287. package/dist/output.js.map +1 -0
  288. package/dist/pack/certification.d.ts +27 -0
  289. package/dist/pack/certification.d.ts.map +1 -0
  290. package/dist/pack/certification.js +38 -0
  291. package/dist/pack/certification.js.map +1 -0
  292. package/dist/pack/compile.d.ts +75 -0
  293. package/dist/pack/compile.d.ts.map +1 -0
  294. package/dist/pack/compile.js +801 -0
  295. package/dist/pack/compile.js.map +1 -0
  296. package/dist/pack/filing.d.ts +48 -0
  297. package/dist/pack/filing.d.ts.map +1 -0
  298. package/dist/pack/filing.js +56 -0
  299. package/dist/pack/filing.js.map +1 -0
  300. package/dist/pack/read.d.ts +766 -0
  301. package/dist/pack/read.d.ts.map +1 -0
  302. package/dist/pack/read.js +2336 -0
  303. package/dist/pack/read.js.map +1 -0
  304. package/dist/pack/schema.d.ts +26 -0
  305. package/dist/pack/schema.d.ts.map +1 -0
  306. package/dist/pack/schema.js +181 -0
  307. package/dist/pack/schema.js.map +1 -0
  308. package/dist/pack/territories.d.ts +98 -0
  309. package/dist/pack/territories.d.ts.map +1 -0
  310. package/dist/pack/territories.js +0 -0
  311. package/dist/pack/territories.js.map +1 -0
  312. package/dist/pack/upgrade.d.ts +86 -0
  313. package/dist/pack/upgrade.d.ts.map +1 -0
  314. package/dist/pack/upgrade.js +76 -0
  315. package/dist/pack/upgrade.js.map +1 -0
  316. package/dist/pack/vat-codes.d.ts +273 -0
  317. package/dist/pack/vat-codes.d.ts.map +1 -0
  318. package/dist/pack/vat-codes.js +513 -0
  319. package/dist/pack/vat-codes.js.map +1 -0
  320. package/dist/profiles.d.ts +67 -0
  321. package/dist/profiles.d.ts.map +1 -0
  322. package/dist/profiles.js +187 -0
  323. package/dist/profiles.js.map +1 -0
  324. package/dist/prompt.d.ts +40 -0
  325. package/dist/prompt.d.ts.map +1 -0
  326. package/dist/prompt.js +120 -0
  327. package/dist/prompt.js.map +1 -0
  328. package/dist/registry.d.ts +84 -0
  329. package/dist/registry.d.ts.map +1 -0
  330. package/dist/registry.js +104 -0
  331. package/dist/registry.js.map +1 -0
  332. package/dist/rest.d.ts +81 -0
  333. package/dist/rest.d.ts.map +1 -0
  334. package/dist/rest.js +245 -0
  335. package/dist/rest.js.map +1 -0
  336. package/dist/schema.d.ts +15 -0
  337. package/dist/schema.d.ts.map +1 -0
  338. package/dist/schema.js +15 -0
  339. package/dist/schema.js.map +1 -0
  340. package/dist/seeds.d.ts +27 -0
  341. package/dist/seeds.d.ts.map +1 -0
  342. package/dist/seeds.js +47 -0
  343. package/dist/seeds.js.map +1 -0
  344. package/dist/session.d.ts +39 -0
  345. package/dist/session.d.ts.map +1 -0
  346. package/dist/session.js +92 -0
  347. package/dist/session.js.map +1 -0
  348. package/dist/sql.d.ts +48 -0
  349. package/dist/sql.d.ts.map +1 -0
  350. package/dist/sql.js +112 -0
  351. package/dist/sql.js.map +1 -0
  352. package/dist/status.d.ts +94 -0
  353. package/dist/status.d.ts.map +1 -0
  354. package/dist/status.js +120 -0
  355. package/dist/status.js.map +1 -0
  356. package/dist/ui.d.ts +55 -0
  357. package/dist/ui.d.ts.map +1 -0
  358. package/dist/ui.js +114 -0
  359. package/dist/ui.js.map +1 -0
  360. package/package.json +29 -0
  361. package/schema/output.1.json +613 -0
@@ -0,0 +1,632 @@
1
+ -- Ekwo OS — a financial statement is data, and one of them fits any chart.
2
+ --
3
+ -- The schema could produce a trial balance and a ledger, and nothing that an
4
+ -- accountant files. A balance sheet was a query somebody would have written
5
+ -- in the application, once per country, which is how a country gets back into
6
+ -- the core through the front door.
7
+ --
8
+ -- Three tables and one function, filled by a pack:
9
+ --
10
+ -- `statement_templates` one statement of one framework — the Belgian
11
+ -- abbreviated scheme, the French liasse, the
12
+ -- generic one by account type.
13
+ -- `statement_line_templates` one line of it, with the plus/minus lists a
14
+ -- total is computed from.
15
+ -- `statement_line_rules` how accounts reach a line: by code range, by
16
+ -- code prefix, by account type, or one code.
17
+ --
18
+ -- **Mapping by code range is presentation, and presentation is allowed.** The
19
+ -- rule that forbids choosing an account *to post to* by prefix is about
20
+ -- posting. The NBB scheme, the liasse and every XBRL taxonomy map by ranges of
21
+ -- the legal chart — in Belgium the rubric code *is* the range, `40/41` being
22
+ -- accounts 40 and 41 — and refusing that would mean hand-listing four hundred
23
+ -- codes per country.
24
+ --
25
+ -- **The generic framework is what the eighteen account types buy.** A
26
+ -- statement whose `country` is null and whose rules are all `account_type`
27
+ -- gives a readable balance sheet on any chart, including the code-less charts
28
+ -- of the United Kingdom and the United States, and it is the fallback for a
29
+ -- company whose chart declares no statement of its own.
30
+ --
31
+ -- **`country` is nullable, so the key is the code alone.** A nullable column
32
+ -- cannot carry a primary key, and a statement code is unique across packs the
33
+ -- way a declaration form code is unique inside a country — `BE-BNB-ABBR-BS`,
34
+ -- `FR-2050`, `IFRS-SME-BS`. `chart_code` null means every chart of the
35
+ -- country; a statement that only fits one chart names it.
36
+ --
37
+ -- **A closing entry is not what a period earned.** `close_fiscal_year()` books
38
+ -- the mirror image of every income and expense account so the next year starts
39
+ -- at nil, and marks the entry `kind = 'closing'`. An income statement leaves
40
+ -- those out — a closed year would otherwise read as a result of zero — and a
41
+ -- balance sheet keeps them, because that entry is what carries the result onto
42
+ -- the line the balance sheet shows it on. An allocation section keeps them
43
+ -- too, and there is a limit there worth knowing: the appropriation entry and
44
+ -- the entry that zeroes the appropriation accounts are both `closing`, so the
45
+ -- two net out and a Belgian allocation section reads nil after a close. Making
46
+ -- it readable needs a kind that tells them apart, which is a change to
47
+ -- `close_fiscal_year()`, not to this file.
48
+ --
49
+ -- **Not copied into a company**, for the reason a declaration form is not: an
50
+ -- operator does not get to redefine what the Banque nationale prints. They are
51
+ -- reference data `financial_statement()` reads directly, which is also why
52
+ -- they carry no `company_id`.
53
+ --
54
+ -- **One evaluator, called twice.** A declaration form and a financial statement
55
+ -- derive their totals the same way — a list to add, a list to subtract — and
56
+ -- the two differences between them are parameters, not engines: a return omits
57
+ -- a box that comes to nothing where a statement prints its whole frame
58
+ -- (`p_keep_zero`), and a statement multiplies a line by the sign the scheme
59
+ -- reads it with (`factor`). `evaluate_totals()` below is that engine;
60
+ -- `vat_return()` is rewritten onto it in the migration that follows this one,
61
+ -- its own file because it was published before this.
62
+
63
+ -- ---------------------------------------------------------------------------
64
+ -- The statements
65
+ -- ---------------------------------------------------------------------------
66
+
67
+ create table if not exists statement_templates (
68
+ code text primary key,
69
+ country char(2),
70
+ chart_code text,
71
+ name text not null,
72
+ name_i18n jsonb not null default '{}'::jsonb,
73
+ kind text not null,
74
+ framework text,
75
+ valid_from date not null default date '1970-01-01',
76
+ valid_to date,
77
+ legal_reference text,
78
+ constraint statement_templates_country_format check (country is null or country ~ '^[A-Z]{2}$'),
79
+ constraint statement_templates_kind check (
80
+ kind in ('balance_sheet', 'income_statement', 'cash_flow', 'allocation')
81
+ ),
82
+ constraint statement_templates_chart_needs_country check (chart_code is null or country is not null),
83
+ constraint statement_templates_validity check (valid_to is null or valid_to >= valid_from)
84
+ );
85
+
86
+ comment on table statement_templates is
87
+ 'Financial statements per framework, from packs/<cc>/statements.json and packs/generic/. Reference data: never copied into a company.';
88
+ comment on column statement_templates.country is
89
+ 'Null on the generic framework, which reports by account type and fits any chart of any country.';
90
+ comment on column statement_templates.chart_code is
91
+ 'Null means every chart of the country. Filled when a statement only makes sense on one — a nonprofit scheme on a nonprofit chart.';
92
+ comment on column statement_templates.kind is
93
+ 'balance_sheet reads balances cumulative to the end of the period; income_statement and allocation read the movements of the period; cash_flow is declared and not yet produced.';
94
+ comment on column statement_templates.code is
95
+ 'Immutable once published. A new version of a scheme is a new code with its own validity, the way a new VAT rate is a new tax code.';
96
+
97
+ create index if not exists statement_templates_country_idx
98
+ on statement_templates (country, chart_code, kind);
99
+
100
+ -- ---------------------------------------------------------------------------
101
+ -- The lines
102
+ -- ---------------------------------------------------------------------------
103
+
104
+ create table if not exists statement_line_templates (
105
+ statement_code text not null references statement_templates(code) on delete cascade,
106
+ code text not null,
107
+ parent_code text,
108
+ name text not null,
109
+ name_i18n jsonb not null default '{}'::jsonb,
110
+ sequence integer not null default 10,
111
+ sign smallint not null default 1,
112
+ is_total boolean not null default false,
113
+ plus_lines text[] not null default '{}'::text[],
114
+ minus_lines text[] not null default '{}'::text[],
115
+ xbrl_element text,
116
+ legal_reference text,
117
+ primary key (statement_code, code),
118
+ constraint statement_line_templates_sign check (sign in (1, -1)),
119
+ -- A line is summed from the ledger or computed from other lines, never both.
120
+ constraint statement_line_templates_formula_is_a_total check (
121
+ is_total or (plus_lines = '{}'::text[] and minus_lines = '{}'::text[])
122
+ )
123
+ );
124
+
125
+ comment on table statement_line_templates is
126
+ 'The lines of a statement, in the order it prints them, and the plus/minus lists a total is computed from.';
127
+ comment on column statement_line_templates.sign is
128
+ 'Multiplies the debit-minus-credit balance so the line reads the way the scheme prints it: 1 on an asset or an expense, -1 on a liability, equity or income line.';
129
+ comment on column statement_line_templates.plus_lines is
130
+ 'Lines added into this total, by their code. Evaluated in `sequence` order, so a total may only name one computed before it.';
131
+ comment on column statement_line_templates.xbrl_element is
132
+ 'What an XBRL filing writes for this line. The NBB CBSO taxonomy is dimensional, so the value is a fact key — a metric and its dimension members, `met:am1|bas:m2` — and not an element name. Null where nothing is verified.';
133
+ comment on column statement_line_templates.parent_code is
134
+ 'The line this one details, for a renderer that indents. Structure only: a parent that is a total says so with its plus list.';
135
+
136
+ -- ---------------------------------------------------------------------------
137
+ -- The rules that bring accounts to a line
138
+ -- ---------------------------------------------------------------------------
139
+
140
+ create table if not exists statement_line_rules (
141
+ statement_code text not null,
142
+ line_code text not null,
143
+ sequence integer not null default 10,
144
+ rule_kind text not null,
145
+ code_from text,
146
+ code_to text,
147
+ account_type account_type,
148
+ balance_side text not null default 'any',
149
+ primary key (statement_code, line_code, sequence),
150
+ foreign key (statement_code, line_code)
151
+ references statement_line_templates (statement_code, code) on delete cascade,
152
+ constraint statement_line_rules_kind check (
153
+ rule_kind in ('account_code', 'code_range', 'code_prefix', 'account_type')
154
+ ),
155
+ constraint statement_line_rules_side check (balance_side in ('debit', 'credit', 'any')),
156
+ constraint statement_line_rules_arguments check (
157
+ case rule_kind
158
+ when 'account_type' then account_type is not null and code_from is null and code_to is null
159
+ when 'code_range' then code_from is not null and code_to is not null and account_type is null
160
+ else code_from is not null and code_to is null and account_type is null
161
+ end
162
+ )
163
+ );
164
+
165
+ comment on table statement_line_rules is
166
+ 'How an account of a company reaches a line. Presentation maps by range of the legal chart; choosing an account to post to by prefix stays forbidden, and is a different question.';
167
+ comment on column statement_line_rules.rule_kind is
168
+ 'account_code names one code; code_range and code_prefix compare the head of the code, so `40`..`41` takes 400000 and 411000 and stops at 42; account_type is what the generic framework is made of.';
169
+ comment on column statement_line_rules.balance_side is
170
+ 'Which side of the account this line takes. `any` takes it whatever it holds; `debit` and `credit` split one account between two lines — a suspense account is a receivable when it is in debit and a payable when it is in credit.';
171
+ comment on column statement_line_rules.sequence is
172
+ 'Order inside the line, and part of the key. Between two rules that both catch an account, the narrower one wins first, then this.';
173
+
174
+ create index if not exists statement_line_rules_line_idx
175
+ on statement_line_rules (statement_code, line_code);
176
+
177
+ -- ---------------------------------------------------------------------------
178
+ -- statement_account_matches — which line each account of a company falls on
179
+ --
180
+ -- One place decides it, so `financial_statement()` and `unmapped_accounts()`
181
+ -- can never disagree about what is on the statement and what is missing from
182
+ -- it. Priority: an exact code beats a range or a prefix, which beat an account
183
+ -- type; between two ranges the narrower head wins.
184
+ -- ---------------------------------------------------------------------------
185
+
186
+ create or replace function statement_account_matches(
187
+ p_company_id uuid,
188
+ p_statement_code text,
189
+ p_from date,
190
+ p_to date
191
+ )
192
+ returns table (
193
+ account_id uuid,
194
+ account_code text,
195
+ account_name text,
196
+ account_type account_type,
197
+ balance numeric,
198
+ line_code text
199
+ )
200
+ language sql
201
+ stable
202
+ as $$
203
+ with statement as (
204
+ select s.code, s.kind from statement_templates s where s.code = p_statement_code
205
+ ),
206
+ balances as (
207
+ select a.id, a.code, a.name, a.account_type,
208
+ round(coalesce(sum(l.balance), 0), 2) as balance
209
+ from accounts a
210
+ join entry_lines l on l.account_id = a.id
211
+ join entries e on e.id = l.entry_id
212
+ cross join statement st
213
+ where a.company_id = p_company_id
214
+ and e.state = 'posted'
215
+ and case when st.kind = 'balance_sheet'
216
+ then e.entry_date <= p_to
217
+ else e.entry_date between p_from and p_to
218
+ end
219
+ -- An income statement is what the period earned, and the entry that
220
+ -- closes a year is not that: it books the mirror image of every income
221
+ -- and expense account so they start the next year at nil. Left in, a
222
+ -- closed year reads as a result of zero. A balance sheet keeps it, and
223
+ -- must: that entry is what moves the result out of the income
224
+ -- statement and onto the line the balance sheet shows it on.
225
+ and (st.kind <> 'income_statement' or e.kind <> 'closing')
226
+ group by a.id, a.code, a.name, a.account_type
227
+ ),
228
+ ranked as (
229
+ select b.id, b.code, b.name, b.account_type, b.balance, r.line_code,
230
+ row_number() over (
231
+ partition by b.id
232
+ order by case r.rule_kind
233
+ when 'account_code' then 1
234
+ when 'code_range' then 2
235
+ when 'code_prefix' then 2
236
+ else 3
237
+ end,
238
+ length(coalesce(r.code_from, '')) desc,
239
+ r.sequence, r.line_code
240
+ ) as rank
241
+ from balances b
242
+ join statement_line_rules r on r.statement_code = p_statement_code
243
+ where case r.rule_kind
244
+ when 'account_code' then b.code = r.code_from
245
+ when 'code_prefix' then left(b.code, length(r.code_from)) = r.code_from
246
+ when 'code_range' then left(b.code, length(r.code_from)) >= r.code_from
247
+ and left(b.code, length(r.code_to)) <= r.code_to
248
+ else b.account_type = r.account_type
249
+ end
250
+ and case r.balance_side
251
+ when 'debit' then b.balance > 0
252
+ when 'credit' then b.balance < 0
253
+ else true
254
+ end
255
+ )
256
+ select b.id, b.code, b.name, b.account_type, b.balance, r.line_code
257
+ from balances b
258
+ left join ranked r on r.id = b.id and r.rank = 1
259
+ order by b.code;
260
+ $$;
261
+
262
+ comment on function statement_account_matches(uuid, text, date, date) is
263
+ 'Every account of a company with a balance in the period, and the statement line it falls on — null when no rule catches it. The single decision financial_statement() and unmapped_accounts() both read.';
264
+
265
+ -- ---------------------------------------------------------------------------
266
+ -- evaluate_totals — the one place a plus/minus formula is worked out
267
+ --
268
+ -- `p_values` what is already known, as `{ "<key>": <amount> }`.
269
+ -- `p_formulas` the totals to derive, as an array of
270
+ -- `{ key, plus[], minus[], floor_zero, factor, sequence }`.
271
+ -- `p_keep_zero` whether a total that comes to nothing is in the answer. It is
272
+ -- always in the working set either way, so a later total that
273
+ -- names it reads a zero and not a gap.
274
+ --
275
+ -- **A reference is resolved the way a declaration form needs it**, which costs
276
+ -- a statement nothing: `08:tax` names one key exactly, a bare `08` sums every
277
+ -- key whose head is `08` — the French CA3 carries a base and a tax on one
278
+ -- line, and a statement whose keys hold no separator gets a plain equality out
279
+ -- of the same rule.
280
+ --
281
+ -- **The totals are evaluated in the order they depend on each other**, not the
282
+ -- order they are declared: a balance sheet prints a subtotal above the lines it
283
+ -- adds up, and a declaration names a total computed before it. A reference that
284
+ -- names no formula is a value — present or nil, it is known already — so a
285
+ -- total over ledger boxes is ready on the first pass. A pass that settles
286
+ -- nothing is a cycle, and says which totals are in it.
287
+ -- ---------------------------------------------------------------------------
288
+
289
+ create or replace function evaluate_totals(
290
+ p_values jsonb,
291
+ p_formulas jsonb,
292
+ p_keep_zero boolean default false
293
+ )
294
+ returns jsonb
295
+ language plpgsql
296
+ immutable
297
+ as $$
298
+ declare
299
+ v_values jsonb := coalesce(p_values, '{}'::jsonb);
300
+ v_out jsonb := '{}'::jsonb;
301
+ v_done jsonb := '{}'::jsonb;
302
+ v_all jsonb := coalesce(p_formulas, '[]'::jsonb);
303
+ v_left integer;
304
+ v_settled integer;
305
+ v_ready boolean;
306
+ v_amount numeric;
307
+ v_part numeric;
308
+ v_refs text[];
309
+ v_ref text;
310
+ v_key text;
311
+ v_stuck text;
312
+ f jsonb;
313
+ begin
314
+ select count(*) into v_left from jsonb_array_elements(v_all);
315
+
316
+ while v_left > 0 loop
317
+ v_settled := 0;
318
+
319
+ for f in
320
+ select t.x from jsonb_array_elements(v_all) with ordinality as t(x, ord)
321
+ order by coalesce((t.x ->> 'sequence')::integer, 0), t.ord
322
+ loop
323
+ v_key := f ->> 'key';
324
+ if v_done ? v_key then
325
+ continue;
326
+ end if;
327
+
328
+ select coalesce(array_agg(e.value), '{}'::text[]) into v_refs
329
+ from (
330
+ select jsonb_array_elements_text(coalesce(f -> 'plus', '[]'::jsonb)) as value
331
+ union all
332
+ select jsonb_array_elements_text(coalesce(f -> 'minus', '[]'::jsonb))
333
+ ) as e;
334
+
335
+ -- Ready when every reference that names another formula has been worked
336
+ -- out already.
337
+ v_ready := true;
338
+ foreach v_ref in array v_refs loop
339
+ if exists (
340
+ select 1 from jsonb_array_elements(v_all) as g(x)
341
+ where (g.x ->> 'key') <> v_key
342
+ and not (v_done ? (g.x ->> 'key'))
343
+ and case when strpos(v_ref, ':') > 0
344
+ then (g.x ->> 'key') = replace(v_ref, ':', '|')
345
+ else split_part((g.x ->> 'key'), '|', 1) = v_ref
346
+ end
347
+ ) then
348
+ v_ready := false;
349
+ end if;
350
+ end loop;
351
+ if not v_ready then
352
+ continue;
353
+ end if;
354
+
355
+ v_amount := 0;
356
+ for v_ref in
357
+ select jsonb_array_elements_text(coalesce(f -> 'plus', '[]'::jsonb))
358
+ loop
359
+ select coalesce(sum(e.value::numeric), 0) into v_part
360
+ from jsonb_each_text(v_values) as e(key, value)
361
+ where case when strpos(v_ref, ':') > 0
362
+ then e.key = replace(v_ref, ':', '|')
363
+ else split_part(e.key, '|', 1) = v_ref
364
+ end;
365
+ v_amount := v_amount + v_part;
366
+ end loop;
367
+ for v_ref in
368
+ select jsonb_array_elements_text(coalesce(f -> 'minus', '[]'::jsonb))
369
+ loop
370
+ select coalesce(sum(e.value::numeric), 0) into v_part
371
+ from jsonb_each_text(v_values) as e(key, value)
372
+ where case when strpos(v_ref, ':') > 0
373
+ then e.key = replace(v_ref, ':', '|')
374
+ else split_part(e.key, '|', 1) = v_ref
375
+ end;
376
+ v_amount := v_amount - v_part;
377
+ end loop;
378
+
379
+ -- The floor belongs to the pair it splits — the Belgian 71 and 72, the
380
+ -- French 25 and 28 — so it applies before the sign the caller reads the
381
+ -- line with.
382
+ if coalesce((f ->> 'floor_zero')::boolean, false) then
383
+ v_amount := greatest(v_amount, 0);
384
+ end if;
385
+ v_amount := round(v_amount * coalesce((f ->> 'factor')::numeric, 1), 2);
386
+
387
+ v_values := v_values || jsonb_build_object(v_key, v_amount);
388
+ v_done := v_done || jsonb_build_object(v_key, true);
389
+ if p_keep_zero or v_amount <> 0 then
390
+ v_out := v_out || jsonb_build_object(v_key, v_amount);
391
+ end if;
392
+ v_settled := v_settled + 1;
393
+ v_left := v_left - 1;
394
+ end loop;
395
+
396
+ if v_settled = 0 then
397
+ select string_agg(t.x ->> 'key', ', ' order by t.x ->> 'key') into v_stuck
398
+ from jsonb_array_elements(v_all) as t(x)
399
+ where not (v_done ? (t.x ->> 'key'));
400
+ raise exception 'formula_cycle: these totals depend on each other and on nothing else: %', v_stuck;
401
+ end if;
402
+ end loop;
403
+
404
+ return v_out;
405
+ end;
406
+ $$;
407
+
408
+ comment on function evaluate_totals(jsonb, jsonb, boolean) is
409
+ 'Works out the plus/minus totals of a declaration form or of a financial statement, in the order they depend on each other. The one place that calculation lives: vat_return() and financial_statement() both call it.';
410
+
411
+ -- ---------------------------------------------------------------------------
412
+ -- financial_statement
413
+ -- ---------------------------------------------------------------------------
414
+
415
+ create or replace function financial_statement(
416
+ p_company_id uuid,
417
+ p_statement_code text,
418
+ p_from date,
419
+ p_to date
420
+ )
421
+ returns table (
422
+ line_code text,
423
+ parent_code text,
424
+ name text,
425
+ sequence integer,
426
+ is_total boolean,
427
+ amount numeric,
428
+ xbrl_element text
429
+ )
430
+ language plpgsql
431
+ stable
432
+ as $$
433
+ declare
434
+ -- line code -> amount: the lines summed from the ledger, then the totals
435
+ -- `evaluate_totals()` derives from them.
436
+ v_values jsonb := '{}'::jsonb;
437
+ v_formulas jsonb := '[]'::jsonb;
438
+ v_rows jsonb := '[]'::jsonb;
439
+ r record;
440
+ begin
441
+ if not exists (select 1 from companies c where c.id = p_company_id) then
442
+ raise exception 'unknown_company: %', p_company_id;
443
+ end if;
444
+ if not exists (select 1 from statement_templates s where s.code = p_statement_code) then
445
+ raise exception 'unknown_statement: % is not a statement of this installation', p_statement_code;
446
+ end if;
447
+
448
+ -- 1. The lines summed from the ledger. All of them first, whatever their
449
+ -- place in the scheme: a scheme prints a subtotal above the lines it adds
450
+ -- up — every balance sheet does — and only a total that names another
451
+ -- total depends on an order, which the evaluator keeps.
452
+ select coalesce(jsonb_object_agg(l.code, round(coalesce(s.balance, 0) * l.sign, 2)), '{}'::jsonb)
453
+ into v_values
454
+ from statement_line_templates l
455
+ left join (
456
+ select m.line_code, round(sum(m.balance), 2) as balance
457
+ from statement_account_matches(p_company_id, p_statement_code, p_from, p_to) m
458
+ where m.line_code is not null
459
+ group by m.line_code
460
+ ) s on s.line_code = l.code
461
+ where l.statement_code = p_statement_code
462
+ and not l.is_total;
463
+
464
+ -- 2. The totals, worked out by the one evaluator the declaration forms use.
465
+ -- A statement prints its whole frame, so every total comes back, and the
466
+ -- sign it reads the line with is the factor.
467
+ select coalesce(jsonb_agg(jsonb_build_object(
468
+ 'key', l.code, 'plus', to_jsonb(l.plus_lines), 'minus', to_jsonb(l.minus_lines),
469
+ 'factor', l.sign, 'sequence', l.sequence
470
+ ) order by l.sequence, l.code), '[]'::jsonb)
471
+ into v_formulas
472
+ from statement_line_templates l
473
+ where l.statement_code = p_statement_code
474
+ and l.is_total;
475
+
476
+ v_values := v_values || evaluate_totals(v_values, v_formulas, true);
477
+
478
+ -- 3. The frame, in the order it is printed. Every line is returned, nil
479
+ -- included: a statement is read top to bottom and tied out, where a
480
+ -- declaration prints what it has — which is why `vat_return()` drops a
481
+ -- nil box and this does not.
482
+ for r in
483
+ select l.code, l.parent_code, l.name, l.sequence, l.is_total, l.xbrl_element
484
+ from statement_line_templates l
485
+ where l.statement_code = p_statement_code
486
+ order by l.sequence, l.code
487
+ loop
488
+ v_rows := v_rows || jsonb_build_array(jsonb_build_object(
489
+ 'line_code', r.code, 'parent_code', r.parent_code, 'name', r.name,
490
+ 'sequence', r.sequence, 'is_total', r.is_total,
491
+ 'amount', coalesce((v_values ->> r.code)::numeric, 0),
492
+ 'xbrl_element', r.xbrl_element));
493
+ end loop;
494
+
495
+ return query
496
+ select (x ->> 'line_code')::text,
497
+ (x ->> 'parent_code')::text,
498
+ (x ->> 'name')::text,
499
+ (x ->> 'sequence')::integer,
500
+ (x ->> 'is_total')::boolean,
501
+ (x ->> 'amount')::numeric,
502
+ (x ->> 'xbrl_element')::text
503
+ from jsonb_array_elements(v_rows) as x;
504
+ end;
505
+ $$;
506
+
507
+ comment on function financial_statement(uuid, text, date, date) is
508
+ 'One financial statement of a company for a period: each line summed from the accounts its rules catch, then the totals evaluated in the order the scheme declares them. No country rule lives in this function.';
509
+
510
+ -- ---------------------------------------------------------------------------
511
+ -- unmapped_accounts — what the statement would silently leave out
512
+ -- ---------------------------------------------------------------------------
513
+
514
+ create or replace function unmapped_accounts(
515
+ p_company_id uuid,
516
+ p_statement_code text,
517
+ p_from date,
518
+ p_to date
519
+ )
520
+ returns table (
521
+ account_id uuid,
522
+ account_code text,
523
+ account_name text,
524
+ account_type account_type,
525
+ balance numeric
526
+ )
527
+ language sql
528
+ stable
529
+ as $$
530
+ select m.account_id, m.account_code, m.account_name, m.account_type, m.balance
531
+ from statement_account_matches(p_company_id, p_statement_code, p_from, p_to) m
532
+ join accounts a on a.id = m.account_id
533
+ cross join (select s.kind from statement_templates s where s.code = p_statement_code) st
534
+ where m.line_code is null
535
+ and m.balance <> 0
536
+ -- Only what this statement is answerable for. A revenue account is not
537
+ -- missing from a balance sheet, and a statement that claims no
538
+ -- completeness — an allocation section, a cash flow — reports nothing.
539
+ and case st.kind
540
+ when 'balance_sheet' then a.internal_group in ('asset', 'liability', 'equity')
541
+ when 'income_statement' then a.internal_group in ('income', 'expense')
542
+ else false
543
+ end
544
+ order by m.account_code;
545
+ $$;
546
+
547
+ comment on function unmapped_accounts(uuid, text, date, date) is
548
+ 'Accounts this statement is answerable for that carry a balance and that no rule of it catches. Empty is what makes the statement tie out; a row is an account somebody opened outside the pack.';
549
+
550
+ -- ---------------------------------------------------------------------------
551
+ -- available_statements — what a company can ask for
552
+ -- ---------------------------------------------------------------------------
553
+
554
+ create or replace function available_statements(p_company_id uuid, p_at date default null)
555
+ returns table (
556
+ code text,
557
+ name text,
558
+ kind text,
559
+ framework text,
560
+ country char(2),
561
+ chart_code text,
562
+ is_default boolean
563
+ )
564
+ language sql
565
+ stable
566
+ as $$
567
+ with company as (
568
+ select c.id, c.fiscal_country,
569
+ coalesce(
570
+ (select p.chart_code from company_packs p
571
+ where p.company_id = c.id and p.country = c.fiscal_country),
572
+ (select ch.code from chart_templates ch
573
+ where ch.country = c.fiscal_country and ch.is_default)
574
+ ) as chart_code
575
+ from companies c where c.id = p_company_id
576
+ )
577
+ select s.code, s.name, s.kind, s.framework, s.country, s.chart_code,
578
+ coalesce(s.code = any (ch.statements), false)
579
+ from statement_templates s
580
+ cross join company co
581
+ left join chart_templates ch
582
+ on ch.country = co.fiscal_country and ch.code = co.chart_code
583
+ where (s.country is null or s.country = co.fiscal_country)
584
+ and (s.chart_code is null or s.chart_code = co.chart_code)
585
+ and s.valid_from <= coalesce(p_at, current_date)
586
+ and (s.valid_to is null or s.valid_to >= coalesce(p_at, current_date))
587
+ order by s.country nulls last, s.kind, s.code;
588
+ $$;
589
+
590
+ comment on function available_statements(uuid, date) is
591
+ 'Statements a company may ask for: those of its country and chart, plus the generic framework. `is_default` marks the ones its chart declares.';
592
+
593
+ -- ---------------------------------------------------------------------------
594
+ -- Row level security
595
+ --
596
+ -- A scheme is reference data, like a chart of accounts and a declaration
597
+ -- form: any signed-in user may read it, and nobody writes it but the
598
+ -- generated seed, which runs as the owner. No write policy at all.
599
+ -- ---------------------------------------------------------------------------
600
+
601
+ alter table statement_templates enable row level security;
602
+ alter table statement_line_templates enable row level security;
603
+ alter table statement_line_rules enable row level security;
604
+
605
+ create policy statement_templates_select on statement_templates
606
+ for select using (auth.uid() is not null);
607
+ create policy statement_line_templates_select on statement_line_templates
608
+ for select using (auth.uid() is not null);
609
+ create policy statement_line_rules_select on statement_line_rules
610
+ for select using (auth.uid() is not null);
611
+
612
+ comment on policy statement_templates_select on statement_templates is
613
+ 'Reference data, readable by any signed-in user. No write policy: a statement comes from a pack.';
614
+
615
+ -- ---------------------------------------------------------------------------
616
+ -- One comment corrected
617
+ --
618
+ -- `20260912074712` said `statement_hint` would be "read by
619
+ -- financial_statement() (P0-4)". It is not: the rules of a statement decide
620
+ -- which line an account falls on, which is a property of the scheme and not of
621
+ -- the account, and a hint on the account would be a second place to keep in
622
+ -- step. The column stays — a chart may carry the intent, and a contributor
623
+ -- writing a pack has somewhere to put it — and its comment now says so.
624
+ -- ---------------------------------------------------------------------------
625
+
626
+ comment on column account_templates.statement_hint is
627
+ 'Free note: the statement line this account is meant for. Read by nothing — the rules of a statement decide — and kept so a chart can carry the intent.';
628
+ comment on column accounts.statement_hint is
629
+ 'Free note: the statement line this account is meant for. Read by nothing — the rules of a statement decide — and kept so a chart can carry the intent.';
630
+
631
+ -- Rule 6 of supabase/migrations/README.md.
632
+ revoke execute on all functions in schema public from public;