ekwo-os 0.19.0 → 0.21.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 (96) hide show
  1. package/README.md +14 -2
  2. package/dist/assets/expected-objects.json +166 -17
  3. package/dist/assets/migrations/20261023160000_a_declaration_already_paid_says_so.sql +45 -0
  4. package/dist/assets/migrations/20261023160100_a_deposit_is_written_by_the_core.sql +259 -0
  5. package/dist/assets/migrations/20261023160200_a_payee_is_named_in_the_company_language.sql +130 -0
  6. package/dist/assets/migrations/20261023160300_schema_version_0_20_0.sql +38 -0
  7. package/dist/assets/migrations/20261023160600_a_draft_changes_its_lines_in_one_statement.sql +126 -0
  8. package/dist/assets/migrations/20261023174709_an_agent_posts_in_the_mode_its_company_chose.sql +501 -0
  9. package/dist/assets/migrations/20261025072151_a_schema_for_the_socle.sql +52 -0
  10. package/dist/assets/migrations/20261026030000_schema_version_0_21_0.sql +39 -0
  11. package/dist/assets/modules/fixed-assets/supabase/migrations/20261023160500_assets_months_run_while_the_asset_is_in_service.sql +227 -0
  12. package/dist/assets/seed/00_currencies.sql +15 -0
  13. package/dist/assets/seed/00_territories.sql +48 -0
  14. package/dist/assets/seed/10_pack_be.sql +9 -2
  15. package/dist/assets/seed/124_pack_kz.sql +7 -2
  16. package/dist/assets/seed/18_pack_de.sql +9 -2
  17. package/dist/assets/seed/222_pack_fj.sql +626 -0
  18. package/dist/assets/seed/223_pack_ki.sql +629 -0
  19. package/dist/assets/seed/225_pack_ws.sql +620 -0
  20. package/dist/assets/seed/411_pack_mc.sql +905 -0
  21. package/dist/assets/seed/412_pack_pg.sql +619 -0
  22. package/dist/assets/seed/49_pack_ng.sql +9 -2
  23. package/dist/assets/seed/58_pack_ca.sql +5 -2
  24. package/dist/assets/seed/62_pack_ch.sql +5 -2
  25. package/dist/assets/seed/63_pack_at.sql +9 -2
  26. package/dist/assets/seed/modules/corporate_tax/10_pack_be.sql +1 -1
  27. package/dist/assets/seed/modules/corporate_tax/18_pack_de.sql +1 -1
  28. package/dist/assets/seed/modules/corporate_tax/49_pack_ng.sql +1 -1
  29. package/dist/assets/seed/modules/fixed_assets/10_pack_be.sql +1 -1
  30. package/dist/assets/seed/modules/fixed_assets/18_pack_de.sql +1 -1
  31. package/dist/assets/seed/modules/fixed_assets/49_pack_ng.sql +1 -1
  32. package/dist/bootstrap.d.ts.map +1 -1
  33. package/dist/bootstrap.js +3 -2
  34. package/dist/bootstrap.js.map +1 -1
  35. package/dist/cli.d.ts +3 -2
  36. package/dist/cli.d.ts.map +1 -1
  37. package/dist/cli.js +35 -2
  38. package/dist/cli.js.map +1 -1
  39. package/dist/commands/company.d.ts.map +1 -1
  40. package/dist/commands/company.js +42 -1
  41. package/dist/commands/company.js.map +1 -1
  42. package/dist/commands/document.d.ts +2 -2
  43. package/dist/commands/document.d.ts.map +1 -1
  44. package/dist/commands/document.js +27 -3
  45. package/dist/commands/document.js.map +1 -1
  46. package/dist/commands/key.d.ts +13 -0
  47. package/dist/commands/key.d.ts.map +1 -0
  48. package/dist/commands/key.js +80 -0
  49. package/dist/commands/key.js.map +1 -0
  50. package/dist/commands/mcp.d.ts +27 -0
  51. package/dist/commands/mcp.d.ts.map +1 -0
  52. package/dist/commands/mcp.js +70 -0
  53. package/dist/commands/mcp.js.map +1 -0
  54. package/dist/commands/migrate.d.ts.map +1 -1
  55. package/dist/commands/migrate.js +11 -0
  56. package/dist/commands/migrate.js.map +1 -1
  57. package/dist/commands/module.d.ts.map +1 -1
  58. package/dist/commands/module.js +2 -1
  59. package/dist/commands/module.js.map +1 -1
  60. package/dist/context.d.ts.map +1 -1
  61. package/dist/context.js +10 -0
  62. package/dist/context.js.map +1 -1
  63. package/dist/doctor.d.ts +9 -0
  64. package/dist/doctor.d.ts.map +1 -1
  65. package/dist/doctor.js +92 -19
  66. package/dist/doctor.js.map +1 -1
  67. package/dist/inventory.d.ts.map +1 -1
  68. package/dist/inventory.js +13 -5
  69. package/dist/inventory.js.map +1 -1
  70. package/dist/output.js +1 -1
  71. package/dist/output.js.map +1 -1
  72. package/dist/pack/compile.js +7 -0
  73. package/dist/pack/compile.js.map +1 -1
  74. package/dist/pack/read.d.ts +9 -0
  75. package/dist/pack/read.d.ts.map +1 -1
  76. package/dist/pack/read.js +22 -2
  77. package/dist/pack/read.js.map +1 -1
  78. package/dist/rest.d.ts +11 -4
  79. package/dist/rest.d.ts.map +1 -1
  80. package/dist/rest.js +34 -4
  81. package/dist/rest.js.map +1 -1
  82. package/dist/schema.d.ts +1 -1
  83. package/dist/schema.js +1 -1
  84. package/dist/seeds.d.ts +5 -0
  85. package/dist/seeds.d.ts.map +1 -1
  86. package/dist/seeds.js +7 -0
  87. package/dist/seeds.js.map +1 -1
  88. package/dist/socle.d.ts +35 -0
  89. package/dist/socle.d.ts.map +1 -0
  90. package/dist/socle.js +48 -0
  91. package/dist/socle.js.map +1 -0
  92. package/dist/status.d.ts.map +1 -1
  93. package/dist/status.js +5 -3
  94. package/dist/status.js.map +1 -1
  95. package/package.json +3 -3
  96. package/schema/output.1.json +20 -0
