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.
- package/README.md +873 -0
- package/dist/args.d.ts +57 -0
- package/dist/args.d.ts.map +1 -0
- package/dist/args.js +134 -0
- package/dist/args.js.map +1 -0
- package/dist/assets/expected-objects.json +9432 -0
- package/dist/assets/migrations/20260911120000_core_companies.sql +260 -0
- package/dist/assets/migrations/20260911120100_accounts_journals.sql +211 -0
- package/dist/assets/migrations/20260911120200_contacts.sql +90 -0
- package/dist/assets/migrations/20260911120300_taxes.sql +146 -0
- package/dist/assets/migrations/20260911120400_entries.sql +338 -0
- package/dist/assets/migrations/20260911120500_documents.sql +279 -0
- package/dist/assets/migrations/20260911120600_payments_reconciliation.sql +251 -0
- package/dist/assets/migrations/20260911120700_bank.sql +178 -0
- package/dist/assets/migrations/20260911120800_analytics_attachments.sql +128 -0
- package/dist/assets/migrations/20260911120900_post_document.sql +279 -0
- package/dist/assets/migrations/20260911121000_reporting.sql +235 -0
- package/dist/assets/migrations/20260911121100_country_templates.sql +226 -0
- package/dist/assets/migrations/20260911121200_fec.sql +71 -0
- package/dist/assets/migrations/20260911130000_instance.sql +77 -0
- package/dist/assets/migrations/20260911130100_instance_members.sql +224 -0
- package/dist/assets/migrations/20260911140000_instance_admins.sql +112 -0
- package/dist/assets/migrations/20260911160000_tax_posting_templates_unique.sql +17 -0
- package/dist/assets/migrations/20260911170000_document_amount_paid.sql +82 -0
- package/dist/assets/migrations/20260911173000_post_payment.sql +122 -0
- package/dist/assets/migrations/20260911173100_sequence_counters_under_rls.sql +84 -0
- package/dist/assets/migrations/20260911183000_country_journal_defaults.sql +143 -0
- package/dist/assets/migrations/20260911193853_line_account_defaults.sql +274 -0
- package/dist/assets/migrations/20260911195054_products.sql +221 -0
- package/dist/assets/migrations/20260911210131_anon_surface.sql +85 -0
- package/dist/assets/migrations/20260912074712_country_packs.sql +318 -0
- package/dist/assets/migrations/20260912080311_report_code_and_region.sql +198 -0
- package/dist/assets/migrations/20260912081014_pack_certification_maintained.sql +31 -0
- package/dist/assets/migrations/20260912081015_pack_certification_backfill.sql +16 -0
- package/dist/assets/migrations/20260912090407_tax_report_boxes.sql +329 -0
- package/dist/assets/migrations/20260912091917_tax_on_base_value.sql +25 -0
- package/dist/assets/migrations/20260912091918_tax_engine_columns.sql +776 -0
- package/dist/assets/migrations/20260912094412_opening_and_closing.sql +759 -0
- package/dist/assets/migrations/20260912095825_charts_of_accounts.sql +326 -0
- package/dist/assets/migrations/20260912100412_financial_statements.sql +632 -0
- package/dist/assets/migrations/20260912104719_one_formula_evaluator.sql +209 -0
- package/dist/assets/migrations/20260912105720_entry_kind_appropriation.sql +26 -0
- package/dist/assets/migrations/20260912105721_appropriation_entry_kind.sql +444 -0
- package/dist/assets/migrations/20260912111751_document_rules.sql +274 -0
- package/dist/assets/migrations/20260912112132_cash_basis_vat_and_fx.sql +1189 -0
- package/dist/assets/migrations/20260913074512_modules.sql +493 -0
- package/dist/assets/migrations/20260913075903_asset_disposal_roles.sql +47 -0
- package/dist/assets/migrations/20260913083216_capabilities.sql +637 -0
- package/dist/assets/migrations/20260913083901_company_invitations.sql +262 -0
- package/dist/assets/migrations/20260913084402_user_preferences.sql +376 -0
- package/dist/assets/migrations/20260913084847_company_profile.sql +261 -0
- package/dist/assets/migrations/20260913085436_numbering_reads_the_pack.sql +235 -0
- package/dist/assets/migrations/20260913085932_api_keys.sql +303 -0
- package/dist/assets/migrations/20260913090216_fiscal_year_bounds.sql +159 -0
- package/dist/assets/migrations/20260913092527_entries_import.sql +219 -0
- package/dist/assets/migrations/20260913101536_null_safe_guards.sql +188 -0
- package/dist/assets/migrations/20260913102115_installer_is_named.sql +462 -0
- package/dist/assets/migrations/20260913102758_no_currency_default.sql +138 -0
- package/dist/assets/migrations/20260913103355_cash_basis_needs_a_box.sql +453 -0
- package/dist/assets/migrations/20260913104014_aged_balance_named_group.sql +79 -0
- package/dist/assets/migrations/20260913104232_foreign_key_indexes.sql +144 -0
- package/dist/assets/migrations/20260913105120_declared_no_reader.sql +41 -0
- package/dist/assets/migrations/20260913111407_pack_languages.sql +223 -0
- package/dist/assets/migrations/20260913112233_schema_comments_for_a_reader.sql +27 -0
- package/dist/assets/migrations/20260913114535_fec_opening_balances.sql +307 -0
- package/dist/assets/migrations/20260914103412_audit_log.sql +509 -0
- package/dist/assets/migrations/20260914111907_pack_upgrade.sql +428 -0
- package/dist/assets/migrations/20260914120500_rounding_reads_the_currency.sql +206 -0
- package/dist/assets/migrations/20260914121200_amounts_round_at_the_currency.sql +2403 -0
- package/dist/assets/migrations/20260914134325_schema_version_0_2_0.sql +36 -0
- package/dist/assets/migrations/20260914143915_accounts_in_use.sql +428 -0
- package/dist/assets/migrations/20260914144731_account_code_frozen.sql +99 -0
- package/dist/assets/migrations/20260914151207_schema_grants_its_own_rights.sql +284 -0
- package/dist/assets/migrations/20260914152840_pack_upgrade_records_its_own_line.sql +237 -0
- package/dist/assets/migrations/20260914163943_declaration_periodicity.sql +349 -0
- package/dist/assets/migrations/20260915094000_foreign_services_received.sql +37 -0
- package/dist/assets/migrations/20260915094500_mentions_read_a_foreign_service.sql +72 -0
- package/dist/assets/migrations/20260915153000_document_shares.sql +568 -0
- package/dist/assets/migrations/20260915160000_ec_sales_list.sql +181 -0
- package/dist/assets/migrations/20260915161842_pack_sources.sql +56 -0
- package/dist/assets/migrations/20260915170500_schema_version_0_3_0.sql +45 -0
- package/dist/assets/migrations/20260915174500_a_vat_category_is_a_code.sql +177 -0
- package/dist/assets/migrations/20260915180000_document_rule_references.sql +85 -0
- package/dist/assets/migrations/20260915181000_territories.sql +342 -0
- package/dist/assets/migrations/20260915181500_ec_sales_list_reads_the_territories.sql +222 -0
- package/dist/assets/migrations/20260915182000_intracom_triangular.sql +53 -0
- package/dist/assets/migrations/20260915182500_a_triangular_supply_says_reverse_charge.sql +99 -0
- package/dist/assets/migrations/20260915191200_a_document_knows_its_language.sql +633 -0
- package/dist/assets/migrations/20260915195000_a_price_that_holds_its_tax.sql +649 -0
- package/dist/assets/migrations/20260915200000_a_posting_names_its_boxes.sql +1004 -0
- package/dist/assets/migrations/20260916094500_a_company_files_more_than_one_declaration.sql +795 -0
- package/dist/assets/migrations/20260916103000_a_ledger_line_names_its_posting.sql +902 -0
- package/dist/assets/migrations/20260916123000_a_vocabulary_for_a_tax_that_is_not_a_vat.sql +144 -0
- package/dist/assets/migrations/20260916124000_a_box_can_be_a_rate_of_a_box.sql +525 -0
- package/dist/assets/migrations/20260916125000_a_tax_follows_the_territory.sql +1318 -0
- package/dist/assets/migrations/20260916126000_a_tax_point_and_its_exception.sql +1211 -0
- package/dist/assets/migrations/20260917090000_a_counterparty_that_learns.sql +561 -0
- package/dist/assets/migrations/20260917120000_what_the_money_pays.sql +545 -0
- package/dist/assets/migrations/20260917150000_a_filing_is_a_row.sql +488 -0
- package/dist/assets/migrations/20260917170000_when_it_is_due.sql +194 -0
- package/dist/assets/migrations/20260917180000_a_box_is_a_number_and_a_kind.sql +213 -0
- package/dist/assets/migrations/20260917190000_what_a_declaration_owes.sql +486 -0
- package/dist/assets/migrations/20260917200000_what_moved_after_it_went.sql +227 -0
- package/dist/assets/migrations/20260918090000_a_form_names_its_file.sql +27 -0
- package/dist/assets/migrations/20260918110000_a_deposit_and_what_came_back.sql +286 -0
- package/dist/assets/migrations/20260918113741_a_fourth_preset_is_named.sql +9 -0
- package/dist/assets/migrations/20260918113807_a_client_reads_and_hands_over.sql +96 -0
- package/dist/assets/migrations/20260918114322_two_definer_functions_check_their_caller.sql +75 -0
- package/dist/assets/migrations/20260918130000_every_company_somebody_keeps.sql +177 -0
- package/dist/assets/migrations/20260918140000_a_session_nobody_prepared.sql +40 -0
- package/dist/assets/migrations/20260918141107_a_line_keeps_the_tax_it_was_posted_with.sql +256 -0
- package/dist/assets/migrations/20260918141342_a_company_has_an_electronic_address.sql +66 -0
- package/dist/assets/migrations/20260918141605_an_invoice_reads_whole_from_the_views.sql +313 -0
- package/dist/assets/migrations/20260918141627_a_policy_asks_once.sql +132 -0
- package/dist/assets/migrations/20260918143352_a_suggestion_reads_the_words_once.sql +204 -0
- package/dist/assets/migrations/20260918143417_a_reference_of_the_caller_and_a_rehearsal.sql +115 -0
- package/dist/assets/migrations/20260918150712_a_company_leaves_with_its_books.sql +1119 -0
- package/dist/assets/migrations/20260918150931_a_statement_is_imported_once.sql +654 -0
- package/dist/assets/migrations/20260918161204_a_posted_document_does_not_move.sql +437 -0
- package/dist/assets/migrations/20260918161538_a_posted_entry_does_not_move.sql +252 -0
- package/dist/assets/migrations/20260918171946_an_entry_is_posted_by_post_entry.sql +289 -0
- package/dist/assets/migrations/20260918174312_schema_version_0_4_0.sql +53 -0
- package/dist/assets/modules/assets/module.json +13 -0
- package/dist/assets/modules/assets/supabase/migrations/20260913081447_assets.sql +1190 -0
- package/dist/assets/modules/assets/supabase/migrations/20260913104234_foreign_key_indexes.sql +47 -0
- package/dist/assets/modules/assets/supabase/migrations/20260913104500_assets_capabilities.sql +145 -0
- package/dist/assets/modules/assets/supabase/migrations/20260914122100_assets_round_at_the_currency.sql +564 -0
- package/dist/assets/modules/assets/supabase/migrations/20260914145012_assets_accounts_in_use.sql +37 -0
- package/dist/assets/modules/assets/supabase/migrations/20260914151530_assets_grants_its_own_rights.sql +63 -0
- package/dist/assets/modules/assets/supabase/migrations/20260918113912_assets_client_reads.sql +20 -0
- package/dist/assets/modules/assets/supabase/migrations/20260918150801_assets_leave_with_the_company.sql +41 -0
- package/dist/assets/modules/budgets/module.json +12 -0
- package/dist/assets/modules/budgets/supabase/migrations/20260913083012_budgets.sql +210 -0
- package/dist/assets/modules/budgets/supabase/migrations/20260913104233_foreign_key_indexes.sql +37 -0
- package/dist/assets/modules/budgets/supabase/migrations/20260913104501_budgets_capabilities.sql +72 -0
- package/dist/assets/modules/budgets/supabase/migrations/20260914122400_budgets_round_at_the_currency.sql +68 -0
- package/dist/assets/modules/budgets/supabase/migrations/20260914145048_budgets_accounts_in_use.sql +30 -0
- package/dist/assets/modules/budgets/supabase/migrations/20260914151812_budgets_grants_its_own_rights.sql +31 -0
- package/dist/assets/modules/budgets/supabase/migrations/20260918113954_budgets_client_reads.sql +20 -0
- package/dist/assets/modules/budgets/supabase/migrations/20260918150823_budgets_leave_with_the_company.sql +37 -0
- package/dist/assets/modules/schema/module.1.json +69 -0
- package/dist/assets/seed/00_currencies.sql +15 -0
- package/dist/assets/seed/00_territories.sql +280 -0
- package/dist/assets/seed/05_framework_generic.sql +110 -0
- package/dist/assets/seed/10_pack_be.sql +1284 -0
- package/dist/assets/seed/11_pack_fr.sql +1112 -0
- package/dist/assets/seed/12_pack_lu.sql +2484 -0
- package/dist/assets/seed/13_pack_ee.sql +733 -0
- package/dist/assets/seed/14_pack_gb.sql +796 -0
- package/dist/assets/seed/15_pack_us.sql +751 -0
- package/dist/assets/seed/90_demo_company.sql +368 -0
- package/dist/assets/seed/modules/assets/10_pack_be.sql +58 -0
- package/dist/assets/seed/modules/assets/11_pack_fr.sql +57 -0
- package/dist/assets/seed/modules/assets/14_pack_gb.sql +58 -0
- package/dist/assets/seed/modules/assets/15_pack_us.sql +60 -0
- package/dist/auth.d.ts +59 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +134 -0
- package/dist/auth.js.map +1 -0
- package/dist/bin.d.ts +6 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +8 -0
- package/dist/bin.js.map +1 -0
- package/dist/books.d.ts +60 -0
- package/dist/books.d.ts.map +1 -0
- package/dist/books.js +168 -0
- package/dist/books.js.map +1 -0
- package/dist/bootstrap.d.ts +236 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/bootstrap.js +459 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/bundle.d.ts +27 -0
- package/dist/bundle.d.ts.map +1 -0
- package/dist/bundle.js +47 -0
- package/dist/bundle.js.map +1 -0
- package/dist/checklist.d.ts +35 -0
- package/dist/checklist.d.ts.map +1 -0
- package/dist/checklist.js +64 -0
- package/dist/checklist.js.map +1 -0
- package/dist/cli.d.ts +14 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +318 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/company.d.ts +59 -0
- package/dist/commands/company.d.ts.map +1 -0
- package/dist/commands/company.js +287 -0
- package/dist/commands/company.js.map +1 -0
- package/dist/commands/contact.d.ts +9 -0
- package/dist/commands/contact.d.ts.map +1 -0
- package/dist/commands/contact.js +82 -0
- package/dist/commands/contact.js.map +1 -0
- package/dist/commands/demo.d.ts +19 -0
- package/dist/commands/demo.d.ts.map +1 -0
- package/dist/commands/demo.js +72 -0
- package/dist/commands/demo.js.map +1 -0
- package/dist/commands/doctor.d.ts +12 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +68 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/document.d.ts +17 -0
- package/dist/commands/document.d.ts.map +1 -0
- package/dist/commands/document.js +217 -0
- package/dist/commands/document.js.map +1 -0
- package/dist/commands/init.d.ts +31 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +535 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/login.d.ts +24 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +128 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/migrate.d.ts +30 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +115 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/module.d.ts +32 -0
- package/dist/commands/module.d.ts.map +1 -0
- package/dist/commands/module.js +285 -0
- package/dist/commands/module.js.map +1 -0
- package/dist/commands/pack.d.ts +22 -0
- package/dist/commands/pack.d.ts.map +1 -0
- package/dist/commands/pack.js +481 -0
- package/dist/commands/pack.js.map +1 -0
- package/dist/commands/payment.d.ts +15 -0
- package/dist/commands/payment.d.ts.map +1 -0
- package/dist/commands/payment.js +97 -0
- package/dist/commands/payment.js.map +1 -0
- package/dist/commands/register.d.ts +20 -0
- package/dist/commands/register.d.ts.map +1 -0
- package/dist/commands/register.js +134 -0
- package/dist/commands/register.js.map +1 -0
- package/dist/commands/status.d.ts +8 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +134 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/whoami.d.ts +21 -0
- package/dist/commands/whoami.d.ts.map +1 -0
- package/dist/commands/whoami.js +133 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/company.d.ts +16 -0
- package/dist/company.d.ts.map +1 -0
- package/dist/company.js +26 -0
- package/dist/company.js.map +1 -0
- package/dist/config.d.ts +24 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +50 -0
- package/dist/config.js.map +1 -0
- package/dist/connection.d.ts +79 -0
- package/dist/connection.d.ts.map +1 -0
- package/dist/connection.js +116 -0
- package/dist/connection.js.map +1 -0
- package/dist/context.d.ts +47 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +93 -0
- package/dist/context.js.map +1 -0
- package/dist/doctor.d.ts +45 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +448 -0
- package/dist/doctor.js.map +1 -0
- package/dist/grants.d.ts +88 -0
- package/dist/grants.d.ts.map +1 -0
- package/dist/grants.js +174 -0
- package/dist/grants.js.map +1 -0
- package/dist/identity.d.ts +54 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +132 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/inventory.d.ts +155 -0
- package/dist/inventory.d.ts.map +1 -0
- package/dist/inventory.js +303 -0
- package/dist/inventory.js.map +1 -0
- package/dist/migrations.d.ts +76 -0
- package/dist/migrations.d.ts.map +1 -0
- package/dist/migrations.js +226 -0
- package/dist/migrations.js.map +1 -0
- package/dist/module/read.d.ts +91 -0
- package/dist/module/read.d.ts.map +1 -0
- package/dist/module/read.js +172 -0
- package/dist/module/read.js.map +1 -0
- package/dist/output.d.ts +110 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +173 -0
- package/dist/output.js.map +1 -0
- package/dist/pack/certification.d.ts +27 -0
- package/dist/pack/certification.d.ts.map +1 -0
- package/dist/pack/certification.js +38 -0
- package/dist/pack/certification.js.map +1 -0
- package/dist/pack/compile.d.ts +75 -0
- package/dist/pack/compile.d.ts.map +1 -0
- package/dist/pack/compile.js +801 -0
- package/dist/pack/compile.js.map +1 -0
- package/dist/pack/filing.d.ts +48 -0
- package/dist/pack/filing.d.ts.map +1 -0
- package/dist/pack/filing.js +56 -0
- package/dist/pack/filing.js.map +1 -0
- package/dist/pack/read.d.ts +766 -0
- package/dist/pack/read.d.ts.map +1 -0
- package/dist/pack/read.js +2336 -0
- package/dist/pack/read.js.map +1 -0
- package/dist/pack/schema.d.ts +26 -0
- package/dist/pack/schema.d.ts.map +1 -0
- package/dist/pack/schema.js +181 -0
- package/dist/pack/schema.js.map +1 -0
- package/dist/pack/territories.d.ts +98 -0
- package/dist/pack/territories.d.ts.map +1 -0
- package/dist/pack/territories.js +0 -0
- package/dist/pack/territories.js.map +1 -0
- package/dist/pack/upgrade.d.ts +86 -0
- package/dist/pack/upgrade.d.ts.map +1 -0
- package/dist/pack/upgrade.js +76 -0
- package/dist/pack/upgrade.js.map +1 -0
- package/dist/pack/vat-codes.d.ts +273 -0
- package/dist/pack/vat-codes.d.ts.map +1 -0
- package/dist/pack/vat-codes.js +513 -0
- package/dist/pack/vat-codes.js.map +1 -0
- package/dist/profiles.d.ts +67 -0
- package/dist/profiles.d.ts.map +1 -0
- package/dist/profiles.js +187 -0
- package/dist/profiles.js.map +1 -0
- package/dist/prompt.d.ts +40 -0
- package/dist/prompt.d.ts.map +1 -0
- package/dist/prompt.js +120 -0
- package/dist/prompt.js.map +1 -0
- package/dist/registry.d.ts +84 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +104 -0
- package/dist/registry.js.map +1 -0
- package/dist/rest.d.ts +81 -0
- package/dist/rest.d.ts.map +1 -0
- package/dist/rest.js +245 -0
- package/dist/rest.js.map +1 -0
- package/dist/schema.d.ts +15 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +15 -0
- package/dist/schema.js.map +1 -0
- package/dist/seeds.d.ts +27 -0
- package/dist/seeds.d.ts.map +1 -0
- package/dist/seeds.js +47 -0
- package/dist/seeds.js.map +1 -0
- package/dist/session.d.ts +39 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +92 -0
- package/dist/session.js.map +1 -0
- package/dist/sql.d.ts +48 -0
- package/dist/sql.d.ts.map +1 -0
- package/dist/sql.js +112 -0
- package/dist/sql.js.map +1 -0
- package/dist/status.d.ts +94 -0
- package/dist/status.d.ts.map +1 -0
- package/dist/status.js +120 -0
- package/dist/status.js.map +1 -0
- package/dist/ui.d.ts +55 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +114 -0
- package/dist/ui.js.map +1 -0
- package/package.json +29 -0
- package/schema/output.1.json +613 -0
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
-- Ekwo OS — the boxes of a declaration, and the formulas that add them up.
|
|
2
|
+
--
|
|
3
|
+
-- `vat_return()` summed whatever the tax postings wrote on the ledger lines,
|
|
4
|
+
-- which is country-free, and then hard-coded the Belgian frame VI: boxes 71
|
|
5
|
+
-- and 72, their two lists of boxes, and a test on the company's fiscal
|
|
6
|
+
-- country. It was the last country rule left in the core. A French company
|
|
7
|
+
-- got no total at all, and a British one never would have.
|
|
8
|
+
--
|
|
9
|
+
-- A form is now data, like a chart of accounts and a tax:
|
|
10
|
+
--
|
|
11
|
+
-- `tax_report_templates` one row per declaration form of a country.
|
|
12
|
+
-- `tax_report_box_templates` one row per box, with the formula of a total.
|
|
13
|
+
--
|
|
14
|
+
-- **No expression language.** A total carries a list of boxes to add, a list
|
|
15
|
+
-- to subtract, and a floor at zero. That covers the Belgian 71/72, the French
|
|
16
|
+
-- 16, 23, 25 and 28, and the British box 5, and it is readable by the
|
|
17
|
+
-- accountant who wrote the pack. The day a country needs a real expression,
|
|
18
|
+
-- that is a discussion about the core, not a field added to a pack.
|
|
19
|
+
--
|
|
20
|
+
-- **A reference resolves to a box and a kind.** `"54"` names one box; the
|
|
21
|
+
-- French CA3 carries a base and a tax on the same line, so it writes
|
|
22
|
+
-- `"08:base"` and `"08:tax"`. `ekwo pack check` refuses a bare reference that
|
|
23
|
+
-- would match both, so the two spellings can never disagree.
|
|
24
|
+
--
|
|
25
|
+
-- **These tables are not copied into a company.** A chart of accounts is
|
|
26
|
+
-- customisable and a form is not: an operator does not get to redefine box 59.
|
|
27
|
+
-- They stay reference data, read straight by `vat_return()`.
|
|
28
|
+
--
|
|
29
|
+
-- A new version of a form is a **new code** with its own validity, the way a
|
|
30
|
+
-- new VAT rate is a new tax code: `(country, code)` is the key, `valid_from`
|
|
31
|
+
-- and `valid_to` say which one is in force, and the return of a past period
|
|
32
|
+
-- keeps giving the same answer.
|
|
33
|
+
|
|
34
|
+
-- ---------------------------------------------------------------------------
|
|
35
|
+
-- The forms
|
|
36
|
+
-- ---------------------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
create table if not exists tax_report_templates (
|
|
39
|
+
country char(2) not null,
|
|
40
|
+
code text not null,
|
|
41
|
+
name text not null,
|
|
42
|
+
name_i18n jsonb not null default '{}'::jsonb,
|
|
43
|
+
period text not null default 'month_or_quarter',
|
|
44
|
+
valid_from date not null default date '1970-01-01',
|
|
45
|
+
valid_to date,
|
|
46
|
+
legal_reference text,
|
|
47
|
+
is_periodic_return boolean not null default true,
|
|
48
|
+
primary key (country, code),
|
|
49
|
+
constraint tax_report_templates_country_format check (country ~ '^[A-Z]{2}$'),
|
|
50
|
+
constraint tax_report_templates_period check (
|
|
51
|
+
period in ('month', 'quarter', 'month_or_quarter', 'year')
|
|
52
|
+
),
|
|
53
|
+
constraint tax_report_templates_validity check (valid_to is null or valid_to >= valid_from)
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
comment on table tax_report_templates is
|
|
57
|
+
'Declaration forms per country, from packs/<cc>/tax_report.json. Reference data: a form is not customisable, so it is never copied into a company.';
|
|
58
|
+
comment on column tax_report_templates.code is
|
|
59
|
+
'BE-VAT-PERIODIC, FR-CA3. Immutable once published; a new version of a form is a new code with its own validity.';
|
|
60
|
+
comment on column tax_report_templates.is_periodic_return is
|
|
61
|
+
'True for the return a company files every month or quarter. vat_return() falls back to the one of the company''s fiscal country.';
|
|
62
|
+
comment on column tax_report_templates.name_i18n is
|
|
63
|
+
'Label by language. The pack format has no key for it yet, so it stays empty until i18n/ carries one.';
|
|
64
|
+
|
|
65
|
+
-- ---------------------------------------------------------------------------
|
|
66
|
+
-- The boxes
|
|
67
|
+
-- ---------------------------------------------------------------------------
|
|
68
|
+
|
|
69
|
+
create table if not exists tax_report_box_templates (
|
|
70
|
+
country char(2) not null,
|
|
71
|
+
report_code text not null,
|
|
72
|
+
box text not null,
|
|
73
|
+
kind text not null,
|
|
74
|
+
name text not null,
|
|
75
|
+
name_i18n jsonb not null default '{}'::jsonb,
|
|
76
|
+
sequence integer not null default 10,
|
|
77
|
+
plus_boxes text[] not null default '{}'::text[],
|
|
78
|
+
minus_boxes text[] not null default '{}'::text[],
|
|
79
|
+
floor_zero boolean not null default false,
|
|
80
|
+
hidden boolean not null default false,
|
|
81
|
+
xml_element text,
|
|
82
|
+
legal_reference text,
|
|
83
|
+
valid_from date,
|
|
84
|
+
valid_to date,
|
|
85
|
+
primary key (country, report_code, box, kind),
|
|
86
|
+
foreign key (country, report_code) references tax_report_templates (country, code) on delete cascade,
|
|
87
|
+
constraint tax_report_box_templates_kind check (kind in ('base', 'tax', 'total')),
|
|
88
|
+
-- A base or a tax box is summed from the ledger; only a total has a formula.
|
|
89
|
+
constraint tax_report_box_templates_formula_is_a_total check (
|
|
90
|
+
kind = 'total' or (plus_boxes = '{}'::text[] and minus_boxes = '{}'::text[])
|
|
91
|
+
),
|
|
92
|
+
constraint tax_report_box_templates_validity check (valid_to is null or valid_to >= valid_from)
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
comment on table tax_report_box_templates is
|
|
96
|
+
'The boxes of a declaration form, and the plus/minus lists a total is computed from. Read by vat_return().';
|
|
97
|
+
comment on column tax_report_box_templates.kind is
|
|
98
|
+
'base, tax or total. Not an enum: vat_return() has always answered in text, and a form that invents a fourth kind is a core change either way.';
|
|
99
|
+
comment on column tax_report_box_templates.plus_boxes is
|
|
100
|
+
'Boxes added into this total. A bare code names the box whatever its kind, "08:tax" names one kind — the French CA3 carries both on one line.';
|
|
101
|
+
comment on column tax_report_box_templates.floor_zero is
|
|
102
|
+
'A negative total is reported as zero, the other side of the pair carrying it: Belgian 71/72, French 25/28.';
|
|
103
|
+
comment on column tax_report_box_templates.hidden is
|
|
104
|
+
'An intermediate total the form does not print. vat_return() returns it with this flag rather than dropping it, so a caller can check a total it cannot see.';
|
|
105
|
+
comment on column tax_report_box_templates.valid_from is
|
|
106
|
+
'Null means the validity of the form itself. Filled only when a box appears or disappears inside one version of a form.';
|
|
107
|
+
|
|
108
|
+
create index if not exists tax_report_box_templates_report_idx
|
|
109
|
+
on tax_report_box_templates (country, report_code, sequence, box);
|
|
110
|
+
|
|
111
|
+
-- ---------------------------------------------------------------------------
|
|
112
|
+
-- vat_return, with no country in it
|
|
113
|
+
--
|
|
114
|
+
-- The three-argument signature is dropped first: an overload with a default
|
|
115
|
+
-- would make `vat_return(company, from, to)` ambiguous, and Postgres would
|
|
116
|
+
-- refuse the call every client makes today. The default parameter keeps that
|
|
117
|
+
-- call working.
|
|
118
|
+
-- ---------------------------------------------------------------------------
|
|
119
|
+
|
|
120
|
+
drop function if exists vat_return(uuid, date, date);
|
|
121
|
+
|
|
122
|
+
create or replace function vat_return(
|
|
123
|
+
p_company_id uuid,
|
|
124
|
+
p_from date,
|
|
125
|
+
p_to date,
|
|
126
|
+
p_report_code text default null
|
|
127
|
+
)
|
|
128
|
+
returns table (
|
|
129
|
+
box text,
|
|
130
|
+
kind text,
|
|
131
|
+
amount numeric,
|
|
132
|
+
computed boolean,
|
|
133
|
+
name text,
|
|
134
|
+
sequence integer,
|
|
135
|
+
hidden boolean,
|
|
136
|
+
report_code text
|
|
137
|
+
)
|
|
138
|
+
language plpgsql
|
|
139
|
+
stable
|
|
140
|
+
as $$
|
|
141
|
+
declare
|
|
142
|
+
-- 'box|kind' -> amount, for every box known so far. The totals are
|
|
143
|
+
-- evaluated in sequence order, so a total may name one computed before it.
|
|
144
|
+
v_values jsonb := '{}'::jsonb;
|
|
145
|
+
v_rows jsonb := '[]'::jsonb;
|
|
146
|
+
v_country char(2);
|
|
147
|
+
v_report text;
|
|
148
|
+
v_in char(2);
|
|
149
|
+
v_count integer;
|
|
150
|
+
v_codes text;
|
|
151
|
+
v_amount numeric;
|
|
152
|
+
v_part numeric;
|
|
153
|
+
v_ref text;
|
|
154
|
+
r record;
|
|
155
|
+
begin
|
|
156
|
+
select c.fiscal_country into v_country from companies c where c.id = p_company_id;
|
|
157
|
+
if not found then
|
|
158
|
+
raise exception 'unknown_company: %', p_company_id;
|
|
159
|
+
end if;
|
|
160
|
+
|
|
161
|
+
-- Which form. The caller names one, or the country files exactly one on
|
|
162
|
+
-- that date. Two and no name is a question only the caller can answer — a
|
|
163
|
+
-- Canadian company files the federal return and the Québec one at once — so
|
|
164
|
+
-- this asks instead of guessing.
|
|
165
|
+
if p_report_code is not null then
|
|
166
|
+
select t.country, t.code into v_in, v_report
|
|
167
|
+
from tax_report_templates t
|
|
168
|
+
where t.code = p_report_code
|
|
169
|
+
and t.valid_from <= p_to
|
|
170
|
+
and (t.valid_to is null or t.valid_to >= p_to)
|
|
171
|
+
order by t.country
|
|
172
|
+
limit 1;
|
|
173
|
+
if v_report is null then
|
|
174
|
+
raise exception 'unknown_tax_report: % is not a declaration form in force on %',
|
|
175
|
+
p_report_code, p_to;
|
|
176
|
+
end if;
|
|
177
|
+
else
|
|
178
|
+
select count(*), min(t.code), string_agg(t.code, ', ' order by t.code)
|
|
179
|
+
into v_count, v_report, v_codes
|
|
180
|
+
from tax_report_templates t
|
|
181
|
+
where t.country = v_country
|
|
182
|
+
and t.is_periodic_return
|
|
183
|
+
and t.valid_from <= p_to
|
|
184
|
+
and (t.valid_to is null or t.valid_to >= p_to);
|
|
185
|
+
if v_count > 1 then
|
|
186
|
+
raise exception 'ambiguous_tax_report: % files several declarations on % (%); name one',
|
|
187
|
+
v_country, p_to, v_codes;
|
|
188
|
+
end if;
|
|
189
|
+
v_in := v_country;
|
|
190
|
+
if v_count = 0 then
|
|
191
|
+
v_report := null; -- no pack for this country: the ledger boxes, and no total.
|
|
192
|
+
end if;
|
|
193
|
+
end if;
|
|
194
|
+
|
|
195
|
+
-- 1. What the tax postings wrote on the ledger. Unchanged: this half never
|
|
196
|
+
-- knew a country.
|
|
197
|
+
for r in
|
|
198
|
+
with ledger as (
|
|
199
|
+
select l.declaration_box as lbox,
|
|
200
|
+
case when l.tax_line then 'tax' else 'base' end as lkind,
|
|
201
|
+
round(sum(l.box_amount), 2) as lamount
|
|
202
|
+
from entry_lines l
|
|
203
|
+
join entries e on e.id = l.entry_id
|
|
204
|
+
where l.company_id = p_company_id
|
|
205
|
+
and e.state = 'posted'
|
|
206
|
+
and e.entry_date between p_from and p_to
|
|
207
|
+
and l.declaration_box is not null
|
|
208
|
+
-- A box number belongs to one form. A line whose posting names
|
|
209
|
+
-- another form is not on this declaration; one that names none is
|
|
210
|
+
-- the single-return case every European company is in.
|
|
211
|
+
and (v_report is null or coalesce((
|
|
212
|
+
select min(tp.report_code)
|
|
213
|
+
from tax_postings tp
|
|
214
|
+
where tp.tax_id = l.tax_id
|
|
215
|
+
and tp.declaration_box = l.declaration_box
|
|
216
|
+
and tp.posting_type =
|
|
217
|
+
(case when l.tax_line then 'tax' else 'base' end)::tax_posting_type
|
|
218
|
+
), v_report) = v_report)
|
|
219
|
+
group by 1, 2
|
|
220
|
+
having round(sum(l.box_amount), 2) <> 0
|
|
221
|
+
)
|
|
222
|
+
select g.lbox, g.lkind, g.lamount, b.name as lname,
|
|
223
|
+
b.sequence as lsequence, coalesce(b.hidden, false) as lhidden
|
|
224
|
+
from ledger g
|
|
225
|
+
left join tax_report_box_templates b
|
|
226
|
+
on b.country = v_in and b.report_code = v_report
|
|
227
|
+
and b.box = g.lbox and b.kind = g.lkind
|
|
228
|
+
order by coalesce(b.sequence, 2147483647), g.lbox, g.lkind
|
|
229
|
+
loop
|
|
230
|
+
v_values := v_values || jsonb_build_object(r.lbox || '|' || r.lkind, r.lamount);
|
|
231
|
+
v_rows := v_rows || jsonb_build_array(jsonb_build_object(
|
|
232
|
+
'box', r.lbox, 'kind', r.lkind, 'amount', r.lamount, 'computed', false,
|
|
233
|
+
'name', r.lname, 'sequence', r.lsequence, 'hidden', r.lhidden,
|
|
234
|
+
'report_code', v_report));
|
|
235
|
+
end loop;
|
|
236
|
+
|
|
237
|
+
-- 2. The totals of the form, in the order the form declares them.
|
|
238
|
+
if v_report is not null then
|
|
239
|
+
for r in
|
|
240
|
+
select b.box as tbox, b.name as tname, b.sequence as tsequence,
|
|
241
|
+
b.hidden as thidden, b.floor_zero as tfloor,
|
|
242
|
+
b.plus_boxes as tplus, b.minus_boxes as tminus
|
|
243
|
+
from tax_report_box_templates b
|
|
244
|
+
where b.country = v_in
|
|
245
|
+
and b.report_code = v_report
|
|
246
|
+
and b.kind = 'total'
|
|
247
|
+
and (b.valid_from is null or b.valid_from <= p_to)
|
|
248
|
+
and (b.valid_to is null or b.valid_to >= p_to)
|
|
249
|
+
order by b.sequence, b.box
|
|
250
|
+
loop
|
|
251
|
+
v_amount := 0;
|
|
252
|
+
-- A qualified reference names one kind; a bare one takes every kind
|
|
253
|
+
-- recorded in that box, which `pack check` has made unambiguous.
|
|
254
|
+
foreach v_ref in array r.tplus loop
|
|
255
|
+
select coalesce(sum(e.ref_value::numeric), 0) into v_part
|
|
256
|
+
from jsonb_each_text(v_values) as e(ref_key, ref_value)
|
|
257
|
+
where case when strpos(v_ref, ':') > 0
|
|
258
|
+
then e.ref_key = replace(v_ref, ':', '|')
|
|
259
|
+
else split_part(e.ref_key, '|', 1) = v_ref
|
|
260
|
+
end;
|
|
261
|
+
v_amount := v_amount + v_part;
|
|
262
|
+
end loop;
|
|
263
|
+
foreach v_ref in array r.tminus loop
|
|
264
|
+
select coalesce(sum(e.ref_value::numeric), 0) into v_part
|
|
265
|
+
from jsonb_each_text(v_values) as e(ref_key, ref_value)
|
|
266
|
+
where case when strpos(v_ref, ':') > 0
|
|
267
|
+
then e.ref_key = replace(v_ref, ':', '|')
|
|
268
|
+
else split_part(e.ref_key, '|', 1) = v_ref
|
|
269
|
+
end;
|
|
270
|
+
v_amount := v_amount - v_part;
|
|
271
|
+
end loop;
|
|
272
|
+
|
|
273
|
+
if r.tfloor then
|
|
274
|
+
v_amount := greatest(v_amount, 0);
|
|
275
|
+
end if;
|
|
276
|
+
|
|
277
|
+
-- A total is known to the boxes after it even when it is nil.
|
|
278
|
+
v_values := v_values || jsonb_build_object(r.tbox || '|total', v_amount);
|
|
279
|
+
|
|
280
|
+
-- Nil boxes are left out, as they always have been for the ledger ones:
|
|
281
|
+
-- a return prints what it has.
|
|
282
|
+
if v_amount <> 0 then
|
|
283
|
+
v_rows := v_rows || jsonb_build_array(jsonb_build_object(
|
|
284
|
+
'box', r.tbox, 'kind', 'total', 'amount', v_amount, 'computed', true,
|
|
285
|
+
'name', r.tname, 'sequence', r.tsequence, 'hidden', r.thidden,
|
|
286
|
+
'report_code', v_report));
|
|
287
|
+
end if;
|
|
288
|
+
end loop;
|
|
289
|
+
end if;
|
|
290
|
+
|
|
291
|
+
return query
|
|
292
|
+
select (x ->> 'box')::text,
|
|
293
|
+
(x ->> 'kind')::text,
|
|
294
|
+
(x ->> 'amount')::numeric,
|
|
295
|
+
(x ->> 'computed')::boolean,
|
|
296
|
+
(x ->> 'name')::text,
|
|
297
|
+
(x ->> 'sequence')::integer,
|
|
298
|
+
(x ->> 'hidden')::boolean,
|
|
299
|
+
(x ->> 'report_code')::text
|
|
300
|
+
from jsonb_array_elements(v_rows) as x;
|
|
301
|
+
end;
|
|
302
|
+
$$;
|
|
303
|
+
|
|
304
|
+
comment on function vat_return(uuid, date, date, text) is
|
|
305
|
+
'Declaration boxes for a period: summed from the ledger, then the totals of the country''s form evaluated in sequence order. No country rule lives in this function.';
|
|
306
|
+
|
|
307
|
+
-- ---------------------------------------------------------------------------
|
|
308
|
+
-- Row level security
|
|
309
|
+
--
|
|
310
|
+
-- A form is reference data, like a chart of accounts: any signed-in user may
|
|
311
|
+
-- read it, and nobody writes it but the generated seed, which runs as the
|
|
312
|
+
-- owner. Same policy as `account_templates` and `tax_posting_templates`, and
|
|
313
|
+
-- no write policy at all — deliberately.
|
|
314
|
+
-- ---------------------------------------------------------------------------
|
|
315
|
+
|
|
316
|
+
alter table tax_report_templates enable row level security;
|
|
317
|
+
alter table tax_report_box_templates enable row level security;
|
|
318
|
+
|
|
319
|
+
create policy tax_report_templates_select on tax_report_templates
|
|
320
|
+
for select using (auth.uid() is not null);
|
|
321
|
+
create policy tax_report_box_templates_select on tax_report_box_templates
|
|
322
|
+
for select using (auth.uid() is not null);
|
|
323
|
+
|
|
324
|
+
comment on policy tax_report_templates_select on tax_report_templates is
|
|
325
|
+
'Reference data, readable by any signed-in user. No write policy: a form comes from a pack.';
|
|
326
|
+
|
|
327
|
+
-- The rule of `20260911210131`, which its own default privileges cannot keep:
|
|
328
|
+
-- a function created now comes out executable by PUBLIC unless this runs.
|
|
329
|
+
revoke execute on all functions in schema public from public;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
-- Ekwo OS — a tax posting that lands on the account of the line it taxes.
|
|
2
|
+
--
|
|
3
|
+
-- `tax_posting_type` had two values: `base`, which is the line itself and
|
|
4
|
+
-- carries no account, and `tax`, which carries one. Neither can express the
|
|
5
|
+
-- most ordinary purchase invoice a Belgian or a French company receives: one
|
|
6
|
+
-- where part of the VAT is not deductible. A company car at 21 % gives 50 %
|
|
7
|
+
-- on the deductible VAT account and 50 % on the expense account, because
|
|
8
|
+
-- non-deductible VAT is not a receivable from the State — it is a cost, and
|
|
9
|
+
-- it follows the account of what was bought (CNC/CBN avis 2018/14, *accessorium
|
|
10
|
+
-- sequitur principale*; in France PCG art. 213-8 and BOI-BIC-CHG-20-20-10,
|
|
11
|
+
-- where a non-recoverable tax is part of the acquisition cost).
|
|
12
|
+
--
|
|
13
|
+
-- So a third value: `tax_on_base`. Like `base`, it carries no account, and
|
|
14
|
+
-- for the same reason — the account it lands on is the one the document line
|
|
15
|
+
-- names. Unlike `base`, its amount is a share of the *tax*, not of the base.
|
|
16
|
+
--
|
|
17
|
+
-- This is a file of its own because PostgreSQL refuses to use an enum value
|
|
18
|
+
-- in the transaction that added it, and the next migration writes it into a
|
|
19
|
+
-- check constraint. The same reason split `20260912081014` from
|
|
20
|
+
-- `20260912081015`; the rule is in `supabase/migrations/README.md`.
|
|
21
|
+
|
|
22
|
+
alter type tax_posting_type add value if not exists 'tax_on_base';
|
|
23
|
+
|
|
24
|
+
comment on type tax_posting_type is
|
|
25
|
+
'base: the line itself, no account. tax: an amount on a tax account. tax_on_base: a share of the tax posted on the account of the line, because it is a cost and not a claim on the State.';
|