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,493 @@
1
+ -- Ekwo OS — modules: one Postgres schema each, the ledger only through a function.
2
+ --
3
+ -- The socle is `public` and knows nothing about what is built beside it. A
4
+ -- module is a schema of its own — `assets`, `budgets`, `carbon` — with its own
5
+ -- migrations, its own row level security and its own tests. It depends on the
6
+ -- socle by foreign key (`public.companies`, `public.accounts`,
7
+ -- `public.contacts`, `public.products`, `public.fiscal_years`) and it never
8
+ -- writes the ledger by hand.
9
+ --
10
+ -- Three things live here, and nothing else:
11
+ --
12
+ -- 1. **The registry is a table, not code.** `modules` is one row per module
13
+ -- this installation carries, written by the module's own first migration.
14
+ -- There is deliberately no plugin registry in TypeScript: a module that
15
+ -- is installed is a schema that exists and a row that says so, and one
16
+ -- query answers "what is here" for the CLI, the MCP server and a human.
17
+ --
18
+ -- 2. **A module is enabled per company.** `company_modules` is that, and it
19
+ -- is written only by `enable_module()` and `disable_module()` — there is
20
+ -- no write policy on the table at all, so the guard inside the function
21
+ -- is the only way in rather than the polite way in. Same reason
22
+ -- `fiscal_years.is_closed` stopped being an ordinary column.
23
+ --
24
+ -- 3. **A module posts through `post_module_entry()`.** It assembles nothing:
25
+ -- it hands over a company, a date, a journal, a tag and a list of lines,
26
+ -- and the function builds the draft and calls `post_entry()` — which
27
+ -- stays the one place an entry is validated, numbered and locked against
28
+ -- a closed period. So a module never names `entries` or `entry_lines` in
29
+ -- a statement of its own, and a test over `modules/**` proves it.
30
+ --
31
+ -- **What the tag buys.** `entries.module_code` and `entries.module_ref` say
32
+ -- which module wrote an entry and what for, and a unique index on the three
33
+ -- makes a second posting of the same thing impossible rather than merely
34
+ -- discouraged. `assets.run_depreciation` is idempotent because the database
35
+ -- refuses the duplicate, not because the module remembered to look. Tagging by
36
+ -- `(module_code, ref)` is also why `entry_kind` gains no value per module: a
37
+ -- depreciation entry is a normal entry that a report may leave in.
38
+ --
39
+ -- **What the socle does not gain.** No hook, no callback, no way for a module
40
+ -- to change what posting means. The dependency points one way: a module reads
41
+ -- and calls the socle, the socle ignores its modules. The single exception is
42
+ -- `disable_module()`, which asks a module whether it still holds posted data —
43
+ -- by looking for `<schema>.can_disable(uuid)` and running it if it is there.
44
+ -- That is a convention rather than a column, so a module that holds nothing
45
+ -- writes nothing.
46
+
47
+ -- ---------------------------------------------------------------------------
48
+ -- The registry
49
+ -- ---------------------------------------------------------------------------
50
+
51
+ create type module_status as enum ('draft', 'available', 'deprecated');
52
+
53
+ comment on type module_status is
54
+ 'Whether a module may be enabled on a company: draft is not ready, available is, deprecated keeps the companies that already have it and refuses new ones.';
55
+
56
+ create table modules (
57
+ code text primary key,
58
+ name text not null,
59
+ description text,
60
+ -- The Postgres schema the module lives in. Unique, because two modules in
61
+ -- one schema is two sets of tables nobody can tell apart.
62
+ schema_name text not null unique,
63
+ version text not null,
64
+ status module_status not null default 'draft',
65
+ -- The oldest socle migration this module needs, as its timestamp version —
66
+ -- the same shape `country_packs.schema_min` uses. Read by `ekwo module
67
+ -- enable`, which holds the migration history and can compare; the function
68
+ -- below does not, because the history table is the CLI's business and a
69
+ -- database restored from a dump may not carry it.
70
+ requires_socle_min text,
71
+ created_at timestamptz not null default now(),
72
+ updated_at timestamptz not null default now(),
73
+ constraint modules_code_format check (code ~ '^[a-z][a-z0-9_]{1,30}$'),
74
+ constraint modules_schema_format check (schema_name ~ '^[a-z][a-z0-9_]{1,30}$'),
75
+ constraint modules_schema_not_public check (schema_name <> 'public')
76
+ );
77
+
78
+ comment on table modules is
79
+ 'One row per module this installation carries, written by the module''s own first migration. The registry is a table, not code.';
80
+ comment on column modules.schema_name is
81
+ 'The Postgres schema the module lives in. PostgREST only exposes it once it is listed in the API settings, which no migration can do — `ekwo module enable` prints the line to add.';
82
+ comment on column modules.requires_socle_min is
83
+ 'Oldest socle migration version this module needs. Read by `ekwo module enable` against the migration history.';
84
+
85
+ create trigger modules_set_updated_at
86
+ before update on modules
87
+ for each row execute function set_updated_at();
88
+
89
+ -- ---------------------------------------------------------------------------
90
+ -- Which company holds which module
91
+ -- ---------------------------------------------------------------------------
92
+
93
+ create table company_modules (
94
+ company_id uuid not null references companies(id) on delete cascade,
95
+ module_code text not null references modules(code) on delete restrict,
96
+ enabled_at timestamptz not null default now(),
97
+ enabled_by uuid,
98
+ settings jsonb not null default '{}'::jsonb,
99
+ primary key (company_id, module_code)
100
+ );
101
+
102
+ comment on table company_modules is
103
+ 'Modules enabled on a company, and the settings that company keeps for each. Written by enable_module() and disable_module() and by nothing else: there is no write policy.';
104
+ comment on column company_modules.settings is
105
+ 'Per-company settings of the module, in its own vocabulary. The socle never reads inside this object.';
106
+
107
+ create index company_modules_module_idx on company_modules (module_code);
108
+
109
+ -- ---------------------------------------------------------------------------
110
+ -- The two questions a module asks
111
+ --
112
+ -- `module_is_enabled` is the bare fact and answers for anybody. `module_enabled`
113
+ -- is the one a row level security policy calls: it is the fact **and** the
114
+ -- membership, so a module policy is one call and a stranger gets the same word
115
+ -- `is_company_member` already gives them — no. That is why it can be granted to
116
+ -- `anon` alongside the eight helpers: without the grant an anonymous select on
117
+ -- a module table would raise "permission denied for function" instead of
118
+ -- returning nothing, and an error is a louder answer than an empty set.
119
+ -- ---------------------------------------------------------------------------
120
+
121
+ create or replace function module_is_enabled(p_company_id uuid, p_code text)
122
+ returns boolean
123
+ language sql
124
+ stable
125
+ security definer
126
+ set search_path = public, pg_temp
127
+ as $$
128
+ select exists (
129
+ select 1 from company_modules m
130
+ where m.company_id = p_company_id and m.module_code = p_code
131
+ );
132
+ $$;
133
+
134
+ comment on function module_is_enabled(uuid, text) is
135
+ 'Whether a module is enabled on a company, regardless of who is asking. Definer so a policy on company_modules cannot recurse into it.';
136
+
137
+ create or replace function module_enabled(p_company_id uuid, p_code text)
138
+ returns boolean
139
+ language sql
140
+ stable
141
+ as $$
142
+ select is_company_member(p_company_id) and module_is_enabled(p_company_id, p_code);
143
+ $$;
144
+
145
+ comment on function module_enabled(uuid, text) is
146
+ 'The helper a module''s row level security policies call: this module is enabled on this company and the caller is a member of it. One call, and the answer to a stranger is no.';
147
+
148
+ create or replace function module_settings(p_company_id uuid, p_code text)
149
+ returns jsonb
150
+ language sql
151
+ stable
152
+ security definer
153
+ set search_path = public, pg_temp
154
+ as $$
155
+ select m.settings
156
+ from company_modules m
157
+ where m.company_id = p_company_id and m.module_code = p_code;
158
+ $$;
159
+
160
+ comment on function module_settings(uuid, text) is
161
+ 'The settings a company keeps for one of its modules, or null when the module is not enabled. The socle never looks inside the object.';
162
+
163
+ -- ---------------------------------------------------------------------------
164
+ -- Enabling and disabling
165
+ --
166
+ -- Both are definer with the guard written inside, because `company_modules`
167
+ -- has no write policy: the function is the only way in, and the rule applies
168
+ -- to psql and PostgREST alike. `register_instance()` is the same shape.
169
+ -- ---------------------------------------------------------------------------
170
+
171
+ create or replace function enable_module(
172
+ p_company_id uuid,
173
+ p_code text,
174
+ p_settings jsonb default null
175
+ )
176
+ returns company_modules
177
+ language plpgsql
178
+ security definer
179
+ set search_path = public, pg_temp
180
+ as $$
181
+ declare
182
+ v_module modules%rowtype;
183
+ v_row company_modules%rowtype;
184
+ begin
185
+ if not is_company_owner(p_company_id) then
186
+ raise exception 'not_company_owner: enabling a module on a company is the owner''s decision'
187
+ using errcode = '42501';
188
+ end if;
189
+
190
+ select * into v_module from modules where code = p_code;
191
+ if not found then
192
+ raise exception 'unknown_module: % is not installed on this instance; apply its migrations first', p_code;
193
+ end if;
194
+
195
+ if v_module.status = 'draft' and not module_is_enabled(p_company_id, p_code) then
196
+ raise exception 'module_not_available: % is still a draft on this installation', p_code;
197
+ end if;
198
+ if v_module.status = 'deprecated' and not module_is_enabled(p_company_id, p_code) then
199
+ raise exception 'module_deprecated: % is deprecated and takes no new company', p_code;
200
+ end if;
201
+
202
+ insert into company_modules (company_id, module_code, enabled_by, settings)
203
+ values (p_company_id, p_code, auth.uid(), coalesce(p_settings, '{}'::jsonb))
204
+ on conflict (company_id, module_code) do update
205
+ set settings = coalesce(p_settings, company_modules.settings)
206
+ returning * into v_row;
207
+
208
+ return v_row;
209
+ end;
210
+ $$;
211
+
212
+ comment on function enable_module(uuid, text, jsonb) is
213
+ 'Enables a module on a company, and updates its settings when it is already enabled. The owner''s decision, checked here because the table has no write policy.';
214
+
215
+ create or replace function disable_module(p_company_id uuid, p_code text)
216
+ returns void
217
+ language plpgsql
218
+ security definer
219
+ set search_path = public, pg_temp
220
+ as $$
221
+ declare
222
+ v_module modules%rowtype;
223
+ v_check regprocedure;
224
+ v_reason text;
225
+ begin
226
+ if not is_company_owner(p_company_id) then
227
+ raise exception 'not_company_owner: disabling a module on a company is the owner''s decision'
228
+ using errcode = '42501';
229
+ end if;
230
+
231
+ select * into v_module from modules where code = p_code;
232
+ if not found then
233
+ raise exception 'unknown_module: % is not installed on this instance', p_code;
234
+ end if;
235
+
236
+ if not module_is_enabled(p_company_id, p_code) then
237
+ return;
238
+ end if;
239
+
240
+ -- A module says for itself whether it still holds something a company would
241
+ -- lose. The convention is one function, `<schema>.can_disable(uuid)`,
242
+ -- returning null when there is nothing in the way and a sentence when there
243
+ -- is. A module that holds no posted data writes none, and `to_regprocedure`
244
+ -- answers null rather than raising.
245
+ v_check := to_regprocedure(format('%I.can_disable(uuid)', v_module.schema_name));
246
+ if v_check is not null then
247
+ execute format('select %I.can_disable($1)', v_module.schema_name)
248
+ into v_reason using p_company_id;
249
+ if v_reason is not null then
250
+ raise exception 'module_holds_data: % cannot be disabled on this company — %', p_code, v_reason
251
+ using errcode = '55006';
252
+ end if;
253
+ end if;
254
+
255
+ delete from company_modules
256
+ where company_id = p_company_id and module_code = p_code;
257
+ end;
258
+ $$;
259
+
260
+ comment on function disable_module(uuid, text) is
261
+ 'Disables a module on a company, unless the module says it still holds data — `<schema>.can_disable(company)` returning a sentence refuses, returning null allows. Nothing the module wrote is deleted.';
262
+
263
+ -- ---------------------------------------------------------------------------
264
+ -- The tag an entry carries when a module wrote it
265
+ -- ---------------------------------------------------------------------------
266
+
267
+ alter table entries
268
+ add column if not exists module_code text references modules(code) on delete restrict,
269
+ add column if not exists module_ref text;
270
+
271
+ comment on column entries.module_code is
272
+ 'Which module wrote this entry, or null for an entry of the socle. Set by post_module_entry().';
273
+ comment on column entries.module_ref is
274
+ 'What the entry is for, in the module''s own words — `depreciation:2026-03` , `disposal:<uuid>`. Unique per company and module, which is what makes a module''s posting idempotent.';
275
+
276
+ -- The idempotence of every module that posts, in one index. A second call that
277
+ -- would book the same period twice fails on the key rather than on a check the
278
+ -- module remembered to write.
279
+ create unique index entries_module_ref_idx
280
+ on entries (company_id, module_code, module_ref)
281
+ where module_code is not null and module_ref is not null;
282
+
283
+ create index entries_module_idx on entries (company_id, module_code)
284
+ where module_code is not null;
285
+
286
+ -- A tag is a fact about who wrote an entry, so it is written once and never
287
+ -- moved, and it may only name a module the company actually holds. An entry
288
+ -- carrying one is also never born posted: `post_module_entry` builds a draft
289
+ -- and lets `post_entry` do the posting, which is where the period lock, the
290
+ -- balance check and the numbering live.
291
+ create or replace function entries_guard_module()
292
+ returns trigger
293
+ language plpgsql
294
+ as $$
295
+ begin
296
+ if tg_op = 'INSERT' then
297
+ if new.module_code is not null then
298
+ if not module_is_enabled(new.company_id, new.module_code) then
299
+ raise exception 'module_not_enabled: % is not enabled on this company', new.module_code
300
+ using errcode = '55006';
301
+ end if;
302
+ if new.state = 'posted' then
303
+ raise exception 'module_entry_not_posted_by_hand: a module entry is built as a draft and posted by post_entry()'
304
+ using errcode = '55006';
305
+ end if;
306
+ end if;
307
+ return new;
308
+ end if;
309
+
310
+ if new.module_code is distinct from old.module_code
311
+ or new.module_ref is distinct from old.module_ref then
312
+ raise exception 'module_tag_immutable: which module wrote an entry, and what for, is written once'
313
+ using errcode = '55006';
314
+ end if;
315
+
316
+ return new;
317
+ end;
318
+ $$;
319
+
320
+ comment on function entries_guard_module() is
321
+ 'Keeps the module tag of an entry honest: a module the company holds, never posted on insert, never moved afterwards.';
322
+
323
+ create trigger entries_guard_module
324
+ before insert or update on entries
325
+ for each row execute function entries_guard_module();
326
+
327
+ -- ---------------------------------------------------------------------------
328
+ -- post_module_entry
329
+ --
330
+ -- The one way a module reaches the ledger. It takes the lines as data — the
331
+ -- same shape `opening_balance()` takes a trial balance in, because that is the
332
+ -- shape this schema has already chosen for "here are some ledger lines" — and
333
+ -- it does exactly what `post_document` and `post_payment` do with them: build
334
+ -- a draft, then `post_entry()`. Nothing about sides, rounding, numbering or
335
+ -- period locks moves into a module, which is the whole reason this function
336
+ -- exists rather than a grant on `entries`.
337
+ -- ---------------------------------------------------------------------------
338
+
339
+ create or replace function post_module_entry(
340
+ p_company_id uuid,
341
+ p_module_code text,
342
+ p_ref text,
343
+ p_date date,
344
+ p_description text,
345
+ p_lines jsonb,
346
+ p_journal_id uuid default null
347
+ )
348
+ returns uuid
349
+ language plpgsql
350
+ as $$
351
+ declare
352
+ v_company companies%rowtype;
353
+ v_journal uuid;
354
+ v_entry entries%rowtype;
355
+ v_line jsonb;
356
+ v_account uuid;
357
+ v_code text;
358
+ v_debit numeric(16, 2);
359
+ v_credit numeric(16, 2);
360
+ v_sequence integer := 0;
361
+ v_debits numeric(16, 2) := 0;
362
+ v_credits numeric(16, 2) := 0;
363
+ begin
364
+ select * into v_company from companies where id = p_company_id;
365
+ if not found then
366
+ raise exception 'unknown_company: %', p_company_id;
367
+ end if;
368
+
369
+ if not module_is_enabled(p_company_id, p_module_code) then
370
+ raise exception 'module_not_enabled: % is not enabled on this company', p_module_code
371
+ using errcode = '55006';
372
+ end if;
373
+
374
+ if p_ref is null or p_ref = '' then
375
+ raise exception 'module_entry_without_ref: an entry written by a module says what it is for, so a second one cannot repeat it';
376
+ end if;
377
+
378
+ if jsonb_typeof(p_lines) <> 'array' or jsonb_array_length(p_lines) = 0 then
379
+ raise exception 'module_entry_empty: post_module_entry takes a non-empty array of lines';
380
+ end if;
381
+
382
+ -- The miscellaneous journal unless the caller names one. A module booking is
383
+ -- not a movement of money and not a document, so it has no business on a
384
+ -- bank or a sales journal — the same reasoning that put the exchange
385
+ -- difference and the cash-basis transfer there.
386
+ v_journal := coalesce(p_journal_id, v_company.miscellaneous_journal_id);
387
+ if v_journal is null then
388
+ raise exception 'no_miscellaneous_journal: this company has no journal for an entry that is neither a document nor a payment';
389
+ end if;
390
+
391
+ insert into entries (company_id, journal_id, fiscal_year_id, entry_date,
392
+ description, state, module_code, module_ref)
393
+ values (p_company_id, v_journal, fiscal_year_at(p_company_id, p_date), p_date,
394
+ p_description, 'draft', p_module_code, p_ref)
395
+ returning * into v_entry;
396
+
397
+ for v_line in select * from jsonb_array_elements(p_lines)
398
+ loop
399
+ v_sequence := v_sequence + 10;
400
+ v_code := v_line ->> 'account_code';
401
+ v_account := (v_line ->> 'account_id')::uuid;
402
+ if v_account is null then
403
+ if v_code is null then
404
+ raise exception 'module_line_without_account: line % names neither account_id nor account_code', v_sequence / 10;
405
+ end if;
406
+ v_account := account_id_by_code(p_company_id, v_code);
407
+ if v_account is null then
408
+ raise exception 'unknown_account: % is not an account of this company', v_code;
409
+ end if;
410
+ end if;
411
+
412
+ v_debit := round(coalesce((v_line ->> 'debit')::numeric, 0), 2);
413
+ v_credit := round(coalesce((v_line ->> 'credit')::numeric, 0), 2);
414
+ if v_debit < 0 or v_credit < 0 then
415
+ raise exception 'module_line_negative: a line chooses a side, never a sign';
416
+ end if;
417
+ if v_debit <> 0 and v_credit <> 0 then
418
+ raise exception 'module_line_two_sides: a line carries a debit or a credit, not both';
419
+ end if;
420
+ if v_debit = 0 and v_credit = 0 then
421
+ raise exception 'module_line_no_amount: a line with neither a debit nor a credit says nothing';
422
+ end if;
423
+
424
+ insert into entry_lines (entry_id, company_id, account_id, sequence, name,
425
+ debit, credit, contact_id, date_maturity)
426
+ values (v_entry.id, p_company_id, v_account, v_sequence,
427
+ coalesce(v_line ->> 'label', p_description),
428
+ v_debit, v_credit,
429
+ (v_line ->> 'contact_id')::uuid,
430
+ (v_line ->> 'date_maturity')::date);
431
+
432
+ v_debits := v_debits + v_debit;
433
+ v_credits := v_credits + v_credit;
434
+ end loop;
435
+
436
+ if v_debits <> v_credits then
437
+ raise exception 'entry_unbalanced: the lines of % have debit % and credit %', p_ref, v_debits, v_credits;
438
+ end if;
439
+
440
+ v_entry := post_entry(v_entry.id);
441
+ return v_entry.id;
442
+ end;
443
+ $$;
444
+
445
+ comment on function post_module_entry(uuid, text, text, date, text, jsonb, uuid) is
446
+ 'The only way a module reaches the ledger: it hands over lines as data and this builds the draft and calls post_entry(). The tag (module_code, ref) is unique per company, so posting the same thing twice is refused by the database.';
447
+
448
+ create or replace function module_entry_id(p_company_id uuid, p_module_code text, p_ref text)
449
+ returns uuid
450
+ language sql
451
+ stable
452
+ as $$
453
+ select e.id
454
+ from entries e
455
+ where e.company_id = p_company_id
456
+ and e.module_code = p_module_code
457
+ and e.module_ref = p_ref
458
+ and e.state = 'posted'
459
+ limit 1;
460
+ $$;
461
+
462
+ comment on function module_entry_id(uuid, text, text) is
463
+ 'The entry a module already posted under a reference, or null. What a module reads before deciding it has work to do.';
464
+
465
+ -- ---------------------------------------------------------------------------
466
+ -- Row level security
467
+ --
468
+ -- `modules` is reference data about the installation, like `country_defaults`:
469
+ -- readable by anyone signed in, written by a migration. `company_modules` is
470
+ -- readable by the members of its company and written by the two functions
471
+ -- above, which is why it has no write policy at all.
472
+ -- ---------------------------------------------------------------------------
473
+
474
+ alter table modules enable row level security;
475
+ alter table company_modules enable row level security;
476
+
477
+ create policy modules_select on modules
478
+ for select using (auth.uid() is not null);
479
+
480
+ create policy company_modules_select on company_modules
481
+ for select using (is_company_member(company_id));
482
+
483
+ comment on policy company_modules_select on company_modules is
484
+ 'Members read. Nobody writes: enable_module() and disable_module() are the way in, and they check the owner themselves.';
485
+
486
+ -- The helper a module's policies call, for the same reason the eight policy
487
+ -- helpers of 20260911210131 keep theirs: without it an anonymous select on a
488
+ -- module table raises instead of returning nothing.
489
+ grant execute on function module_enabled(uuid, text) to anon;
490
+
491
+ -- A migration that adds a function ends with this line, from PUBLIC and never
492
+ -- from `anon`.
493
+ revoke execute on all functions in schema public from public;
@@ -0,0 +1,47 @@
1
+ -- Ekwo OS — where the disposal of a fixed asset lands, per country.
2
+ --
3
+ -- Four nullable columns on `country_defaults`, for the `assets` module to
4
+ -- read. They are in the socle and not in the module's own schema on purpose: a
5
+ -- role is the answer to "which account of this chart plays this part", and
6
+ -- `country_defaults` is the one place a pack answers it. A second roles table
7
+ -- per module would be a second source of truth for the same question — and
8
+ -- `ekwo pack check`, which already refuses a pack whose role codes are not in
9
+ -- *every* chart it ships, would not be checking the second one.
10
+ --
11
+ -- **There are four and not two, because two countries derecognise an asset
12
+ -- differently and neither is a variant of the other.**
13
+ --
14
+ -- `net_result` the asset and its accumulated depreciation are cleared, the
15
+ -- proceeds are booked, and the difference lands on one account
16
+ -- — a gain or a loss. Belgium: 763 and 663, which is how the
17
+ -- statutory income statement presents a *plus-value* or a
18
+ -- *moins-value de réalisation*.
19
+ -- `gross` the net book value is booked as a charge and the proceeds as
20
+ -- an income, both in full, and the result is the difference
21
+ -- between two lines the income statement prints separately.
22
+ -- France: 675 *valeurs comptables des éléments d'actif cédés*
23
+ -- and 775 *produits des cessions d'éléments d'actif*.
24
+ --
25
+ -- Which of the two a country follows is not a role, it is a mechanism, and it
26
+ -- lives with the rest of the module's country model in
27
+ -- `assets.country_rules` — the same division `closing_style` made between the
28
+ -- style and the accounts that style needs.
29
+ --
30
+ -- **None of the four carries a default.** A pack that says nothing about
31
+ -- disposals leaves them null and `assets.dispose_asset` refuses by name,
32
+ -- rather than booking a gain on the account another country happens to use.
33
+
34
+ alter table country_defaults
35
+ add column if not exists asset_disposal_gain_code text,
36
+ add column if not exists asset_disposal_loss_code text,
37
+ add column if not exists asset_disposal_proceeds_code text,
38
+ add column if not exists asset_disposal_value_code text;
39
+
40
+ comment on column country_defaults.asset_disposal_gain_code is
41
+ 'Net-result disposal: the account a gain on the disposal of a fixed asset lands on (Belgium 763). Null under the gross style, and null until a pack names one.';
42
+ comment on column country_defaults.asset_disposal_loss_code is
43
+ 'Net-result disposal: the account a loss lands on (Belgium 663). Left empty where the chart keeps one account for both signs, and then the gain account answers for both.';
44
+ comment on column country_defaults.asset_disposal_proceeds_code is
45
+ 'Gross disposal: the income account the proceeds of a sale are booked on in full (France 775). Null under the net-result style.';
46
+ comment on column country_defaults.asset_disposal_value_code is
47
+ 'Gross disposal: the charge account the net book value of the asset sold is booked on in full (France 675). Null under the net-result style.';