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,486 @@
|
|
|
1
|
+
-- Ekwo OS — what a declaration owes.
|
|
2
|
+
--
|
|
3
|
+
-- A return that was accepted leaves the books in a state nothing clears: the
|
|
4
|
+
-- tax accounts keep the collected and the deductible of the period, side by
|
|
5
|
+
-- side, and the amount actually owed to the administration is a subtraction
|
|
6
|
+
-- nobody wrote down. Every month that passes adds another period to the same
|
|
7
|
+
-- two accounts, and by the end of a year their balances say nothing at all —
|
|
8
|
+
-- not what is owed, not what was paid, not what is still open.
|
|
9
|
+
--
|
|
10
|
+
-- What is missing is one entry per declaration: the tax accounts of the period
|
|
11
|
+
-- go back to zero, and the net lands on the account that carries the debt
|
|
12
|
+
-- towards the administration. From there the money has somewhere to go —
|
|
13
|
+
-- the debt is a position that stays open until a payment settles it, and
|
|
14
|
+
-- `auto_settle()` matches that payment the way it matches any other.
|
|
15
|
+
--
|
|
16
|
+
-- Three rules, and they are the rules of the rest of this schema:
|
|
17
|
+
--
|
|
18
|
+
-- **The accounts come from the pack.** `tax_payable` and `tax_receivable` are
|
|
19
|
+
-- roles, like `rounding` or `retained_earnings`, and a pack that names neither
|
|
20
|
+
-- gets a refusal by name rather than the account another country happens to
|
|
21
|
+
-- use.
|
|
22
|
+
--
|
|
23
|
+
-- **The entry goes through `post_entry()`.** Nothing here inserts a posted
|
|
24
|
+
-- entry: the numbering, the period locks, the balance check and the audit
|
|
25
|
+
-- trail are the ones every other entry goes through.
|
|
26
|
+
--
|
|
27
|
+
-- **A declaration has at most one settlement.** The link is a column with a
|
|
28
|
+
-- unique index, so replaying is refused by the database and not by a caller
|
|
29
|
+
-- remembering.
|
|
30
|
+
--
|
|
31
|
+
-- Two things this does not do, on purpose.
|
|
32
|
+
--
|
|
33
|
+
-- *It settles the ledger, not the boxes.* The lines it clears are the ones the
|
|
34
|
+
-- return read — same window, same `tax_point_date` rule — but the figure it
|
|
35
|
+
-- carries to the debt account is what those lines sum to, not what the frozen
|
|
36
|
+
-- boxes say. The two can differ: a country that rounds what it claims to the
|
|
37
|
+
-- unit, a box a form asks for that no posting fills. Where they differ,
|
|
38
|
+
-- `filing_drift()` is the function that says so, and inventing an account to
|
|
39
|
+
-- absorb the difference here would be hiding exactly what it exists to show.
|
|
40
|
+
--
|
|
41
|
+
-- *A late entry in a settled period is not picked up.* It falls in the window
|
|
42
|
+
-- of a declaration that has gone; its treatment is a corrective, and a
|
|
43
|
+
-- corrective is what supersedes the filing and settles the difference.
|
|
44
|
+
|
|
45
|
+
-- ---------------------------------------------------------------------------
|
|
46
|
+
-- The two roles
|
|
47
|
+
-- ---------------------------------------------------------------------------
|
|
48
|
+
|
|
49
|
+
alter table country_defaults
|
|
50
|
+
add column if not exists tax_payable_code text,
|
|
51
|
+
add column if not exists tax_receivable_code text;
|
|
52
|
+
|
|
53
|
+
comment on column country_defaults.tax_payable_code is
|
|
54
|
+
'The account that carries what a filed declaration owes to the administration, once the tax accounts of the period have been cleared into it (FR 445510, LU 461412, GB 2210). It has to be an account apart from the ones the taxes themselves post to, and reconcilable, because the payment is matched against it. Null until a pack names one, and then settling refuses by name.';
|
|
55
|
+
comment on column country_defaults.tax_receivable_code is
|
|
56
|
+
'The same account for a period that ends in a credit, where the chart keeps the two apart (FR 445670). Null falls back to tax_payable_code, for a chart that keeps one control account whose sign says which way it goes.';
|
|
57
|
+
|
|
58
|
+
-- ---------------------------------------------------------------------------
|
|
59
|
+
-- What happens to a credit
|
|
60
|
+
--
|
|
61
|
+
-- A period that ends in the company's favour has two outcomes and they are not
|
|
62
|
+
-- the same object afterwards: carried forward, it will be absorbed by the next
|
|
63
|
+
-- declaration and nobody is waiting for money; claimed back, it is a
|
|
64
|
+
-- receivable that a repayment settles, and it belongs in the aged balance
|
|
65
|
+
-- until it arrives. Which of the two is the company's decision — most
|
|
66
|
+
-- administrations ask, and some make the answer conditional on an amount — so
|
|
67
|
+
-- it is asked for rather than defaulted.
|
|
68
|
+
-- ---------------------------------------------------------------------------
|
|
69
|
+
|
|
70
|
+
create type tax_credit_treatment as enum ('carry_forward', 'refund');
|
|
71
|
+
|
|
72
|
+
comment on type tax_credit_treatment is
|
|
73
|
+
'What a company does with a period that ends in a credit: carry it to the next declaration, or claim it back. There is no default: the choice is the company''s, and both are ordinary.';
|
|
74
|
+
|
|
75
|
+
alter table tax_filings
|
|
76
|
+
add column if not exists settlement_entry_id uuid references entries(id) on delete restrict,
|
|
77
|
+
add column if not exists credit_treatment tax_credit_treatment;
|
|
78
|
+
|
|
79
|
+
comment on column tax_filings.settlement_entry_id is
|
|
80
|
+
'The entry that cleared the tax accounts of this period into the debt towards the administration. One per declaration, enforced by a unique index: replaying the settlement is refused rather than doubling the debt.';
|
|
81
|
+
comment on column tax_filings.credit_treatment is
|
|
82
|
+
'Set when the period ended in a credit, and only then: carried forward to the next declaration, or claimed back.';
|
|
83
|
+
|
|
84
|
+
create unique index tax_filings_settlement_entry_idx
|
|
85
|
+
on tax_filings (settlement_entry_id)
|
|
86
|
+
where settlement_entry_id is not null;
|
|
87
|
+
|
|
88
|
+
-- ---------------------------------------------------------------------------
|
|
89
|
+
-- open_items, with one more place a reference can come from
|
|
90
|
+
--
|
|
91
|
+
-- Matching by reference reads the document behind the line. The debt of a
|
|
92
|
+
-- declaration has no document — it is an entry, keyed by this file — and
|
|
93
|
+
-- without this it would only ever be found by its amount. So the entry's own
|
|
94
|
+
-- reference answers where there is no document: it is the field an operator
|
|
95
|
+
-- fills with the structured communication of a tax payment, and the one a
|
|
96
|
+
-- manual entry carries in every other case too.
|
|
97
|
+
-- ---------------------------------------------------------------------------
|
|
98
|
+
|
|
99
|
+
create or replace function open_items(
|
|
100
|
+
p_company_id uuid,
|
|
101
|
+
p_contact_id uuid default null,
|
|
102
|
+
p_as_of date default null
|
|
103
|
+
)
|
|
104
|
+
returns table (
|
|
105
|
+
line_id uuid,
|
|
106
|
+
contact_id uuid,
|
|
107
|
+
account_id uuid,
|
|
108
|
+
side text,
|
|
109
|
+
amount_open numeric,
|
|
110
|
+
entry_date date,
|
|
111
|
+
date_maturity date,
|
|
112
|
+
document_id uuid,
|
|
113
|
+
document_number text,
|
|
114
|
+
reference text
|
|
115
|
+
)
|
|
116
|
+
language sql
|
|
117
|
+
stable
|
|
118
|
+
security invoker
|
|
119
|
+
as $$
|
|
120
|
+
select l.id,
|
|
121
|
+
l.contact_id,
|
|
122
|
+
l.account_id,
|
|
123
|
+
case when l.debit > 0 then 'debit' else 'credit' end,
|
|
124
|
+
abs(l.balance) - l.matched_amount,
|
|
125
|
+
e.entry_date,
|
|
126
|
+
l.date_maturity,
|
|
127
|
+
d.id,
|
|
128
|
+
d.number,
|
|
129
|
+
coalesce(d.payment_reference, d.number, e.reference)
|
|
130
|
+
from entry_lines l
|
|
131
|
+
join entries e on e.id = l.entry_id
|
|
132
|
+
join accounts a on a.id = l.account_id
|
|
133
|
+
left join documents d on d.entry_id = e.id
|
|
134
|
+
where l.company_id = p_company_id
|
|
135
|
+
and e.state = 'posted'
|
|
136
|
+
and a.reconcilable
|
|
137
|
+
and abs(l.balance) - l.matched_amount > 0
|
|
138
|
+
and (p_contact_id is null or l.contact_id = p_contact_id)
|
|
139
|
+
and (p_as_of is null or e.entry_date <= p_as_of);
|
|
140
|
+
$$;
|
|
141
|
+
|
|
142
|
+
comment on function open_items(uuid, uuid, date) is
|
|
143
|
+
'Third-party lines with something still open, with the document behind each and the references it carries. Where there is no document — the debt of a declaration, an entry keyed by hand — the entry''s own reference answers. Read by the matching, and by anybody asking what is still owed.';
|
|
144
|
+
|
|
145
|
+
revoke execute on function open_items(uuid, uuid, date) from public, anon;
|
|
146
|
+
grant execute on function open_items(uuid, uuid, date) to authenticated, service_role;
|
|
147
|
+
|
|
148
|
+
-- ---------------------------------------------------------------------------
|
|
149
|
+
-- filing_tax_movements
|
|
150
|
+
--
|
|
151
|
+
-- What a declared period actually moved, account by account, in the window and
|
|
152
|
+
-- under the date rule `vat_return()` reads. Its own function because settling
|
|
153
|
+
-- is not the only reason to ask: before an entry exists, this is what the
|
|
154
|
+
-- settlement will be, and after one exists it is what the settlement was
|
|
155
|
+
-- computed from.
|
|
156
|
+
-- ---------------------------------------------------------------------------
|
|
157
|
+
|
|
158
|
+
create or replace function filing_tax_movements(p_filing_id uuid)
|
|
159
|
+
returns table (account_id uuid, balance numeric)
|
|
160
|
+
language sql
|
|
161
|
+
stable
|
|
162
|
+
security invoker
|
|
163
|
+
as $$
|
|
164
|
+
select l.account_id,
|
|
165
|
+
round_amount(sum(l.balance), rounding_of(f.company_id))
|
|
166
|
+
from tax_filings f
|
|
167
|
+
join entry_lines l on l.company_id = f.company_id
|
|
168
|
+
join entries e on e.id = l.entry_id
|
|
169
|
+
where f.id = p_filing_id
|
|
170
|
+
and e.state = 'posted'
|
|
171
|
+
and l.tax_line
|
|
172
|
+
and coalesce(l.tax_point_date, e.entry_date) between f.period_start and f.period_end
|
|
173
|
+
group by l.account_id, f.company_id
|
|
174
|
+
having round_amount(sum(l.balance), rounding_of(f.company_id)) <> 0;
|
|
175
|
+
$$;
|
|
176
|
+
|
|
177
|
+
comment on function filing_tax_movements(uuid) is
|
|
178
|
+
'The tax accounts a declared period moved and by how much, on the same window and the same tax-point rule the return read. What settle_filing() clears, and what anybody can read before it does.';
|
|
179
|
+
|
|
180
|
+
revoke execute on function filing_tax_movements(uuid) from public, anon;
|
|
181
|
+
grant execute on function filing_tax_movements(uuid) to authenticated, service_role;
|
|
182
|
+
|
|
183
|
+
-- ---------------------------------------------------------------------------
|
|
184
|
+
-- settle_filing
|
|
185
|
+
--
|
|
186
|
+
-- One entry, at the end of the period it settles, in the miscellaneous
|
|
187
|
+
-- journal: every tax account the period moved goes back to zero, and the net
|
|
188
|
+
-- lands on the account the pack names. It runs on an accepted declaration —
|
|
189
|
+
-- the administration has agreed to the figures, which is the moment the debt
|
|
190
|
+
-- becomes certain — and it refuses everything else by naming the state it
|
|
191
|
+
-- found.
|
|
192
|
+
-- ---------------------------------------------------------------------------
|
|
193
|
+
|
|
194
|
+
create or replace function settle_filing(
|
|
195
|
+
p_filing_id uuid,
|
|
196
|
+
p_credit tax_credit_treatment default null,
|
|
197
|
+
p_reference text default null,
|
|
198
|
+
p_contact_id uuid default null,
|
|
199
|
+
p_date date default null
|
|
200
|
+
)
|
|
201
|
+
returns entries
|
|
202
|
+
language plpgsql
|
|
203
|
+
volatile
|
|
204
|
+
security invoker
|
|
205
|
+
as $$
|
|
206
|
+
declare
|
|
207
|
+
v_filing tax_filings;
|
|
208
|
+
v_country char(2);
|
|
209
|
+
v_payable text;
|
|
210
|
+
v_receivable text;
|
|
211
|
+
v_account uuid;
|
|
212
|
+
v_contact_account uuid;
|
|
213
|
+
v_journal uuid;
|
|
214
|
+
v_round money_rounding;
|
|
215
|
+
v_date date;
|
|
216
|
+
v_label text;
|
|
217
|
+
v_reference text;
|
|
218
|
+
v_net numeric := 0;
|
|
219
|
+
v_seq integer := 0;
|
|
220
|
+
v_entry entries;
|
|
221
|
+
r record;
|
|
222
|
+
begin
|
|
223
|
+
select * into v_filing from tax_filings f where f.id = p_filing_id for update;
|
|
224
|
+
if not found then
|
|
225
|
+
raise exception 'not_found: filing %', p_filing_id using errcode = 'no_data_found';
|
|
226
|
+
end if;
|
|
227
|
+
if v_filing.state <> 'accepted' then
|
|
228
|
+
raise exception 'filing_not_accepted: settling follows acceptance, and this one is %', v_filing.state;
|
|
229
|
+
end if;
|
|
230
|
+
if v_filing.settlement_entry_id is not null then
|
|
231
|
+
raise exception 'filing_already_settled: % was settled by entry %',
|
|
232
|
+
p_filing_id, v_filing.settlement_entry_id;
|
|
233
|
+
end if;
|
|
234
|
+
|
|
235
|
+
select c.fiscal_country, c.miscellaneous_journal_id
|
|
236
|
+
into v_country, v_journal
|
|
237
|
+
from companies c where c.id = v_filing.company_id;
|
|
238
|
+
|
|
239
|
+
if v_journal is null then
|
|
240
|
+
raise exception 'no_miscellaneous_journal: this company has no journal for an entry that belongs to no document. Set defaults.journal_roles.miscellaneous in the pack, which fills country_defaults.misc_journal_code.';
|
|
241
|
+
end if;
|
|
242
|
+
|
|
243
|
+
select d.tax_payable_code, d.tax_receivable_code
|
|
244
|
+
into v_payable, v_receivable
|
|
245
|
+
from country_defaults d where d.country = v_country;
|
|
246
|
+
|
|
247
|
+
if v_payable is null then
|
|
248
|
+
raise exception 'no_tax_payable_account: the pack of this company names no account for what a declaration owes. Set defaults.roles.tax_payable in the pack, which fills country_defaults.tax_payable_code.';
|
|
249
|
+
end if;
|
|
250
|
+
|
|
251
|
+
v_round := rounding_of(v_filing.company_id);
|
|
252
|
+
v_date := coalesce(p_date, v_filing.period_end);
|
|
253
|
+
v_label := v_filing.report_code || ' ' || v_filing.period_start || ' — ' || v_filing.period_end;
|
|
254
|
+
v_reference := coalesce(p_reference, v_filing.reference);
|
|
255
|
+
|
|
256
|
+
if not exists (select 1 from filing_tax_movements(p_filing_id)) then
|
|
257
|
+
raise exception 'nothing_to_settle: % moved no tax account between % and %',
|
|
258
|
+
v_filing.report_code, v_filing.period_start, v_filing.period_end;
|
|
259
|
+
end if;
|
|
260
|
+
|
|
261
|
+
select sum(m.balance) into v_net from filing_tax_movements(p_filing_id) m;
|
|
262
|
+
|
|
263
|
+
-- A positive net is a debit balance left on the tax accounts, which is a
|
|
264
|
+
-- credit in the company's favour; a negative one is what it owes.
|
|
265
|
+
if v_net > 0 then
|
|
266
|
+
if p_credit is null then
|
|
267
|
+
raise exception 'no_credit_treatment: % to % ends in a credit of %, and what happens to it — carried to the next declaration or claimed back — is this company''s decision',
|
|
268
|
+
v_filing.period_start, v_filing.period_end, v_net;
|
|
269
|
+
end if;
|
|
270
|
+
v_account := account_id_by_code(v_filing.company_id, coalesce(v_receivable, v_payable));
|
|
271
|
+
if v_account is null then
|
|
272
|
+
raise exception 'unknown_tax_account: the pack names % for a credit and this chart has no such account',
|
|
273
|
+
coalesce(v_receivable, v_payable);
|
|
274
|
+
end if;
|
|
275
|
+
else
|
|
276
|
+
if p_credit is not null then
|
|
277
|
+
raise exception 'not_a_credit: this declaration owes money, and a credit treatment does not apply to it';
|
|
278
|
+
end if;
|
|
279
|
+
v_account := account_id_by_code(v_filing.company_id, v_payable);
|
|
280
|
+
if v_account is null then
|
|
281
|
+
raise exception 'unknown_tax_account: the pack names % for what is owed and this chart has no such account',
|
|
282
|
+
v_payable;
|
|
283
|
+
end if;
|
|
284
|
+
end if;
|
|
285
|
+
|
|
286
|
+
-- The debt is matched against a payment, and matching reads reconcilable
|
|
287
|
+
-- accounts. A pack that names an account that is not one has named the
|
|
288
|
+
-- wrong account, and the settlement would be posted where no payment could
|
|
289
|
+
-- ever find it.
|
|
290
|
+
if not exists (select 1 from accounts a where a.id = v_account and a.reconcilable) then
|
|
291
|
+
raise exception 'tax_account_not_reconcilable: % carries a debt that a payment settles, so the chart has to keep it reconcilable',
|
|
292
|
+
coalesce(case when v_net > 0 then v_receivable end, v_payable);
|
|
293
|
+
end if;
|
|
294
|
+
|
|
295
|
+
-- Naming the administration is what lets the payment settle by itself, and
|
|
296
|
+
-- it only works if the ledger books that payment where the debt sits. A
|
|
297
|
+
-- contact whose third-party account is the default supplier one would send
|
|
298
|
+
-- the payment to the payables and leave the debt open for ever — a silence,
|
|
299
|
+
-- and this file's whole job is to end one. So it is checked here, where the
|
|
300
|
+
-- sentence can still name what to change.
|
|
301
|
+
if p_contact_id is not null then
|
|
302
|
+
v_contact_account := resolve_counterpart_account(v_filing.company_id, p_contact_id, v_net > 0);
|
|
303
|
+
if v_contact_account <> v_account then
|
|
304
|
+
raise exception 'contact_account_mismatch: the payment of this declaration would be booked on the third-party account of that contact, and the debt sits on %. Set that contact''s account to the one the pack names, or leave the contact out.',
|
|
305
|
+
coalesce(case when v_net > 0 then v_receivable end, v_payable);
|
|
306
|
+
end if;
|
|
307
|
+
end if;
|
|
308
|
+
|
|
309
|
+
-- The account the net lands on is never one of the accounts being cleared:
|
|
310
|
+
-- a chart that used the same one for both would net the period against
|
|
311
|
+
-- itself and post an entry that says nothing.
|
|
312
|
+
if exists (select 1 from filing_tax_movements(p_filing_id) m where m.account_id = v_account) then
|
|
313
|
+
raise exception 'tax_account_is_a_posting_account: % is an account the taxes of this period post to, so clearing them into it would leave nothing',
|
|
314
|
+
coalesce(case when v_net > 0 then v_receivable end, v_payable);
|
|
315
|
+
end if;
|
|
316
|
+
|
|
317
|
+
insert into entries (company_id, journal_id, fiscal_year_id, entry_date,
|
|
318
|
+
reference, description, state)
|
|
319
|
+
values (v_filing.company_id, v_journal,
|
|
320
|
+
fiscal_year_at(v_filing.company_id, v_date), v_date,
|
|
321
|
+
v_reference, v_label, 'draft')
|
|
322
|
+
returning * into v_entry;
|
|
323
|
+
|
|
324
|
+
-- Each tax account, on the side that empties it.
|
|
325
|
+
for r in select * from filing_tax_movements(p_filing_id) order by account_id loop
|
|
326
|
+
v_seq := v_seq + 10;
|
|
327
|
+
insert into entry_lines (entry_id, company_id, account_id, sequence, name, debit, credit)
|
|
328
|
+
values (v_entry.id, v_filing.company_id, r.account_id, v_seq, v_label,
|
|
329
|
+
case when r.balance < 0 then -r.balance else 0 end,
|
|
330
|
+
case when r.balance > 0 then r.balance else 0 end);
|
|
331
|
+
end loop;
|
|
332
|
+
|
|
333
|
+
-- And the net, on the account that carries it. A period whose tax accounts
|
|
334
|
+
-- cancel each other out leaves nothing to carry, and the entry is the
|
|
335
|
+
-- clearing alone: balanced, and worth having, because the accounts are back
|
|
336
|
+
-- to zero either way.
|
|
337
|
+
if v_net <> 0 then
|
|
338
|
+
insert into entry_lines (entry_id, company_id, account_id, sequence, name,
|
|
339
|
+
debit, credit, contact_id, date_maturity)
|
|
340
|
+
values (v_entry.id, v_filing.company_id, v_account, v_seq + 10, v_label,
|
|
341
|
+
case when v_net > 0 then v_net else 0 end,
|
|
342
|
+
case when v_net < 0 then -v_net else 0 end,
|
|
343
|
+
p_contact_id, v_filing.due_date);
|
|
344
|
+
end if;
|
|
345
|
+
|
|
346
|
+
v_entry := post_entry(v_entry.id);
|
|
347
|
+
|
|
348
|
+
update tax_filings
|
|
349
|
+
set settlement_entry_id = v_entry.id,
|
|
350
|
+
credit_treatment = p_credit
|
|
351
|
+
where id = p_filing_id;
|
|
352
|
+
|
|
353
|
+
return v_entry;
|
|
354
|
+
end;
|
|
355
|
+
$$;
|
|
356
|
+
|
|
357
|
+
comment on function settle_filing(uuid, tax_credit_treatment, text, uuid, date) is
|
|
358
|
+
'Clears the tax accounts a declared period moved and carries the net to the account the pack names for what is owed to the administration — or, where the period ends in a credit, to the one it names for a credit, once the company has said whether it is carried forward or claimed back. One entry per declaration, through post_entry(), with the reference the payment will be matched by. Naming the administration as the contact is what makes the debt settle by itself: matching books a payment, and a payment is made to somebody.';
|
|
359
|
+
|
|
360
|
+
revoke execute on function settle_filing(uuid, tax_credit_treatment, text, uuid, date) from public, anon;
|
|
361
|
+
grant execute on function settle_filing(uuid, tax_credit_treatment, text, uuid, date) to authenticated, service_role;
|
|
362
|
+
|
|
363
|
+
-- ---------------------------------------------------------------------------
|
|
364
|
+
-- auto_settle, which no longer dies on one line it cannot book
|
|
365
|
+
--
|
|
366
|
+
-- Found by the test below, and worth more than the feature it was found by.
|
|
367
|
+
-- `settle_from_statement()` refuses an open item that names nobody — a payment
|
|
368
|
+
-- is made to or by somebody — and the debt of a declaration names nobody
|
|
369
|
+
-- unless the caller passes the administration as its contact. That refusal is
|
|
370
|
+
-- right. What was wrong is what it did to the pass: the exception propagated
|
|
371
|
+
-- out of `auto_settle()` and **the whole run stopped**, with the lines it had
|
|
372
|
+
-- already settled rolled back and no report of anything.
|
|
373
|
+
--
|
|
374
|
+
-- A pass over a month of statements is exactly where one line must not be able
|
|
375
|
+
-- to silence the other forty. So the refusal is caught, reported against the
|
|
376
|
+
-- line it belongs to, in the words the database used, and the walk goes on:
|
|
377
|
+
-- the rule that a report has a row for every line of the window is the rule
|
|
378
|
+
-- this one serves.
|
|
379
|
+
-- ---------------------------------------------------------------------------
|
|
380
|
+
|
|
381
|
+
create or replace function auto_settle(
|
|
382
|
+
p_company_id uuid,
|
|
383
|
+
p_from date,
|
|
384
|
+
p_to date,
|
|
385
|
+
p_apply boolean default false
|
|
386
|
+
)
|
|
387
|
+
returns table (
|
|
388
|
+
transaction_id uuid,
|
|
389
|
+
action text,
|
|
390
|
+
method text,
|
|
391
|
+
line_ids uuid[],
|
|
392
|
+
because text
|
|
393
|
+
)
|
|
394
|
+
language plpgsql
|
|
395
|
+
volatile
|
|
396
|
+
security invoker
|
|
397
|
+
as $$
|
|
398
|
+
declare
|
|
399
|
+
v_policy matching_policy;
|
|
400
|
+
v_round money_rounding;
|
|
401
|
+
v_tolerance numeric;
|
|
402
|
+
t record;
|
|
403
|
+
best record;
|
|
404
|
+
v_count integer;
|
|
405
|
+
v_open numeric;
|
|
406
|
+
v_refusal text;
|
|
407
|
+
begin
|
|
408
|
+
v_policy := matching_policy_of(p_company_id);
|
|
409
|
+
|
|
410
|
+
for t in
|
|
411
|
+
select * from bank_transactions b
|
|
412
|
+
where b.company_id = p_company_id
|
|
413
|
+
and b.state = 'pending'
|
|
414
|
+
and b.entry_id is null
|
|
415
|
+
and b.transaction_date between p_from and p_to
|
|
416
|
+
order by b.transaction_date, b.sequence
|
|
417
|
+
loop
|
|
418
|
+
v_round := rounding_of(p_company_id, t.currency_code);
|
|
419
|
+
v_tolerance := v_policy.amount_tolerance_units * power(10::numeric, -v_round.decimals);
|
|
420
|
+
|
|
421
|
+
select count(*) into v_count
|
|
422
|
+
from suggest_matches(t.id) s
|
|
423
|
+
where s.kind = 'internal_transfer';
|
|
424
|
+
if v_count > 0 then
|
|
425
|
+
transaction_id := t.id; action := 'left'; method := 'internal_transfer';
|
|
426
|
+
line_ids := '{}'::uuid[];
|
|
427
|
+
because := 'a transfer between two accounts of this company settles nothing, and its other side is its own statement line';
|
|
428
|
+
return next; continue;
|
|
429
|
+
end if;
|
|
430
|
+
|
|
431
|
+
-- The one candidate whose evidence identified exactly one thing.
|
|
432
|
+
select * into best
|
|
433
|
+
from suggest_matches(t.id) s
|
|
434
|
+
where s.alternatives = 1 and s.method in ('reference', 'exact_amount')
|
|
435
|
+
order by s.score desc
|
|
436
|
+
limit 1;
|
|
437
|
+
|
|
438
|
+
if not found then
|
|
439
|
+
select count(*) into v_count from suggest_matches(t.id);
|
|
440
|
+
transaction_id := t.id; action := 'proposed'; method := 'none';
|
|
441
|
+
line_ids := '{}'::uuid[];
|
|
442
|
+
because := case when v_count = 0
|
|
443
|
+
then 'nothing open matches this line'
|
|
444
|
+
else format('%s candidates, none of them an identification', v_count) end;
|
|
445
|
+
return next; continue;
|
|
446
|
+
end if;
|
|
447
|
+
|
|
448
|
+
-- Partial settlement is four different accounting treatments wearing the
|
|
449
|
+
-- same face. The machine proposes; a person decides which one it is.
|
|
450
|
+
select sum(i.amount_open) into v_open
|
|
451
|
+
from open_items(p_company_id) i where i.line_id = any(best.line_ids);
|
|
452
|
+
if abs(t.amount) + v_tolerance < v_open then
|
|
453
|
+
transaction_id := t.id; action := 'proposed'; method := best.method;
|
|
454
|
+
line_ids := best.line_ids;
|
|
455
|
+
because := format('%s of %s — a deposit, a discount, a short payment or an error, and the ledger cannot tell which',
|
|
456
|
+
abs(t.amount), v_open);
|
|
457
|
+
return next; continue;
|
|
458
|
+
end if;
|
|
459
|
+
|
|
460
|
+
if p_apply then
|
|
461
|
+
v_refusal := null;
|
|
462
|
+
begin
|
|
463
|
+
perform settle_from_statement(t.id, best.line_ids);
|
|
464
|
+
exception when others then
|
|
465
|
+
v_refusal := sqlerrm;
|
|
466
|
+
end;
|
|
467
|
+
if v_refusal is not null then
|
|
468
|
+
transaction_id := t.id; action := 'refused'; method := best.method;
|
|
469
|
+
line_ids := best.line_ids; because := v_refusal;
|
|
470
|
+
return next; continue;
|
|
471
|
+
end if;
|
|
472
|
+
transaction_id := t.id; action := 'settled';
|
|
473
|
+
else
|
|
474
|
+
transaction_id := t.id; action := 'would_settle';
|
|
475
|
+
end if;
|
|
476
|
+
method := best.method; line_ids := best.line_ids; because := best.because;
|
|
477
|
+
return next;
|
|
478
|
+
end loop;
|
|
479
|
+
end;
|
|
480
|
+
$$;
|
|
481
|
+
|
|
482
|
+
comment on function auto_settle(uuid, date, date, boolean) is
|
|
483
|
+
'Walks the pending statement lines of a period and settles the ones a single piece of evidence identifies — a reference, or an exact amount with one candidate. Everything else comes back with the reason it was left: a combination, a partial payment, an internal transfer, nothing open that fits, or a refusal the database made, quoted. With p_apply false it changes nothing and says what it would do.';
|
|
484
|
+
|
|
485
|
+
revoke execute on function auto_settle(uuid, date, date, boolean) from public, anon;
|
|
486
|
+
grant execute on function auto_settle(uuid, date, date, boolean) to authenticated, service_role;
|