package/README.md CHANGED
@@ -171,7 +171,11 @@ project reports what was already there and creates nothing a second time.
171
171
  | `ekwo contact duplicates` | The pairs of contacts that are probably one party, strongest first, through `suggest_duplicate_contacts()`: which one to keep, a score, and the evidence — the same VAT or registration number, the same bank account, the words of the name weighed by how few contacts carry them. Writes nothing. |
172
172
  | `ekwo contact merge <keep> <absorb>` | One party created twice — two spellings, two imports — joined through `merge_contacts()`: everything that names the second, posted lines and issued documents included, names the first; the first takes the fields it left empty; the second is retired, never deleted, and named by nothing again. By name or id. |
173
173
  | `ekwo doc new` / `doc line add` | A draft document — any kind, with `--type` — and one more line on it. A draft books nothing. `ekwo invoice` is the old name of `ekwo doc`, kept as an alias. |
174
- | `ekwo post <document>` | Books it, through `post_document()`. `--dry-run` shows the entry the database would write and writes nothing. |
174
+ | `ekwo doc approve <document>` | Approves a draft, as it stands, for an agent to post where agents post in `review`, through `approve_document()`. Signed in as yourself, with `documents.post`; refused to a machine key. A change to the draft afterwards needs another approval. |
175
+ | `ekwo company agent-posting [review\|autopilot\|review_only]` | The setting `agent_posting`: how an agent — a machine key, the MCP server — books a document of the company in use. `review`, the default, once a person approved it, unless the agent's session was started with `--autopilot`; `autopilot`, directly, within its rights, each posting on the audit trail; `review_only`, review with autopilot refused to every session. Without a value, says which. Signed in as yourself, with `company.write`; an agent may only make it stricter. |
176
+ | `ekwo key list [--all]` / `ekwo key create <name> --capability <code>… [--expires <timestamp>] [--autopilot]` | The machine keys of the company in use, with what each may do and how it posts; and one more, through `create_api_key()`, its secret shown once. A key posts as the company's `agent_posting` says; `--autopilot` issues one that posts without approvals — with `company.write`, never in a `review_only` company — and the mode is fixed for good: a key wanted in another mode is issued again. Needs `members.manage`. |
177
+ | `ekwo mcp [--autopilot\|--review]` | The MCP server, over stdio, for an agent: the same server as `ekwo-mcp` of [`@ekwo-ai/mcp`](../mcp/README.md), with its flags and its environment (`ekwo mcp --help`). The `@ekwo-ai/mcp` installed beside this CLI, or the one of its release through `npx` — this CLI keeps its one outside dependency. In `.mcp.json`: `"command": "ekwo", "args": ["mcp"]`. |
178
+ | `ekwo post <document>` | Books it, through `post_document()`. `--dry-run` shows the entry the database would write and writes nothing. Signed in as yourself, you post in any mode; with a machine key, the company's `agent_posting` applies, or the key's own autopilot. |
175
179
  | `ekwo cancel <document>` | Undoes a posted invoice, and says how. Back to draft, through `unpost_document()`, where its country allows it and nothing about it has left; otherwise through `cancel_document()`: the credit note that names it, posted and matched against it, and the invoice cancelled. `--date` books the credit note on another day than the invoice's, which is how a locked period is stepped over; `--credit` asks for the note where a draft was possible. |
176
180
  | `ekwo reverse <entry>` | Undoes a posted entry keyed by hand, through `reverse_entry()`: its mirror, posted and matched against it. By id or by number; `--date` as for `cancel`. |
177
181
  | `ekwo line contacts suggest [--line <line>]…` / `ekwo line contact set <line> <contact>` | The open receivable and payable lines that name nobody — open items of books imported line by line — with the contacts each could be, best first: a learned motif, the number of a document of the company quoted in the label, the description or the reference of the entry, the words of a contact's name, and how many contacts the same evidence reached. `set` names one, once, through `set_line_contact()`, and the label is learned for the next time. A contact by name or id. |
@@ -386,6 +390,14 @@ extra tables are reported as information. It also checks row level security on
386
390
  every table, pending migrations, memberships of deleted users, companies
387
391
  without a bank account, and posted entries that do not balance.
388
392
 
393
+ Two checks say where the socle lives, ahead of its move to the schema `ekwo`
394
+ in 0.22.0 ([decision 0090](../../docs/decisions/0090-the-socle-has-its-own-schema.md)):
395
+ `socle_schema` (`ekwo` or `public`, found by the marker `ekwo_schema_version()`)
396
+ and `ekwo_exposed` (whether the Data API serves `ekwo`, read from
397
+ `pgrst.db_schemas` where the database carries it; otherwise the line to set).
398
+ `ekwo migrate` prints the same line: Project Settings → Data API → Exposed
399
+ schemas, add `ekwo`.
400
+
389
401
  Exit code `0` when there is no problem, `1` otherwise — usable as a deployment
390
402
  gate.
391
403
 
@@ -529,7 +541,7 @@ exactly six fields:
529
541
  "organization": "My Organisation",
530
542
  "country": "<cc>",
531
543
  "edition": "community",
532
- "schema_version": "0.19.0",
544
+ "schema_version": "0.21.0",
533
545
  "contact_email": "you@example.com"
534
546
  }
535
547
  ```
@@ -1,6 +1,6 @@
1
1
  {
2
- "schemaVersion": "0.19.0",
3
- "migration": "20261023124700",
2
+ "schemaVersion": "0.21.0",
3
+ "migration": "20261026030000",
4
4
  "socle": {
5
5
  "schema": "public",
6
6
  "tables": [
@@ -346,6 +346,10 @@
346
346
  "name": "name",
347
347
  "type": "text"
348
348
  },
349
+ {
350
+ "name": "posting_mode",
351
+ "type": "text"
352
+ },
349
353
  {
350
354
  "name": "prefix",
351
355
  "type": "text"
@@ -889,6 +893,10 @@
889
893
  "name": "address_line2",
890
894
  "type": "text"
891
895
  },
896
+ {
897
+ "name": "agent_posting",
898
+ "type": "text"
899
+ },
892
900
  {
893
901
  "name": "archived_at",
894
902
  "type": "timestamp with time zone"
@@ -1845,6 +1853,10 @@
1845
1853
  "name": "tax_payee_name",
1846
1854
  "type": "text"
1847
1855
  },
1856
+ {
1857
+ "name": "tax_payee_name_i18n",
1858
+ "type": "jsonb"
1859
+ },
1848
1860
  {
1849
1861
  "name": "tax_payee_source_key",
1850
1862
  "type": "text"
@@ -4747,6 +4759,18 @@
4747
4759
  "name": "aged_balance",
4748
4760
  "arguments": "p_company_id uuid, p_at date, p_group text"
4749
4761
  },
4762
+ {
4763
+ "name": "agent_call",
4764
+ "arguments": ""
4765
+ },
4766
+ {
4767
+ "name": "agent_mark",
4768
+ "arguments": "p_name text"
4769
+ },
4770
+ {
4771
+ "name": "agent_posting_mode",
4772
+ "arguments": "p_company_id uuid"
4773
+ },
4750
4774
  {
4751
4775
  "name": "amount_text_format",
4752
4776
  "arguments": "p_rounding money_rounding"
@@ -4771,6 +4795,10 @@
4771
4795
  "name": "api_key_on_company",
4772
4796
  "arguments": "p_company_id uuid"
4773
4797
  },
4798
+ {
4799
+ "name": "approve_document",
4800
+ "arguments": "p_document_id uuid"
4801
+ },
4774
4802
  {
4775
4803
  "name": "archive_company",
4776
4804
  "arguments": "p_company_id uuid"
@@ -4943,6 +4971,10 @@
4943
4971
  "name": "commercial_entity",
4944
4972
  "arguments": "p_contact_id uuid"
4945
4973
  },
4974
+ {
4975
+ "name": "companies_agent_posting_by_a_person",
4976
+ "arguments": ""
4977
+ },
4946
4978
  {
4947
4979
  "name": "companies_creator_is_fixed",
4948
4980
  "arguments": ""
@@ -5077,12 +5109,16 @@
5077
5109
  },
5078
5110
  {
5079
5111
  "name": "create_api_key",
5080
- "arguments": "p_company_id uuid, p_name text, p_capabilities jsonb, p_expires_at timestamp with time zone"
5112
+ "arguments": "p_company_id uuid, p_name text, p_capabilities jsonb, p_expires_at timestamp with time zone, p_posting_mode text"
5081
5113
  },
5082
5114
  {
5083
5115
  "name": "create_company",
5084
5116
  "arguments": "p_name text, p_country character, p_currency_code character, p_language character, p_chart_code text, p_fiscal_year integer, p_fiscal_year_start date, p_owner_user_id uuid"
5085
5117
  },
5118
+ {
5119
+ "name": "create_document",
5120
+ "arguments": "p_document jsonb, p_lines jsonb"
5121
+ },
5086
5122
  {
5087
5123
  "name": "currency_of_bank_account",
5088
5124
  "arguments": ""
@@ -5199,6 +5235,10 @@
5199
5235
  "name": "document_territory",
5200
5236
  "arguments": "p_document_id uuid, p_party text"
5201
5237
  },
5238
+ {
5239
+ "name": "document_version",
5240
+ "arguments": "p_document_id uuid"
5241
+ },
5202
5242
  {
5203
5243
  "name": "documents_allocate_included_tax",
5204
5244
  "arguments": "p_document_id uuid"
@@ -5219,6 +5259,10 @@
5219
5259
  "name": "documents_match_credit_note_on_posting",
5220
5260
  "arguments": ""
5221
5261
  },
5262
+ {
5263
+ "name": "documents_posting_mode",
5264
+ "arguments": ""
5265
+ },
5222
5266
  {
5223
5267
  "name": "documents_refresh_amount_paid",
5224
5268
  "arguments": "p_document_id uuid"
@@ -5815,6 +5859,10 @@
5815
5859
  "name": "reopen_fiscal_year",
5816
5860
  "arguments": "p_fiscal_year_id uuid"
5817
5861
  },
5862
+ {
5863
+ "name": "replace_document_lines",
5864
+ "arguments": "p_document_id uuid, p_lines jsonb"
5865
+ },
5818
5866
  {
5819
5867
  "name": "resolve_counterpart_account",
5820
5868
  "arguments": "p_company_id uuid, p_contact_id uuid, p_is_sale boolean"
@@ -6095,6 +6143,10 @@
6095
6143
  "name": "version_at_least",
6096
6144
  "arguments": "p_version text, p_floor text"
6097
6145
  },
6146
+ {
6147
+ "name": "write_filing_outcome",
6148
+ "arguments": "p_filing_id uuid, p_state tax_filing_state, p_reference text, p_message text"
6149
+ },
6098
6150
  {
6099
6151
  "name": "year_result_account",
6100
6152
  "arguments": "p_company_id uuid, p_balance numeric"
@@ -6646,11 +6698,6 @@
6646
6698
  "name": "tax_filing_deposits_select",
6647
6699
  "command": "select"
6648
6700
  },
6649
- {
6650
- "table": "tax_filing_deposits",
6651
- "name": "tax_filing_deposits_write",
6652
- "command": "all"
6653
- },
6654
6701
  {
6655
6702
  "table": "tax_filings",
6656
6703
  "name": "tax_filings_select",
@@ -6841,6 +6888,10 @@
6841
6888
  "table": "bank_transactions",
6842
6889
  "name": "bank_transactions_set_updated_at"
6843
6890
  },
6891
+ {
6892
+ "table": "companies",
6893
+ "name": "companies_agent_posting_by_a_person"
6894
+ },
6844
6895
  {
6845
6896
  "table": "companies",
6846
6897
  "name": "companies_audit"
@@ -7105,6 +7156,10 @@
7105
7156
  "table": "documents",
7106
7157
  "name": "documents_match_credit_note_on_posting"
7107
7158
  },
7159
+ {
7160
+ "table": "documents",
7161
+ "name": "documents_posting_mode"
7162
+ },
7108
7163
  {
7109
7164
  "table": "documents",
7110
7165
  "name": "documents_refresh_payment_state"
@@ -8693,16 +8748,10 @@
8693
8748
  "name": "tax_filing_deposits",
8694
8749
  "anon": [],
8695
8750
  "authenticated": [
8696
- "delete",
8697
- "insert",
8698
- "select",
8699
- "update"
8751
+ "select"
8700
8752
  ],
8701
8753
  "service_role": [
8702
- "delete",
8703
- "insert",
8704
- "select",
8705
- "update"
8754
+ "select"
8706
8755
  ]
8707
8756
  },
8708
8757
  {
@@ -9059,6 +9108,39 @@
9059
9108
  "execute"
9060
9109
  ]
9061
9110
  },
9111
+ {
9112
+ "name": "agent_call",
9113
+ "arguments": "",
9114
+ "anon": [],
9115
+ "authenticated": [
9116
+ "execute"
9117
+ ],
9118
+ "service_role": [
9119
+ "execute"
9120
+ ]
9121
+ },
9122
+ {
9123
+ "name": "agent_mark",
9124
+ "arguments": "p_name text",
9125
+ "anon": [],
9126
+ "authenticated": [
9127
+ "execute"
9128
+ ],
9129
+ "service_role": [
9130
+ "execute"
9131
+ ]
9132
+ },
9133
+ {
9134
+ "name": "agent_posting_mode",
9135
+ "arguments": "p_company_id uuid",
9136
+ "anon": [],
9137
+ "authenticated": [
9138
+ "execute"
9139
+ ],
9140
+ "service_role": [
9141
+ "execute"
9142
+ ]
9143
+ },
9062
9144
  {
9063
9145
  "name": "amount_text_format",
9064
9146
  "arguments": "p_rounding money_rounding",
@@ -9127,6 +9209,17 @@
9127
9209
  "execute"
9128
9210
  ]
9129
9211
  },
9212
+ {
9213
+ "name": "approve_document",
9214
+ "arguments": "p_document_id uuid",
9215
+ "anon": [],
9216
+ "authenticated": [
9217
+ "execute"
9218
+ ],
9219
+ "service_role": [
9220
+ "execute"
9221
+ ]
9222
+ },
9130
9223
  {
9131
9224
  "name": "archive_company",
9132
9225
  "arguments": "p_company_id uuid",
@@ -9547,6 +9640,14 @@
9547
9640
  "execute"
9548
9641
  ]
9549
9642
  },
9643
+ {
9644
+ "name": "companies_agent_posting_by_a_person",
9645
+ "arguments": "",
9646
+ "trigger": true,
9647
+ "anon": [],
9648
+ "authenticated": [],
9649
+ "service_role": []
9650
+ },
9550
9651
  {
9551
9652
  "name": "companies_creator_is_fixed",
9552
9653
  "arguments": "",
@@ -9857,7 +9958,7 @@
9857
9958
  },
9858
9959
  {
9859
9960
  "name": "create_api_key",
9860
- "arguments": "p_company_id uuid, p_name text, p_capabilities jsonb, p_expires_at timestamp with time zone",
9961
+ "arguments": "p_company_id uuid, p_name text, p_capabilities jsonb, p_expires_at timestamp with time zone, p_posting_mode text",
9861
9962
  "anon": [],
9862
9963
  "authenticated": [
9863
9964
  "execute"
@@ -9877,6 +9978,17 @@
9877
9978
  "execute"
9878
9979
  ]
9879
9980
  },
9981
+ {
9982
+ "name": "create_document",
9983
+ "arguments": "p_document jsonb, p_lines jsonb",
9984
+ "anon": [],
9985
+ "authenticated": [
9986
+ "execute"
9987
+ ],
9988
+ "service_role": [
9989
+ "execute"
9990
+ ]
9991
+ },
9880
9992
  {
9881
9993
  "name": "currency_of_bank_account",
9882
9994
  "arguments": "",
@@ -10154,6 +10266,17 @@
10154
10266
  "execute"
10155
10267
  ]
10156
10268
  },
10269
+ {
10270
+ "name": "document_version",
10271
+ "arguments": "p_document_id uuid",
10272
+ "anon": [],
10273
+ "authenticated": [
10274
+ "execute"
10275
+ ],
10276
+ "service_role": [
10277
+ "execute"
10278
+ ]
10279
+ },
10157
10280
  {
10158
10281
  "name": "documents_allocate_included_tax",
10159
10282
  "arguments": "p_document_id uuid",
@@ -10197,6 +10320,14 @@
10197
10320
  "authenticated": [],
10198
10321
  "service_role": []
10199
10322
  },
10323
+ {
10324
+ "name": "documents_posting_mode",
10325
+ "arguments": "",
10326
+ "trigger": true,
10327
+ "anon": [],
10328
+ "authenticated": [],
10329
+ "service_role": []
10330
+ },
10200
10331
  {
10201
10332
  "name": "documents_refresh_amount_paid",
10202
10333
  "arguments": "p_document_id uuid",
@@ -11764,6 +11895,17 @@
11764
11895
  "execute"
11765
11896
  ]
11766
11897
  },
11898
+ {
11899
+ "name": "replace_document_lines",
11900
+ "arguments": "p_document_id uuid, p_lines jsonb",
11901
+ "anon": [],
11902
+ "authenticated": [
11903
+ "execute"
11904
+ ],
11905
+ "service_role": [
11906
+ "execute"
11907
+ ]
11908
+ },
11767
11909
  {
11768
11910
  "name": "resolve_counterpart_account",
11769
11911
  "arguments": "p_company_id uuid, p_contact_id uuid, p_is_sale boolean",
@@ -12506,6 +12648,13 @@
12506
12648
  "execute"
12507
12649
  ]
12508
12650
  },
12651
+ {
12652
+ "name": "write_filing_outcome",
12653
+ "arguments": "p_filing_id uuid, p_state tax_filing_state, p_reference text, p_message text",
12654
+ "anon": [],
12655
+ "authenticated": [],
12656
+ "service_role": []
12657
+ },
12509
12658
  {
12510
12659
  "name": "year_result_account",
12511
12660
  "arguments": "p_company_id uuid, p_balance numeric",
@@ -0,0 +1,45 @@
1
+ -- Ekwo OS — a declaration whose debt was matched before matching said so is paid.
2
+ --
3
+ -- `20261023124650` made a declaration paid when the line its settlement
4
+ -- carried the net on is matched in full — by the trigger
5
+ -- `tax_filings_paid_by_matching`, which fires when `matched_amount` moves. A
6
+ -- debt matched before that migration ran never moved again, so its
7
+ -- declaration stayed `accepted` with its money in the bank.
8
+ --
9
+ -- This finds them and records `paid` through `record_filing_outcome()`, the
10
+ -- function the trigger calls, so the declaration and its last deposit carry
11
+ -- the outcome exactly as if the payment had been matched today. The line is
12
+ -- the one the trigger reads: in the settlement entry, on the account the pack
13
+ -- names for the side the period ended on — `tax_payable_code`, or for a
14
+ -- credit `tax_receivable_code` where the pack names one — with something to
15
+ -- pay and nothing left open. A debt paid in part stays accepted, as it would
16
+ -- by the trigger.
17
+ --
18
+ -- It only ever reads `accepted` declarations and writes them `paid`, so a
19
+ -- second run finds nothing to do.
20
+
21
+ do $$
22
+ declare
23
+ r record;
24
+ begin
25
+ for r in
26
+ select f.id
27
+ from tax_filings f
28
+ join companies c on c.id = f.company_id
29
+ join country_defaults d on d.country = c.fiscal_country
30
+ where f.state = 'accepted'
31
+ and f.settlement_entry_id is not null
32
+ and exists (
33
+ select 1 from entry_lines l
34
+ where l.entry_id = f.settlement_entry_id
35
+ and l.account_id = account_id_by_code(f.company_id,
36
+ case when f.credit_treatment is null then d.tax_payable_code
37
+ else coalesce(d.tax_receivable_code, d.tax_payable_code) end)
38
+ and abs(l.debit - l.credit) > 0
39
+ and abs(l.debit - l.credit) - l.matched_amount = 0)
40
+ order by f.company_id, f.period_start, f.id
41
+ loop
42
+ perform record_filing_outcome(r.id, 'paid');
43
+ end loop;
44
+ end;
45
+ $$;