Compare commits

...
Author SHA1 Message Date
nala 3be371c823 docs(delivery): record G4D installed delta and beverage follow-up in L2 L3 2026-10-24 18:09:53 +02:00
nala 686328a085 chore(delivery): prepare G4D with verified destination backup and restore
tests / ci (push) Canceled after 0s
2026-10-24 18:07:35 +02:00
nala 40a4ddcbde docs(iva): close G4D QA with Tempo directed visual confirmation 2026-10-24 18:06:14 +02:00
nala e50733ba1d docs(iva): record G4D coverage exclusions and pending visual proof 2026-10-24 18:05:20 +02:00
nala 8df721ac51 feat(iva): classify G4D onboard supplies with explicit beverage exceptions 2026-10-24 18:04:31 +02:00
nala 25cae1d98b docs(delivery): record G4C installed delta and preserved baseline 2026-10-24 17:59:25 +02:00
nala 679203d4b1 chore(delivery): prepare G4C after authenticated backup and isolated restore
tests / ci (push) Canceled after 0s
2026-10-24 17:56:23 +02:00
nala 2fccbc8ee8 docs(iva): close G4C QA with Tempo manual visual confirmation 2026-10-24 17:55:23 +02:00
nala 19b31d51c5 docs(iva): record G4C code/API coverage and pending directed visual proof 2026-10-24 17:54:36 +02:00
nala b1c8e0e343 feat(iva): add G4C linked export services with explicit operation reference 2026-10-24 17:53:35 +02:00
nala 117f2a70a8 docs(iva): record G4B homologation delivery and preserved balance 2026-10-24 17:42:50 +02:00
nala a153d0782f docs(iva): prepare G4B delivery with fresh authenticated backup and restore
tests / ci (push) Canceled after 0s
2026-10-24 17:40:34 +02:00
nala 0b0e002d15 docs(iva): record Tempo G4B visual completion and current saved result 2026-10-24 17:31:20 +02:00
nala b641887274 docs(iva): record G4B code QA and explicit browser access gate 2026-10-24 17:29:11 +02:00
nala f946364baa feat(iva): implement G4B eligible vessel aircraft and direct services 2026-10-24 17:27:32 +02:00
nala 3846be8fc6 docs(iva): record G4A homologation delivery and preserved balance 2026-10-24 17:21:31 +02:00
nala b898955603 docs(iva): prepare G4A delivery with fresh backup and restore
tests / ci (push) Canceled after 0s
2026-10-24 17:19:15 +02:00
nala 7b54efb0fc docs(iva): record Tempo G4A visual completion and preserved historical result 2026-10-24 17:16:23 +02:00
nala 7a58fa2435 docs(iva): record G4A code QA coverage and explicit visual remainder 2026-10-24 17:08:36 +02:00
nala 0f0d2e566f feat(iva): implement G4A direct international operations with scoped evidence 2026-10-24 17:07:26 +02:00
nala 82e010c44f docs(iva): record G3 homologation delivery and preserved balance 2026-10-24 17:03:13 +02:00
nala 6eefe4b332 docs(iva): prepare G3 delivery with fresh backup restore and compatible rollback
tests / ci (push) Canceled after 0s
2026-10-24 17:01:08 +02:00
nala 0dc2d64b20 docs(iva): record Tempo visual completion of G3 QA 2026-10-24 16:58:34 +02:00
nala bda6d1e3a0 docs(iva): record G3 cessation code QA and explicit visual verification remainder 2026-10-24 16:54:23 +02:00
nala ac948bd8b7 feat(iva): implement G3 temporary benefit cessation and explicit treatment continuity 2026-10-24 16:51:52 +02:00
nala 908c8afc54 docs(iva): make G2L manual visual evidence and technical corroboration explicit 2026-10-24 16:44:26 +02:00
nala 643ba6ed72 docs(iva): record G2K G2L homologation delivery and preserved balance 2026-10-24 16:41:57 +02:00
nala ccdecbd8d7 docs(iva): verify G2K G2L joint delivery backup and restore
tests / ci (push) Canceled after 0s
2026-10-24 16:39:06 +02:00
nala da798dd1d8 docs(iva): complete G2L QA with Tempo review and actual saved payload evidence 2026-10-24 16:36:58 +02:00
nala 0304612093 docs(iva): record partial Tempo review and clarify QA save recovery controls 2026-10-24 16:33:05 +02:00
nala d76078a81f docs(iva): accept Tempo manual verification route without claiming G2L closure 2026-10-24 16:24:02 +02:00
nala c4cc7d83e7 docs(iva): record G2L code QA and explicit pending visual access gate 2026-10-24 16:20:31 +02:00
nala 744682835a feat(iva): implement G2L Annex I and explicit continuity pending visual QA 2026-10-24 16:19:52 +02:00
nala 1fe742561f docs(iva): record G2K P008 QA candidate and preserved balance 2026-10-24 16:06:48 +02:00
nala 8882dc54d0 feat(iva): implement G2K pharmaceutical manufacturing inputs in QA 2026-10-24 16:05:55 +02:00
nala eb9e0dbc60 docs(iva): record G2I G2J homologation delivery and calendar resolution 2026-10-24 15:52:45 +02:00
nala e45a1394fa docs(iva): verify G2I G2J joint delivery backup and calendar evidence
tests / ci (push) Canceled after 0s
2026-10-24 15:49:08 +02:00
nala 72f4187d3b feat(iva): add fundraising group and correct production option calendar in QA 2026-10-24 15:47:02 +02:00
nala a5ac8ca1c9 docs(iva): record G2I QA candidate and explicit calendar limit 2026-10-24 15:31:29 +02:00
nala fe69a16eea feat(iva): add own-production exemptions and dated tax options in QA 2026-10-24 15:31:27 +02:00
nala 7696af6814 docs(iva): record G2G G2H homologation delivery and preserved balance 2026-10-24 15:15:49 +02:00
nala d4eae917ee docs(iva): verify G2G G2H joint delivery backup and compatibility
tests / ci (push) Canceled after 0s
2026-10-24 15:13:32 +02:00
nala b297058d11 docs(iva): record G2H QA candidate and one-branch coverage 2026-10-24 15:12:30 +02:00
nala 48146089cd feat(iva): add eighteen enumerated products within P026 in QA 2026-10-24 15:12:14 +02:00
nala 2440cb448a docs(iva): record G2G QA candidate and four-branch balance 2026-10-24 15:06:45 +02:00
nala 9dbfdd67ad feat(iva): add conditional public official and asset-sale operations in QA 2026-10-24 15:06:43 +02:00
nala b1928b61e5 docs(iva): clarify delivered G2F IDs and evidence paths 2026-10-24 15:03:42 +02:00
nala 541ea70484 docs(iva): record G2E G2F homologation delivery and preservation 2026-10-24 15:01:45 +02:00
nala 9a56d98242 docs(iva): verify G2E G2F destination backup and isolated restore
tests / ci (push) Canceled after 0s
2026-10-24 14:59:24 +02:00
nala 38b49bd5fa docs(iva): prepare G2E G2F joint delivery and authenticated preflight 2026-10-24 14:57:53 +02:00
nala 9b0f437073 docs(iva): record G2F candidate and seven QA branches 2026-10-24 14:57:23 +02:00
nala 8171c7992e feat(iva): add games stamped values and passenger transport in QA 2026-10-24 14:57:22 +02:00
nala 30760cab9b docs(iva): record G2E QA candidate and preserved balance 2026-10-24 14:53:24 +02:00
nala 33d18b9efc feat(iva): add conditional agropecuary operations in QA 2026-10-24 14:53:23 +02:00
nala 0aac0d1555 docs(iva): record G2C G2D homologation delivery and preservation 2026-10-24 14:49:27 +02:00
nala 3b788ec009 docs(iva): record G2C G2D backup and activation scope
tests / ci (push) Canceled after 0s
2026-10-24 14:46:36 +02:00
nala db4ff64e87 docs(iva): prepare verified G2C G2D joint Git delivery 2026-10-24 14:46:24 +02:00
nala c28e290b42 docs(iva): record G2D candidate and joint QA balance 2026-10-24 14:42:43 +02:00
nala 8d127799cd feat(iva): add author rights and eligible publications in QA 2026-10-24 14:42:38 +02:00
nala d32ad1e0a6 docs(iva): record G2C QA candidate and preserved delivery balance 2026-10-24 14:39:04 +02:00
nala 122f4f04b9 feat(iva): add conditional cultural and membership operations in QA 2026-10-24 14:38:55 +02:00
nala dacda11c07 Record joint L1 homologation delivery 490527b9 and verified preservation 2026-10-24 14:32:35 +02:00
nala 490527b92c Record joint L1 QA candidate, verified Git bundle and integration preview
tests / ci (push) Canceled after 0s
2026-10-24 14:22:15 +02:00
nala 4a35d63cd3 Complete G2B social QA and prepare joint L1 delivery with compatible rollback 2026-10-24 14:21:21 +02:00
nala 0e644b5524 Record G2A QA candidate and reconciled L1 closure counts 2026-10-24 14:04:45 +02:00
nala 675cf38f67 Implement G2A health exemptions in QA and reconcile L1 branch inventory 2026-10-24 14:04:18 +02:00
nala 89ab288334 Record L1 grouped QA candidate and verified final export evidence 2026-10-24 13:54:42 +02:00
nala 5030116ee5 Group L1 coverage and implement documented service exemptions in QA 2026-10-24 13:54:32 +02:00
nala 8719e916ea docs: record rational VAT QA candidate and open form dependency 2026-10-24 13:20:52 +02:00
nala 689e7cbe8b feat: preserve exact included VAT fractions and enumerate L1 remainder 2026-10-24 13:20:32 +02:00
nala d89912e579 docs: record IVA L1 QA candidate and explicit remaining scope 2026-10-24 13:00:26 +02:00
nala 544068e8cc feat: demonstrate scoped IVA operations L1 in QA 2026-10-24 12:59:37 +02:00
nala e8c39a1b54 docs: receipt for installed Modelo A acquisitions and totals 2026-10-24 12:19:34 +02:00
nala 1655f57e69 docs: register Modelo A acquisitions QA candidate and evidence
tests / ci (push) Canceled after 0s
2026-10-24 12:14:21 +02:00
nala d18ff0f049 feat: implement opportunity-scoped Modelo A acquisitions in QA 2026-10-24 12:13:57 +02:00
nala 355656b5c8 docs: receipt for installed simulator S1-S3 closure in homologation 2026-10-24 11:41:57 +02:00
nala cd10cccbf4 docs: close S3 monthly PDF review and mark simulator candidate ready for integration
tests / ci (push) Canceled after 0s
2026-10-24 11:37:09 +02:00
nala d044ef1efc docs: record S1 and S2 QA results and directed S3 file checks 2026-10-24 11:30:59 +02:00
nala 65b87819a0 fix: preserve cashflow currency and recover admitted monthly IVA executions in QA 2026-10-24 11:29:15 +02:00
nala be62783b98 docs: delimit simulator closure to two code gaps and monthly export proof 2026-10-24 11:16:42 +02:00
109 changed files with 16217 additions and 46 deletions
@@ -37,7 +37,7 @@ class StoreSimulationFormDraftRequest extends FormRequest
'contact_province', 'contact_district', 'preferred_channel',
];
$economic = [
'context_opportunity', 'context_applicability_snapshot', 'investment_regime', 'context_reuse', 'compatible_fields_snapshot', 'published_iva_base', 'published_iva_currency', 'published_iva_date', 'published_iva_scope', 'monthly_iva_settings', 'monthly_iva_snapshot', 'journey_type', 'detail_level', 'business_plan_snapshot', 'financial_tools_snapshot', 'cashflow_snapshot', 'project_team_snapshot', 'project_execution_snapshot', 'purpose', 'manifestation_type', 'preferred_language', 'project_title', 'project_summary', 'project_problem', 'target_customers', 'value_proposition', 'market_assumption', 'market_source', 'project_milestones', 'selection_labels', 'project_type',
'context_opportunity', 'context_applicability_snapshot', 'investment_regime', 'context_reuse', 'compatible_fields_snapshot', 'published_iva_base', 'published_iva_currency', 'published_iva_date', 'published_iva_scope', 'monthly_iva_settings', 'monthly_iva_snapshot', 'modelo_a_snapshot', 'journey_type', 'detail_level', 'business_plan_snapshot', 'financial_tools_snapshot', 'cashflow_snapshot', 'project_team_snapshot', 'project_execution_snapshot', 'purpose', 'manifestation_type', 'preferred_language', 'project_title', 'project_summary', 'project_problem', 'target_customers', 'value_proposition', 'market_assumption', 'market_source', 'project_milestones', 'selection_labels', 'project_type',
'competitor_assumption', 'sales_channel_assumption', 'marketing_approach', 'location_rationale', 'project_risk_responses_snapshot', 'project_questionnaire_version',
'customer_validation_status', 'cost_estimate_status', 'location_assessment_status', 'funding_status', 'receivables_timing_status',
'project_type_other', 'sector_id', 'activity_id', 'products_services', 'maturity_stage', 'expected_start_date',
@@ -83,6 +83,7 @@ class StoreSimulationFormDraftRequest extends FormRequest
'economic_snapshot.published_iva_scope' => ['nullable', 'string', 'in:yes,no'],
'economic_snapshot.monthly_iva_settings' => ['nullable', 'string', 'max:2000'],
'economic_snapshot.monthly_iva_snapshot' => ['nullable', 'string', 'max:60000'],
'economic_snapshot.modelo_a_snapshot' => ['nullable', 'string', 'json', 'max:1000000'],
'economic_snapshot.project_team_snapshot' => ['nullable', 'string', 'max:30000'],
'economic_snapshot.project_execution_snapshot' => ['nullable', 'string', 'max:30000'],
'economic_snapshot.project_risk_responses_snapshot' => ['nullable', 'string', 'max:30000'],
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,258 @@
{
"status": "installed_delta_verified_partial_L1",
"base_remote_main": "490527b92cf1ca18122679440ff3a38933b7e0c2",
"candidate": "c28e290b42a2a96c68b16dab59871581633a471e",
"compatibility": "fresh fetch;origin/main ancestor of candidate;no concurrent change;local stale main not used",
"coverage": {
"G2C": {
"P013": [
"cultural_visits_public",
"cultural_visits_nonprofit"
],
"P014": [
"religious_personnel_public",
"religious_personnel_nonprofit"
],
"P015": [
"statutory_membership"
]
},
"G2D": {
"P024": [
"author_rights"
],
"P025": [
"cultural_publications"
]
},
"new_branches": 5,
"new_treatments": 7,
"conditional_treatments_total": 32
},
"counts_before": {
"delivered": 12,
"QA": 5,
"functional_pending": 115,
"documentary": 1,
"total": 133
},
"counts_after_delivery": {
"delivered": 17,
"QA": 0,
"functional_pending": 115,
"documentary": 1,
"total": 133
},
"runtime_delta": [
{
"path": "resources/js/lib/iva-operations.ts",
"sha256_LF": "577a029e24580d9c4dba0e4c19ce57da6273fe6f44185b3a32bd02fd7573578c"
}
],
"activation": "Existing Git FF/webhook installer;catalogue available in existing L1 component;no migration/import/server fiscal rule activation/permissions changes",
"preservation": "12delivered+G2C/G2Dproofs reused;four frozen books unchanged/current without recalculation;newrules scoped keys only",
"rollback": "Existing compatible readonly containment patch apply-check passed;keep catalogue/readers/snapshots/reports;prior release and fresh verified backup required;no active rollback executed",
"QA": "G2C2frontend+API1/14;G2D2frontend+API1/11;UI?API?report;types/build passed;acceptedWord/PDFunchanged",
"P001_blocks_independent": false,
"L1_complete": false,
"statistics_AI": "deferred",
"authenticated_preflight": "confirmed490527b9;installed/current/revisionagree;serviceinactive;pipelinehashunchanged",
"backup_restore": {
"verified": true,
"tables": 174,
"files": 369,
"dump_sha256": "c11ba51e60cb3ac1cad5411c2aeefcb0adaeadd6fd2c16cd42fd6b63b1449fff",
"backup": "/var/backups/investmoz-l1-g2cd-delivery-20261024/backup",
"restore": "l1_g2cd_restore_20261024:55441;networknone;174checksumsagree;containerremoved;zeroactiveDBwrites"
},
"installed_delta": "verified",
"served_commit": "3b788ec0098d84dcc154239651a35c685dfc2ebd",
"installation": {
"backup": {
"stage": "/var/backups/investmoz-l1-g2cd-delivery-20261024/backup",
"target": {
"database": "teste_investidor",
"port": 5432
},
"tables": 174,
"files_verified": 369,
"dump_sha256": "c11ba51e60cb3ac1cad5411c2aeefcb0adaeadd6fd2c16cd42fd6b63b1449fff",
"files_sha256": "21fc80e45eaa289b67e2d2ce6bcc538b51330a3fa7cfb7e9cd64367201389b5e",
"restore_verified": false
},
"restore": {
"restore_verified": true,
"tables_verified": 174,
"container_network": "none",
"database": "l1_g2cd_restore_20261024",
"port": 55441,
"source_dump_sha256": "c11ba51e60cb3ac1cad5411c2aeefcb0adaeadd6fd2c16cd42fd6b63b1449fff",
"active_database_writes": 0
},
"installer": {
"service": "ExecMainStatus=0\nActiveState=inactive\nSubState=dead\n",
"installed": {
"status": "installed",
"commit": "3b788ec0098d84dcc154239651a35c685dfc2ebd",
"release": "/var/www/investmoz-homologacao/releases/3b788ec0098d84dcc154239651a35c685dfc2ebd-56825c6e",
"previous_release": "/var/www/investmoz-homologacao/releases/490527b92cf1ca18122679440ff3a38933b7e0c2-d41ae12f",
"database_migrations": 0,
"content_imports": 0
},
"latest_report": {
"status": "installed",
"commit": "3b788ec0098d84dcc154239651a35c685dfc2ebd",
"release": "/var/www/investmoz-homologacao/releases/3b788ec0098d84dcc154239651a35c685dfc2ebd-56825c6e",
"previous_release": "/var/www/investmoz-homologacao/releases/490527b92cf1ca18122679440ff3a38933b7e0c2-d41ae12f",
"database_migrations": 0,
"content_imports": 0,
"requested_commits": [
"3b788ec0098d84dcc154239651a35c685dfc2ebd"
],
"finished_at": "2026-10-24T12:48:10.504292+00:00"
},
"log_file": "1792846007466003663.log",
"summaries": [
"OK (1 test, 3106 assertions)",
"built in 23.88s",
"OK (59 tests, 317 assertions)",
"# tests 251",
"# pass 251",
"# fail 0"
],
"log_bytes": 101223
},
"protected_preservation": {
"installed": {
"status": "installed",
"commit": "3b788ec0098d84dcc154239651a35c685dfc2ebd",
"release": "/var/www/investmoz-homologacao/releases/3b788ec0098d84dcc154239651a35c685dfc2ebd-56825c6e",
"previous_release": "/var/www/investmoz-homologacao/releases/490527b92cf1ca18122679440ff3a38933b7e0c2-d41ae12f",
"database_migrations": 0,
"content_imports": 0
},
"runtime_files_verified": 1,
"persistent_files_and_env_verified": 369,
"tables_compared": 174,
"changed_tables": {
"audit_events": {
"before": {
"rows": 645,
"checksum": "88c2047620eb3fad4d2a2837ed3daef5"
},
"after": {
"rows": 646,
"checksum": "cf24e81547ee23d812ccaadaccc387b6"
}
},
"cache": {
"before": {
"rows": 105,
"checksum": "ef2967a3b3174300a6509d3013c1823d"
},
"after": {
"rows": 105,
"checksum": "6dfe16f04a406749beaf0a189897106b"
}
},
"sessions": {
"before": {
"rows": 5,
"checksum": "2a932f661c46631221bec768a4a23574"
},
"after": {
"rows": 8,
"checksum": "6d7f01315a1de04eadaddc0b90e0526c"
}
}
},
"preserved_counts": {
"published_fiches": 29,
"relations": 28,
"geometries": 408
},
"migration_count": 0,
"content_imports": 0,
"comparison_role": "postgres_before_and_after;sameexportedsnapshotbaseline;noapplicationRLSvisibilityinference",
"writes_by_verification": 0
},
"audit_delta": {
"historical_audit_unchanged": true,
"historical_rows": 645,
"new_events": 1,
"new_event_metadata": {
"source_system": "virtual-desk",
"entity_type": "desk_cases",
"action": "consulted",
"created_at": "2026-10-24T12:47:35.31492+00:00"
},
"verification_writes": 0
},
"public_delta": {
"status": "installed_delta_verified",
"served_revision": {
"commit": "3b788ec0098d84dcc154239651a35c685dfc2ebd",
"branch": "main",
"built_at": "2026-10-24T12:48:08.073225+00:00",
"manifest_sha256": "b00f59904a5709fbcd8eaa6b51ac8dc421ddfc8dfd2e0ce18d133240150c8810"
},
"manifest_hash_matches": true,
"compiled_delta_markers": {
"cultural_visits_": [
"assets/project-dossier-BDWSVUNs.js"
],
"religious_personnel_": [
"assets/project-dossier-BDWSVUNs.js"
],
"statutory_membership": [
"assets/project-dossier-BDWSVUNs.js"
],
"author_rights": [
"assets/project-dossier-BDWSVUNs.js"
],
"cultural_publications": [
"assets/project-dossier-BDWSVUNs.js"
],
"iva-operations-l1/2": [
"assets/project-dossier-BDWSVUNs.js"
]
},
"assets": [
{
"file": "assets/simulation-form-CPZAFZU3.js",
"status": 200,
"sha256": "c6bcf64e60a5eeac0cafe3dc055dc5544162f21942ee08b34d51bc6d52947567"
},
{
"file": "assets/project-dossier-document-BVqhDRN3.js",
"status": 200,
"sha256": "56076c99222527ecc453bd245e21830618d07d26a874eede4f07cd597587922a"
},
{
"file": "assets/project-dossier-BDWSVUNs.js",
"status": 200,
"sha256": "574235d0a55380d1a0a4044b46bed1c9f47aca0ec4f61b1356ac7216b8fcc85d"
},
{
"file": "assets/services-CJfVMeO3.js",
"status": 200,
"sha256": "ae0b9fda96068b6179b16d0b7d121d4d840ba82d6763253821bb6b9ac03a3686"
}
],
"simulator_status": 200,
"simulator_entry": "assets/app-B0KlTmxs.js",
"existing_fiscal_availability": {
"data": {
"enabled": true,
"coverage_start": "2026-01-01",
"coverage_end": "2026-12-31",
"message": "IVA geral sobre base líquida disponível; enquadramento declarado."
}
},
"synthetic_private_writes": 0,
"method": "Read-only installedrevision/manifest/newcompiledcatalogueandreaders/simulatorentry;acceptedQAproofsreused"
},
"Git": "freshfetch;branchpush;mainfastforward;noforce;existingwebhook",
"rollback_executed": false
}
}
@@ -0,0 +1,289 @@
{
"status": "installed_delta_verified_partial_L1",
"candidate": "9b0f4370737f340b7fca606728f5ca281f6b5dfd",
"base_remote_main": "3b788ec0098d84dcc154239651a35c685dfc2ebd",
"fresh_fetch": "confirmed main3b788ec0;ancestor;no concurrent changes detected;localmainnotused",
"coverage": {
"G2E": {
"P033": "industrial_feed",
"P034": "industrial_feed_inputs",
"P036": "veterinary_goods",
"P044": "agricultural_services"
},
"G2F": {
"P023": "special_tax_games",
"P028": "stamped_values",
"P037": "public_passenger_transport"
},
"new_branches": 7,
"new_treatments": 7,
"conditional_treatments_total": 39
},
"counts_before": {
"delivered": 17,
"QA": 7,
"functional_pending": 108,
"documentary": 1,
"total": 133
},
"counts_after_delivery": {
"delivered": 24,
"QA": 0,
"functional_pending": 108,
"documentary": 1,
"total": 133
},
"runtime_delta": [
{
"path": "resources/js/lib/iva-operations.ts",
"sha256_LF": "dcb141a4d0a1edb0d2b2c8f63a20a076b8362c02d652baad673e652c133c64ce"
}
],
"activation": "ExistingGitFF/webhook/installer;catalogueexistingcomponent;no migrations/imports/server fiscal rule activation/permissions changes",
"preservation": "17delivered closed;G2E/G2FacceptedQAproofsreused;sixfrozenbookscurrentwithoutrecalculation",
"rollback": "Keepcataloguereaderssnapshotsresultsreports;existingreadonlycontainmentpatchapplycheckrequired;backuprestorebeforepush;no rollback executed",
"P001": "Stilldocumentary05/06;05/07doesnotresolveit;doesnotblockindependent",
"QA": "G2E2frontend+API1/14;G2F2frontend+API1/13;UItoAPIreport;types/buildpassed;WordPDFunchanged",
"authenticated_preflight": {
"installed": {
"status": "installed",
"commit": "3b788ec0098d84dcc154239651a35c685dfc2ebd",
"release": "/var/www/investmoz-homologacao/releases/3b788ec0098d84dcc154239651a35c685dfc2ebd-56825c6e",
"previous_release": "/var/www/investmoz-homologacao/releases/490527b92cf1ca18122679440ff3a38933b7e0c2-d41ae12f",
"database_migrations": 0,
"content_imports": 0
},
"current_link": "/var/www/investmoz-homologacao/releases/3b788ec0098d84dcc154239651a35c685dfc2ebd-56825c6e",
"release_revision": {
"commit": "3b788ec0098d84dcc154239651a35c685dfc2ebd",
"branch": "main",
"built_at": "2026-10-24T12:48:08.073225+00:00",
"manifest_sha256": "b00f59904a5709fbcd8eaa6b51ac8dc421ddfc8dfd2e0ce18d133240150c8810"
},
"service": "ExecMainStatus=0\nActiveState=inactive\nSubState=dead\n",
"configuration_keys": [
"repository",
"branch",
"target_url",
"legacy_root",
"state_root",
"release_root",
"current_link",
"shared_assets",
"php",
"schema_contract",
"ci_environment",
"postgis_image",
"test_database",
"qa_port",
"retention",
"webhook_secret_file"
],
"safe_paths": {
"repository": "nala/Investidor-V2",
"release_root": "/var/www/investmoz-homologacao/releases",
"postgis_image": "postgis/postgis@sha256:01a6a70e41e6c4467c8f55f6063555ed72db2d6662cd0d571040d42eadaeb6f6"
},
"pipeline_sha256": "adec1c17654f3a8658b83b134f1e75f95391b235738552721906c3236e388604"
},
"backup_restore": {
"backup": {
"stage": "/var/backups/investmoz-l1-g2ef-delivery-20261024/backup",
"target": {
"database": "teste_investidor",
"port": 5432
},
"tables": 174,
"files_verified": 369,
"dump_sha256": "e23ea1909ede1cb3be7a5e5751f5580e8b8c0b2452c53772c8e28d06ec999b20",
"files_sha256": "c56f7ac804b0d4f0c69a2f53a23b00cc34fa067888e62e13444192b3d41c52cf",
"restore_verified": false
},
"restore": {
"restore_verified": true,
"tables_verified": 174,
"container_network": "none",
"database": "l1_g2ef_restore_20261024",
"port": 55441,
"source_dump_sha256": "e23ea1909ede1cb3be7a5e5751f5580e8b8c0b2452c53772c8e28d06ec999b20",
"active_database_writes": 0
}
},
"installed_delta": "verified",
"L1_complete": false,
"statistics_AI": "deferred",
"rollback_compatibility": "gitapplycheckpassed;notapplied;keepcatalogueandreaders;previousreleaseandverifiedbackupavailable",
"served_commit": "9a56d982423d0c244850f8638290a1ce8a968619",
"installation": {
"backup": {
"stage": "/var/backups/investmoz-l1-g2ef-delivery-20261024/backup",
"target": {
"database": "teste_investidor",
"port": 5432
},
"tables": 174,
"files_verified": 369,
"dump_sha256": "e23ea1909ede1cb3be7a5e5751f5580e8b8c0b2452c53772c8e28d06ec999b20",
"files_sha256": "c56f7ac804b0d4f0c69a2f53a23b00cc34fa067888e62e13444192b3d41c52cf",
"restore_verified": false
},
"restore": {
"restore_verified": true,
"tables_verified": 174,
"container_network": "none",
"database": "l1_g2ef_restore_20261024",
"port": 55441,
"source_dump_sha256": "e23ea1909ede1cb3be7a5e5751f5580e8b8c0b2452c53772c8e28d06ec999b20",
"active_database_writes": 0
},
"installer": {
"service": "ExecMainStatus=0\nActiveState=inactive\nSubState=dead\n",
"installed": {
"status": "installed",
"commit": "9a56d982423d0c244850f8638290a1ce8a968619",
"release": "/var/www/investmoz-homologacao/releases/9a56d982423d0c244850f8638290a1ce8a968619-19d0ea6c",
"previous_release": "/var/www/investmoz-homologacao/releases/3b788ec0098d84dcc154239651a35c685dfc2ebd-56825c6e",
"database_migrations": 0,
"content_imports": 0
},
"latest_report": {
"status": "installed",
"commit": "9a56d982423d0c244850f8638290a1ce8a968619",
"release": "/var/www/investmoz-homologacao/releases/9a56d982423d0c244850f8638290a1ce8a968619-19d0ea6c",
"previous_release": "/var/www/investmoz-homologacao/releases/3b788ec0098d84dcc154239651a35c685dfc2ebd-56825c6e",
"database_migrations": 0,
"content_imports": 0,
"requested_commits": [
"9a56d982423d0c244850f8638290a1ce8a968619"
],
"finished_at": "2026-10-24T13:01:02.426859+00:00"
},
"log_file": "1792846776358374658.log",
"summaries": [
"OK (1 test, 3106 assertions)",
"built in 25.68s",
"OK (59 tests, 317 assertions)",
"# tests 255",
"# pass 255",
"# fail 0"
],
"log_bytes": 102308
},
"protected_preservation": {
"installed": {
"status": "installed",
"commit": "9a56d982423d0c244850f8638290a1ce8a968619",
"release": "/var/www/investmoz-homologacao/releases/9a56d982423d0c244850f8638290a1ce8a968619-19d0ea6c",
"previous_release": "/var/www/investmoz-homologacao/releases/3b788ec0098d84dcc154239651a35c685dfc2ebd-56825c6e",
"database_migrations": 0,
"content_imports": 0
},
"runtime_files_verified": 1,
"persistent_files_and_env_verified": 369,
"tables_compared": 174,
"changed_tables": {
"cache": {
"before": {
"rows": 105,
"checksum": "17b5d816f82ab932dca814a8e76c1211"
},
"after": {
"rows": 105,
"checksum": "316356979dc340fc5f141679bdee5c0d"
}
},
"sessions": {
"before": {
"rows": 8,
"checksum": "d1df0268b1343c91b756052e39ca7930"
},
"after": {
"rows": 11,
"checksum": "787de58f2b0436566c2ad27161a8a759"
}
}
},
"preserved_counts": {
"published_fiches": 29,
"relations": 28,
"geometries": 408
},
"migration_count": 0,
"content_imports": 0,
"comparison_role": "postgres_before_and_after;sameexportedsnapshotbaseline;noapplicationRLSvisibilityinference",
"writes_by_verification": 0
},
"public_delta": {
"status": "installed_delta_verified",
"served_revision": {
"commit": "9a56d982423d0c244850f8638290a1ce8a968619",
"branch": "main",
"built_at": "2026-10-24T13:00:59.831259+00:00",
"manifest_sha256": "b92bc7b64176675274dd934bb683f09c4a4ca3c4fe690dfce06425e89a7f3e04"
},
"manifest_hash_matches": true,
"compiled_delta_markers": {
"industrial_feed": [
"assets/project-dossier-DSFHX342.js"
],
"industrial_feed_inputs": [
"assets/project-dossier-DSFHX342.js"
],
"veterinary_goods": [
"assets/project-dossier-DSFHX342.js"
],
"agricultural_services": [
"assets/project-dossier-DSFHX342.js"
],
"special_tax_games": [
"assets/project-dossier-DSFHX342.js"
],
"stamped_values": [
"assets/project-dossier-DSFHX342.js"
],
"public_passenger_transport": [
"assets/project-dossier-DSFHX342.js"
],
"iva-operations-l1/2": [
"assets/project-dossier-DSFHX342.js"
]
},
"assets": [
{
"file": "assets/project-dossier-DSFHX342.js",
"status": 200,
"sha256": "9083729b212d85c15164545718f7813f1a843627eb7dffbfa398bd8ce4a35afb"
},
{
"file": "assets/services-CfCgVoiZ.js",
"status": 200,
"sha256": "4e3c1d5d90b642e4face01d05ab47f73cc9e3e7c4286fb7b638319d8d71dc96a"
},
{
"file": "assets/project-dossier-document-7BExzGRH.js",
"status": 200,
"sha256": "3e925451351648c1dd2f7323c15e1881ba09dd3f0f27092a153958537476583f"
},
{
"file": "assets/simulation-form-CPZAFZU3.js",
"status": 200,
"sha256": "c6bcf64e60a5eeac0cafe3dc055dc5544162f21942ee08b34d51bc6d52947567"
}
],
"simulator_status": 200,
"simulator_entry": "assets/app-CHL9O0-A.js",
"existing_fiscal_availability": {
"data": {
"enabled": true,
"coverage_start": "2026-01-01",
"coverage_end": "2026-12-31",
"message": "IVA geral sobre base líquida disponível; enquadramento declarado."
}
},
"synthetic_private_writes": 0,
"method": "Read-only installedrevision/manifest/newcompiledcatalogueandreaders/simulatorentry;acceptedQAproofsreused"
},
"Git": "freshfetch;branchpush;mainfastforward;noforce;existingwebhook",
"rollback_executed": false
}
}
@@ -0,0 +1,371 @@
{
"status": "installed_delta_verified_partial_L1",
"candidate": "b297058d11aee206530492a65f86e3d58eb5ba15",
"base_remote_main": "9a56d982423d0c244850f8638290a1ce8a968619",
"fresh_fetch": "main9a56d982;ancestor;no concurrent advance detected",
"coverage": {
"G2G": {
"P010": [
"public_security"
],
"P027": [
"official_military_supplies"
],
"P031": [
"sisa_subject_operation"
],
"P032": [
"exempt_activity_asset_sale",
"no_deduction_right_asset_sale",
"excluded_deduction_asset_sale"
]
},
"G2H": {
"P026": [
"listed_maize",
"listed_maize_flour",
"listed_rice",
"listed_bread",
"listed_iodised_salt",
"listed_infant_powdered_milk",
"listed_wheat",
"listed_wheat_flour",
"listed_fresh_chilled_tomato",
"listed_potato",
"listed_onion",
"listed_frozen_horse_mackerel",
"listed_lighting_kerosene",
"listed_domestic_lpg",
"listed_jet_fuel",
"listed_eligible_bicycles",
"listed_condoms",
"listed_insecticides"
]
},
"new_branches": 5,
"new_treatments": 24,
"conditional_treatments_total": 63
},
"counts_before": {
"delivered": 24,
"QA": 5,
"functional_pending": 103,
"documentary": 1,
"total": 133
},
"counts_after_delivery": {
"delivered": 29,
"QA": 0,
"functional_pending": 103,
"documentary": 1,
"total": 133
},
"runtime_delta": [
{
"path": "resources/js/lib/iva-operations.ts",
"sha256_LF": "f18941067a82d18f43af4252c11b7ff26e001212e1e6cb5bff62c9b4ba48f855"
}
],
"activation": "ExistingGitFF/webhook/installer;catalogueexistingcomponent;no migrations/imports/server rule activation/permissions/other tax calculations",
"QA": "G2G2frontend+API1/16;G2H2frontend+API1/28;UItoAPIreport;types/buildpassed;acceptedWordPDFreused",
"preservation": "24delivered andeightfrozencontextscurrentwithoutrecalculation;G2G/G2Hproofsreused;G2Ftraceabilityclarifiedwithoutretests",
"rollback": "Keepcataloguereaderssnapshotsresultsreports;compatibleexistingreadonlypatch;priorreleaseandfreshbackuprestorebeforepush;no rollback executed",
"P001": "Documentary05/06stillopen;05/07doesnotresolveit;noindependentblock",
"authenticated_preflight": {
"installed": {
"status": "installed",
"commit": "9a56d982423d0c244850f8638290a1ce8a968619",
"release": "/var/www/investmoz-homologacao/releases/9a56d982423d0c244850f8638290a1ce8a968619-19d0ea6c",
"previous_release": "/var/www/investmoz-homologacao/releases/3b788ec0098d84dcc154239651a35c685dfc2ebd-56825c6e",
"database_migrations": 0,
"content_imports": 0
},
"current_link": "/var/www/investmoz-homologacao/releases/9a56d982423d0c244850f8638290a1ce8a968619-19d0ea6c",
"release_revision": {
"commit": "9a56d982423d0c244850f8638290a1ce8a968619",
"branch": "main",
"built_at": "2026-10-24T13:00:59.831259+00:00",
"manifest_sha256": "b92bc7b64176675274dd934bb683f09c4a4ca3c4fe690dfce06425e89a7f3e04"
},
"service": "ExecMainStatus=0\nActiveState=inactive\nSubState=dead\n",
"configuration_keys": [
"repository",
"branch",
"target_url",
"legacy_root",
"state_root",
"release_root",
"current_link",
"shared_assets",
"php",
"schema_contract",
"ci_environment",
"postgis_image",
"test_database",
"qa_port",
"retention",
"webhook_secret_file"
],
"safe_paths": {
"repository": "nala/Investidor-V2",
"release_root": "/var/www/investmoz-homologacao/releases",
"postgis_image": "postgis/postgis@sha256:01a6a70e41e6c4467c8f55f6063555ed72db2d6662cd0d571040d42eadaeb6f6"
},
"pipeline_sha256": "adec1c17654f3a8658b83b134f1e75f95391b235738552721906c3236e388604"
},
"backup_restore": {
"backup": {
"stage": "/var/backups/investmoz-l1-g2gh-delivery-20261024/backup",
"target": {
"database": "teste_investidor",
"port": 5432
},
"tables": 174,
"files_verified": 369,
"dump_sha256": "ffe24d9e324cc1ad2354e8feec088e072db437eb54d1f5b6dfd3830865940b40",
"files_sha256": "57bcb40faf4cb5e14b0aa13eb8b274f222e51bc3cd5fd17e07d70e87165e2b94",
"restore_verified": false
},
"restore": {
"restore_verified": true,
"tables_verified": 174,
"container_network": "none",
"database": "l1_g2gh_restore_20261024",
"port": 55441,
"source_dump_sha256": "ffe24d9e324cc1ad2354e8feec088e072db437eb54d1f5b6dfd3830865940b40",
"active_database_writes": 0
}
},
"installed_delta": "verified",
"L1_complete": false,
"statistics_AI": "deferred",
"rollback_compatibility": "gitapplycheckpassed;notapplied;keepcatalogueandreaders;previousreleaseandverifiedbackupavailable",
"served_commit": "d4eae917ee9c9d37f0339905a96c1e35480f324e",
"installation": {
"backup": {
"stage": "/var/backups/investmoz-l1-g2gh-delivery-20261024/backup",
"target": {
"database": "teste_investidor",
"port": 5432
},
"tables": 174,
"files_verified": 369,
"dump_sha256": "ffe24d9e324cc1ad2354e8feec088e072db437eb54d1f5b6dfd3830865940b40",
"files_sha256": "57bcb40faf4cb5e14b0aa13eb8b274f222e51bc3cd5fd17e07d70e87165e2b94",
"restore_verified": false
},
"restore": {
"restore_verified": true,
"tables_verified": 174,
"container_network": "none",
"database": "l1_g2gh_restore_20261024",
"port": 55441,
"source_dump_sha256": "ffe24d9e324cc1ad2354e8feec088e072db437eb54d1f5b6dfd3830865940b40",
"active_database_writes": 0
},
"installer": {
"service": "ExecMainStatus=0\nActiveState=inactive\nSubState=dead\n",
"installed": {
"status": "installed",
"commit": "d4eae917ee9c9d37f0339905a96c1e35480f324e",
"release": "/var/www/investmoz-homologacao/releases/d4eae917ee9c9d37f0339905a96c1e35480f324e-afcda0da",
"previous_release": "/var/www/investmoz-homologacao/releases/9a56d982423d0c244850f8638290a1ce8a968619-19d0ea6c",
"database_migrations": 0,
"content_imports": 0
},
"latest_report": {
"status": "installed",
"commit": "d4eae917ee9c9d37f0339905a96c1e35480f324e",
"release": "/var/www/investmoz-homologacao/releases/d4eae917ee9c9d37f0339905a96c1e35480f324e-afcda0da",
"previous_release": "/var/www/investmoz-homologacao/releases/9a56d982423d0c244850f8638290a1ce8a968619-19d0ea6c",
"database_migrations": 0,
"content_imports": 0,
"requested_commits": [
"d4eae917ee9c9d37f0339905a96c1e35480f324e"
],
"finished_at": "2026-10-24T13:15:14.273272+00:00"
},
"log_file": "1792847626452821855.log",
"summaries": [
"OK (1 test, 3106 assertions)",
"built in 26.20s",
"OK (59 tests, 317 assertions)",
"# tests 259",
"# pass 259",
"# fail 0"
],
"log_bytes": 103542
},
"protected_preservation": {
"installed": {
"status": "installed",
"commit": "d4eae917ee9c9d37f0339905a96c1e35480f324e",
"release": "/var/www/investmoz-homologacao/releases/d4eae917ee9c9d37f0339905a96c1e35480f324e-afcda0da",
"previous_release": "/var/www/investmoz-homologacao/releases/9a56d982423d0c244850f8638290a1ce8a968619-19d0ea6c",
"database_migrations": 0,
"content_imports": 0
},
"runtime_files_verified": 1,
"persistent_files_and_env_verified": 369,
"tables_compared": 174,
"changed_tables": {
"cache": {
"before": {
"rows": 105,
"checksum": "316356979dc340fc5f141679bdee5c0d"
},
"after": {
"rows": 105,
"checksum": "39b6357efbe3142e8d0e55b5fac6a935"
}
},
"sessions": {
"before": {
"rows": 11,
"checksum": "787de58f2b0436566c2ad27161a8a759"
},
"after": {
"rows": 14,
"checksum": "ba1aa4ceaf894c62a66a4186ae4e9ddc"
}
}
},
"preserved_counts": {
"published_fiches": 29,
"relations": 28,
"geometries": 408
},
"migration_count": 0,
"content_imports": 0,
"comparison_role": "postgres_before_and_after;sameexportedsnapshotbaseline;noapplicationRLSvisibilityinference",
"writes_by_verification": 0
},
"public_delta": {
"status": "installed_delta_verified",
"served_revision": {
"commit": "d4eae917ee9c9d37f0339905a96c1e35480f324e",
"branch": "main",
"built_at": "2026-10-24T13:15:11.725340+00:00",
"manifest_sha256": "4018026aac013855f2c9baf9258ed96e1b1bf808d996e8fa8eec9458ea6b35c7"
},
"manifest_hash_matches": true,
"compiled_delta_markers": {
"public_security": [
"assets/project-dossier-PaHmg6s9.js"
],
"official_military_supplies": [
"assets/project-dossier-PaHmg6s9.js"
],
"sisa_subject_operation": [
"assets/project-dossier-PaHmg6s9.js"
],
"exempt_activity_asset_sale": [
"assets/project-dossier-PaHmg6s9.js"
],
"no_deduction_right_asset_sale": [
"assets/project-dossier-PaHmg6s9.js"
],
"excluded_deduction_asset_sale": [
"assets/project-dossier-PaHmg6s9.js"
],
"maize": [
"assets/project-dossier-PaHmg6s9.js"
],
"maize_flour": [
"assets/project-dossier-PaHmg6s9.js"
],
"rice": [
"assets/services-CVvFKfag.js",
"assets/project-dossier-PaHmg6s9.js"
],
"bread": [
"assets/project-dossier-PaHmg6s9.js"
],
"iodised_salt": [
"assets/project-dossier-PaHmg6s9.js"
],
"infant_powdered_milk": [
"assets/project-dossier-PaHmg6s9.js"
],
"wheat": [
"assets/project-dossier-PaHmg6s9.js"
],
"wheat_flour": [
"assets/project-dossier-PaHmg6s9.js"
],
"fresh_chilled_tomato": [
"assets/project-dossier-PaHmg6s9.js"
],
"potato": [
"assets/project-dossier-PaHmg6s9.js"
],
"onion": [
"assets/project-dossier-PaHmg6s9.js"
],
"frozen_horse_mackerel": [
"assets/project-dossier-PaHmg6s9.js"
],
"lighting_kerosene": [
"assets/project-dossier-PaHmg6s9.js"
],
"domestic_lpg": [
"assets/project-dossier-PaHmg6s9.js"
],
"jet_fuel": [
"assets/project-dossier-PaHmg6s9.js"
],
"eligible_bicycles": [
"assets/project-dossier-PaHmg6s9.js"
],
"condoms": [
"assets/project-dossier-PaHmg6s9.js"
],
"insecticides": [
"assets/project-dossier-PaHmg6s9.js"
],
"listed_": [
"assets/project-dossier-PaHmg6s9.js"
],
"iva-operations-l1/2": [
"assets/project-dossier-PaHmg6s9.js"
]
},
"assets": [
{
"file": "assets/services-CVvFKfag.js",
"status": 200,
"sha256": "3ce2515eb4d53e8c2da3f10fdca2bfea208d801616813e6dcd18331b7d25c048"
},
{
"file": "assets/simulation-form-CPZAFZU3.js",
"status": 200,
"sha256": "c6bcf64e60a5eeac0cafe3dc055dc5544162f21942ee08b34d51bc6d52947567"
},
{
"file": "assets/project-dossier-PaHmg6s9.js",
"status": 200,
"sha256": "9fce800b1b9805b436a1d3801f8a596ad8c879604ac193d2af6cfb546d15c7e8"
},
{
"file": "assets/project-dossier-document-CNebL8r6.js",
"status": 200,
"sha256": "242eebf5c9d9dac52eb0b53009013705058cfd62aeb0c576e4cdb6cad7619c5f"
}
],
"simulator_status": 200,
"simulator_entry": "assets/app-gy0vGuME.js",
"existing_fiscal_availability": {
"data": {
"enabled": true,
"coverage_start": "2026-01-01",
"coverage_end": "2026-12-31",
"message": "IVA geral sobre base líquida disponível; enquadramento declarado."
}
},
"synthetic_private_writes": 0,
"method": "Read-only installedrevision/manifest/newcompiledcatalogueandreaders/simulatorentry;acceptedQAproofsreused"
},
"Git": "freshfetch;branchpush;mainfastforward;noforce;existingwebhook",
"rollback_executed": false
}
}
@@ -0,0 +1,319 @@
{
"status": "installed_delta_verified_partial_L1",
"candidate": "72f4187d3bc0727ae0c5162500d5d6f26b7eed49",
"base_remote_main": "d4eae917ee9c9d37f0339905a96c1e35480f324e",
"fresh_fetch": "main d4eae917; ancestral; no concurrent advance detected; fetch again immediately before push",
"coverage": {
"G2I": {
"P019": [
"production_agriculture"
],
"P020": [
"production_forestry",
"production_forestry_opted"
],
"P021": [
"production_livestock",
"production_livestock_opted"
],
"P022": [
"production_fishing",
"production_fishing_opted"
]
},
"G2J": {
"P016": [
"fundraising_public",
"fundraising_nonprofit"
]
},
"new_branches": 5,
"new_treatments": 9,
"conditional_treatments_total": 72,
"calendar_resolution": "Civil279(c)/296 plus CIVA11(3), production-option/2; no additional branch"
},
"counts_before": {
"delivered": 29,
"QA": 5,
"functional_pending": 98,
"documentary": 1,
"total": 133
},
"counts_after_delivery": {
"delivered": 34,
"QA": 0,
"functional_pending": 98,
"documentary": 1,
"total": 133
},
"runtime_delta": [
{
"path": "resources/js/components/simulation-operations.tsx",
"sha256_LF": "94e7419ee3338c9eda6418e741d72f08334dbb3f6507dd78d2bd6690d4be6b5b"
},
{
"path": "resources/js/lib/iva-fundraising.ts",
"sha256_LF": "b58fc5733eb9f7facfe00a5f4cf0acdc98ad1e4191dbfdd1189fdf379e25e227"
},
{
"path": "resources/js/lib/iva-operations.ts",
"sha256_LF": "844d9b634afcb6a72237ca87626e5e1bcba8df3744b35063c1657a590d17b957"
},
{
"path": "resources/js/lib/iva-production-option.ts",
"sha256_LF": "2bdbb6ed52086c2c47d9f615b2cbe1c8f1370b8fdcefaa40c07b6cda8cc47526"
}
],
"activation": "Existing Git FF/webhook/installer and existing enabled simulator panel; no migrations/imports/server-rule activation/permissions/other taxes",
"QA": "G2I fe69a16e/a5ac8ca1 reused except changed calendar; calendar2frontend+API1/10;G2J2frontend+API1/10;UI/API/report;types/buildpassed;acceptedWordPDFreused",
"preservation": "29 delivered branches and previous receipts/data retained; only changed G2I opted-rule results marked historical, never rewritten",
"rollback": "Keep catalogue/readers/snapshots/results/reports; verified compatible l1-joint-readonly-rollback-20261024.patch suspends edits/calculations only; not applied. Prior release and verified fresh backup retained; no broad rollback or DB restoration executed.",
"rollback_compatibility": "git apply --check passed; not applied",
"authenticated_preflight": {
"installed": {
"status": "installed",
"commit": "d4eae917ee9c9d37f0339905a96c1e35480f324e",
"release": "/var/www/investmoz-homologacao/releases/d4eae917ee9c9d37f0339905a96c1e35480f324e-afcda0da",
"previous_release": "/var/www/investmoz-homologacao/releases/9a56d982423d0c244850f8638290a1ce8a968619-19d0ea6c",
"database_migrations": 0,
"content_imports": 0
},
"current_link": "/var/www/investmoz-homologacao/releases/d4eae917ee9c9d37f0339905a96c1e35480f324e-afcda0da",
"release_revision": {
"commit": "d4eae917ee9c9d37f0339905a96c1e35480f324e",
"branch": "main",
"built_at": "2026-10-24T13:15:11.725340+00:00",
"manifest_sha256": "4018026aac013855f2c9baf9258ed96e1b1bf808d996e8fa8eec9458ea6b35c7"
},
"service": "ExecMainStatus=0\nActiveState=inactive\nSubState=dead\n",
"configuration_keys": [
"repository",
"branch",
"target_url",
"legacy_root",
"state_root",
"release_root",
"current_link",
"shared_assets",
"php",
"schema_contract",
"ci_environment",
"postgis_image",
"test_database",
"qa_port",
"retention",
"webhook_secret_file"
],
"safe_paths": {
"repository": "nala/Investidor-V2",
"release_root": "/var/www/investmoz-homologacao/releases",
"postgis_image": "postgis/postgis@sha256:01a6a70e41e6c4467c8f55f6063555ed72db2d6662cd0d571040d42eadaeb6f6"
},
"pipeline_sha256": "adec1c17654f3a8658b83b134f1e75f95391b235738552721906c3236e388604"
},
"backup_restore": {
"backup": {
"stage": "/var/backups/investmoz-l1-g2ij-delivery-20261024/backup",
"target": {
"database": "teste_investidor",
"port": 5432
},
"tables": 174,
"files_verified": 369,
"dump_sha256": "a75cb8751146ad0a59ecd62fa13e4d9ede3fd98ad2f4ebda092b48f7c2526c32",
"files_sha256": "889fe89ec3acccfc17ace98dec9e6fb8675bfb75f69efb1ae9ce7585c50ef873",
"restore_verified": false
},
"restore": {
"restore_verified": true,
"tables_verified": 174,
"container_network": "none",
"database": "l1_g2ij_restore_20261024",
"port": 55441,
"source_dump_sha256": "a75cb8751146ad0a59ecd62fa13e4d9ede3fd98ad2f4ebda092b48f7c2526c32",
"active_database_writes": 0
}
},
"P001": "Documentary05/06only;independentoperationsnotblocked",
"L1_complete": false,
"statistics_AI": "deferred",
"served_commit": "e45a1394fa2ca8631593549b3af62093f25d9c13",
"installed_delta": "verified",
"installation": {
"backup": {
"stage": "/var/backups/investmoz-l1-g2ij-delivery-20261024/backup",
"target": {
"database": "teste_investidor",
"port": 5432
},
"tables": 174,
"files_verified": 369,
"dump_sha256": "a75cb8751146ad0a59ecd62fa13e4d9ede3fd98ad2f4ebda092b48f7c2526c32",
"files_sha256": "889fe89ec3acccfc17ace98dec9e6fb8675bfb75f69efb1ae9ce7585c50ef873",
"restore_verified": false
},
"restore": {
"restore_verified": true,
"tables_verified": 174,
"container_network": "none",
"database": "l1_g2ij_restore_20261024",
"port": 55441,
"source_dump_sha256": "a75cb8751146ad0a59ecd62fa13e4d9ede3fd98ad2f4ebda092b48f7c2526c32",
"active_database_writes": 0
},
"installer": {
"service": "ExecMainStatus=0\nActiveState=inactive\nSubState=dead\n",
"installed": {
"status": "installed",
"commit": "e45a1394fa2ca8631593549b3af62093f25d9c13",
"release": "/var/www/investmoz-homologacao/releases/e45a1394fa2ca8631593549b3af62093f25d9c13-f5f7e07d",
"previous_release": "/var/www/investmoz-homologacao/releases/d4eae917ee9c9d37f0339905a96c1e35480f324e-afcda0da",
"database_migrations": 0,
"content_imports": 0
},
"latest_report": {
"status": "installed",
"commit": "e45a1394fa2ca8631593549b3af62093f25d9c13",
"release": "/var/www/investmoz-homologacao/releases/e45a1394fa2ca8631593549b3af62093f25d9c13-f5f7e07d",
"previous_release": "/var/www/investmoz-homologacao/releases/d4eae917ee9c9d37f0339905a96c1e35480f324e-afcda0da",
"database_migrations": 0,
"content_imports": 0,
"requested_commits": [
"e45a1394fa2ca8631593549b3af62093f25d9c13"
],
"finished_at": "2026-10-24T13:51:04.874534+00:00"
},
"log_file": "1792849778512278349.log",
"summaries": [
"OK (1 test, 3106 assertions)",
"built in 25.05s",
"OK (59 tests, 317 assertions)",
"# tests 265",
"# pass 265",
"# fail 0"
],
"log_bytes": 105228
},
"protected_preservation": {
"installed": {
"status": "installed",
"commit": "e45a1394fa2ca8631593549b3af62093f25d9c13",
"release": "/var/www/investmoz-homologacao/releases/e45a1394fa2ca8631593549b3af62093f25d9c13-f5f7e07d",
"previous_release": "/var/www/investmoz-homologacao/releases/d4eae917ee9c9d37f0339905a96c1e35480f324e-afcda0da",
"database_migrations": 0,
"content_imports": 0
},
"runtime_files_verified": 4,
"persistent_files_and_env_verified": 369,
"tables_compared": 174,
"changed_tables": {
"cache": {
"before": {
"rows": 105,
"checksum": "39b6357efbe3142e8d0e55b5fac6a935"
},
"after": {
"rows": 105,
"checksum": "de9f82d4485c5358f6677efbc61c53a0"
}
},
"sessions": {
"before": {
"rows": 14,
"checksum": "ba1aa4ceaf894c62a66a4186ae4e9ddc"
},
"after": {
"rows": 15,
"checksum": "c6e69ce7f5936cefebf8b1d7b9295a15"
}
}
},
"preserved_counts": {
"published_fiches": 29,
"relations": 28,
"geometries": 408
},
"migration_count": 0,
"content_imports": 0,
"comparison_role": "postgres_before_and_after;sameexportedsnapshotbaseline;noapplicationRLSvisibilityinference",
"writes_by_verification": 0
},
"public_delta": {
"status": "installed_delta_verified",
"served_revision": {
"commit": "e45a1394fa2ca8631593549b3af62093f25d9c13",
"branch": "main",
"built_at": "2026-10-24T13:51:02.487098+00:00",
"manifest_sha256": "2f3fd204e659ac71f0e35b59365b7342d79f1460119ef34a4daa217e4b21c0af"
},
"manifest_hash_matches": true,
"compiled_delta_markers": {
"production_": [
"assets/project-dossier-CP3iqTD7.js",
"assets/services-D8gl05j7.js"
],
"agriculture": [
"assets/project-dossier-CP3iqTD7.js"
],
"forestry": [
"assets/project-dossier-CP3iqTD7.js"
],
"livestock": [
"assets/project-dossier-CP3iqTD7.js"
],
"fishing": [
"assets/project-dossier-CP3iqTD7.js"
],
"fundraising_public": [
"assets/project-dossier-CP3iqTD7.js"
],
"fundraising_nonprofit": [
"assets/project-dossier-CP3iqTD7.js",
"assets/services-D8gl05j7.js"
],
"production-option/2": [
"assets/project-dossier-CP3iqTD7.js"
],
"fundraising/1": [
"assets/project-dossier-CP3iqTD7.js"
]
},
"assets": [
{
"file": "assets/simulation-form-CPZAFZU3.js",
"status": 200,
"sha256": "c6bcf64e60a5eeac0cafe3dc055dc5544162f21942ee08b34d51bc6d52947567"
},
{
"file": "assets/project-dossier-document-RxKyJJE-.js",
"status": 200,
"sha256": "f1580c32f9b5590f65ef1caeb99bcb8838a7593837001e8f541815318bbffc65"
},
{
"file": "assets/project-dossier-CP3iqTD7.js",
"status": 200,
"sha256": "7317575f701ff3b68c5909f57bfa8b2d228fc30f3c0a8b852ebe2f98ad4431fc"
},
{
"file": "assets/services-D8gl05j7.js",
"status": 200,
"sha256": "018c16520dc0410f830de3963aa55bcf459297cd0bbebfa4562312cd2793c218"
}
],
"simulator_status": 200,
"simulator_entry": "assets/app-B5iYnxXw.js",
"existing_fiscal_availability": {
"data": {
"enabled": true,
"coverage_start": "2026-01-01",
"coverage_end": "2026-12-31",
"message": "IVA geral sobre base líquida disponível; enquadramento declarado."
}
},
"synthetic_private_writes": 0,
"method": "Read-only installedrevision/manifest/newcompiledcatalogueandreaders/simulatorentry;acceptedQAproofsreused"
},
"Git": "fresh fetch; feature push; main fast-forward; no force; existing webhook",
"rollback_executed": false
}
}
@@ -0,0 +1,391 @@
{
"status": "installed_delta_verified_partial_L1",
"base_remote_main": "e45a1394fa2ca8631593549b3af62093f25d9c13",
"fresh_fetch": "origin/main e45a1394,ancestor;fetch again immediately before main push",
"coverage": {
"G2K": {
"P008": [
"pharma_manufacturing_inputs"
]
},
"G2L": {
"P035": [
"annexI_goods"
]
},
"new_branches": 2,
"new_treatments": 2,
"documentary_rows": {
"AnexoIII": 170,
"AnexoI": 172
},
"existing_treatments_reused": "Explicit identity-preserving continuations to9(10);no new branch IDs"
},
"counts_current": {
"delivered": 36,
"QA": 0,
"functional_pending": 96,
"documentary": 1,
"total": 133
},
"counts_after_QA_and_delivery_only": {
"delivered": 36,
"QA": 0,
"functional_pending": 96,
"documentary": 1,
"total": 133
},
"runtime_delta": [
{
"path": "resources/js/components/simulation-operations.tsx",
"sha256_LF": "6e6d7b5d7f47541683dd4f32e93805b0d3068283a8ff1b3446884f5e4c626039"
},
{
"path": "resources/js/lib/iva-operations.ts",
"sha256_LF": "02e411659c84c00182c6c46f3af499f04648a8cf84911ce11ed9a21f12d48d78"
},
{
"path": "resources/js/lib/iva-pharma-annex.ts",
"sha256_LF": "dd56382b6edcced208efb03ebfc412f75e03b7180d084021ecbde1bac713ce3f"
},
{
"path": "resources/js/lib/iva-annex-i.ts",
"sha256_LF": "6dda21a66dd9399b911bc9839163a5e20f10808ac1937d3b2ca70dff3109424d"
}
],
"QA": {
"G2K": "8882dc54/1fe74256;accepted proofs reused",
"G2L": "4frontend/types/build accepted; manual Tempo reading/viewing and reported save/recover/report passage; actual saved UI payload verified and private API1/29 passed;12previousbooks preserved without recalculation.",
"review_controls": "Same-origin synthetic file save/recover/report clarified; manual passage reported by Tempo and saved file found; no Codex browser observation claimed."
},
"visual_gate": {
"origin": "http://127.0.0.1:18639",
"user_authorized": true,
"user_requested_retry": true,
"current_tool_result": "A saved user permission setting blocks this action; saved permission or managed policy denies access",
"alternate_origin_or_browser_workaround_attempted": false
},
"before_delivery_required": [],
"activation": "Existing Git fast-forward/webhook/installer and existing simulator panel;no migrations/imports/server fiscal activation/permissions/other taxes",
"rollback": "Existing l1-joint-readonly-rollback-20261024.patch passed git apply --check;not applied;keeps catalogue/readers/history/API/reports. Retain prior release and verified fresh backup before deployment;no DBrestore executed.",
"backup_restore_new_delivery": "Verified fresh backup and real isolated restore;no active restore executed.",
"homologation_unchanged": false,
"P001": "05/06only;notextended",
"L1_complete": false,
"statistics_AI": "deferred",
"G2L_candidate": "744682835a91f08aece9258380466ae746bc7353",
"G2K_candidate": "8882dc54d0973bc058b04009bdbc36c9da2cc31b",
"G2L_record": "iva_l1_g2_annex_i_code_qa_visual_pending_20261024",
"visual_verification_routes": {
"authority": "Express Tempo instruction,24/10/2026",
"manual_Tempo": {
"accepted": true,
"status": "manual_passage_reported_and_saved_payload_technically_verified",
"observations": {
"source": "Tempo, conversation24/10/2026",
"earlier_statement": "No failure seen in what was read and observed; save/recovery buttons not identified.",
"latest_statement": "ja procedi com a tua instrução pode verificar",
"scope": "User reports following the save/recover/report instructions after controls were clarified.",
"Codex_visual_observation": false,
"additional_individual_observations_invented": false
}
},
"Codex_browser": {
"accepted_after_tool_permission_review": true,
"saved_permission_not_changed_by_conversation_authorization": true
},
"scope": [
"Search/select an AnnexI position",
"Conditions and missing information",
"Save/recover and match selected position in report;continuitywhereapplicable"
],
"automatic_tests": "Already accepted;do not repeat",
"tool_block_is_portal_failure_evidence": false,
"circumvention": false
},
"G2L_completion_record": "iva_l1_g2l_manual_completion_and_actual_UI_payload_20261024",
"candidate": "da798dd1d8a017cfb20764b566661807b2ef0ffc",
"authenticated_preflight": {
"installed": {
"status": "installed",
"commit": "e45a1394fa2ca8631593549b3af62093f25d9c13",
"release": "/var/www/investmoz-homologacao/releases/e45a1394fa2ca8631593549b3af62093f25d9c13-f5f7e07d",
"previous_release": "/var/www/investmoz-homologacao/releases/d4eae917ee9c9d37f0339905a96c1e35480f324e-afcda0da",
"database_migrations": 0,
"content_imports": 0
},
"current_link": "/var/www/investmoz-homologacao/releases/e45a1394fa2ca8631593549b3af62093f25d9c13-f5f7e07d",
"release_revision": {
"commit": "e45a1394fa2ca8631593549b3af62093f25d9c13",
"branch": "main",
"built_at": "2026-10-24T13:51:02.487098+00:00",
"manifest_sha256": "2f3fd204e659ac71f0e35b59365b7342d79f1460119ef34a4daa217e4b21c0af"
},
"service": "ExecMainStatus=0\nActiveState=inactive\nSubState=dead\n",
"configuration_keys": [
"repository",
"branch",
"target_url",
"legacy_root",
"state_root",
"release_root",
"current_link",
"shared_assets",
"php",
"schema_contract",
"ci_environment",
"postgis_image",
"test_database",
"qa_port",
"retention",
"webhook_secret_file"
],
"safe_paths": {
"repository": "nala/Investidor-V2",
"release_root": "/var/www/investmoz-homologacao/releases",
"postgis_image": "postgis/postgis@sha256:01a6a70e41e6c4467c8f55f6063555ed72db2d6662cd0d571040d42eadaeb6f6"
},
"pipeline_sha256": "adec1c17654f3a8658b83b134f1e75f95391b235738552721906c3236e388604"
},
"backup_restore": {
"backup": {
"stage": "/var/backups/investmoz-l1-g2kl-delivery-20261024/backup",
"target": {
"database": "teste_investidor",
"port": 5432
},
"tables": 174,
"files_verified": 369,
"dump_sha256": "8c6d8f2745ebb3dc6883d67fb8d9810593d47ad44fb0e20859e3547044adee6c",
"files_sha256": "66d42c9053508681e8f7adfe20631396272f2fb934a69a6c79347a029fa11f78",
"restore_verified": false
},
"restore": {
"restore_verified": true,
"tables_verified": 174,
"container_network": "none",
"database": "l1_g2kl_restore_20261024",
"port": 55441,
"source_dump_sha256": "8c6d8f2745ebb3dc6883d67fb8d9810593d47ad44fb0e20859e3547044adee6c",
"active_database_writes": 0
}
},
"rollback_compatibility": "git apply --check passed on current candidate;patch not applied;catalogue/readers/history retained",
"served_commit": "ccdecbd8d74596e729f03381d3b37ca22ce5800e",
"installed_delta": "verified",
"installation": {
"backup": {
"stage": "/var/backups/investmoz-l1-g2kl-delivery-20261024/backup",
"target": {
"database": "teste_investidor",
"port": 5432
},
"tables": 174,
"files_verified": 369,
"dump_sha256": "8c6d8f2745ebb3dc6883d67fb8d9810593d47ad44fb0e20859e3547044adee6c",
"files_sha256": "66d42c9053508681e8f7adfe20631396272f2fb934a69a6c79347a029fa11f78",
"restore_verified": false
},
"restore": {
"restore_verified": true,
"tables_verified": 174,
"container_network": "none",
"database": "l1_g2kl_restore_20261024",
"port": 55441,
"source_dump_sha256": "8c6d8f2745ebb3dc6883d67fb8d9810593d47ad44fb0e20859e3547044adee6c",
"active_database_writes": 0
},
"installer": {
"service": "ExecMainStatus=0\nActiveState=inactive\nSubState=dead\n",
"installed": {
"status": "installed",
"commit": "ccdecbd8d74596e729f03381d3b37ca22ce5800e",
"release": "/var/www/investmoz-homologacao/releases/ccdecbd8d74596e729f03381d3b37ca22ce5800e-0967d766",
"previous_release": "/var/www/investmoz-homologacao/releases/e45a1394fa2ca8631593549b3af62093f25d9c13-f5f7e07d",
"database_migrations": 0,
"content_imports": 0
},
"latest_report": {
"status": "installed",
"commit": "ccdecbd8d74596e729f03381d3b37ca22ce5800e",
"release": "/var/www/investmoz-homologacao/releases/ccdecbd8d74596e729f03381d3b37ca22ce5800e-0967d766",
"previous_release": "/var/www/investmoz-homologacao/releases/e45a1394fa2ca8631593549b3af62093f25d9c13-f5f7e07d",
"database_migrations": 0,
"content_imports": 0,
"requested_commits": [
"ccdecbd8d74596e729f03381d3b37ca22ce5800e"
],
"finished_at": "2026-10-24T14:40:58.261566+00:00"
},
"log_file": "1792852768694030688.log",
"summaries": [
"OK (1 test, 3106 assertions)",
"built in 25.35s",
"OK (59 tests, 317 assertions)",
"# tests 272",
"# pass 272",
"# fail 0"
],
"log_bytes": 107426
},
"protected_preservation": {
"installed": {
"status": "installed",
"commit": "ccdecbd8d74596e729f03381d3b37ca22ce5800e",
"release": "/var/www/investmoz-homologacao/releases/ccdecbd8d74596e729f03381d3b37ca22ce5800e-0967d766",
"previous_release": "/var/www/investmoz-homologacao/releases/e45a1394fa2ca8631593549b3af62093f25d9c13-f5f7e07d",
"database_migrations": 0,
"content_imports": 0
},
"runtime_files_verified": 4,
"persistent_files_and_env_verified": 369,
"tables_compared": 174,
"changed_tables": {
"cache": {
"before": {
"rows": 105,
"checksum": "9d045636f1332b32bb65a20a35a0ffe1"
},
"after": {
"rows": 105,
"checksum": "f8fbf67b713b7dfdce6a3bacb6c46823"
}
},
"sessions": {
"before": {
"rows": 14,
"checksum": "fa2aec2278d6646c26970993447e306a"
},
"after": {
"rows": 15,
"checksum": "9c9c8b103d1429a690d8e140f1c19ad7"
}
}
},
"preserved_counts": {
"published_fiches": 29,
"relations": 28,
"geometries": 408
},
"migration_count": 0,
"content_imports": 0,
"comparison_role": "postgres_before_and_after;sameexportedsnapshotbaseline;noapplicationRLSvisibilityinference",
"writes_by_verification": 0
},
"public_delta": {
"status": "installed_delta_verified",
"served_revision": {
"commit": "ccdecbd8d74596e729f03381d3b37ca22ce5800e",
"branch": "main",
"built_at": "2026-10-24T14:40:55.681401+00:00",
"manifest_sha256": "8ee52a7b3f7c4363f10d73382d85325bbfa331c2e6e44ccd08d92e578cdf2776"
},
"manifest_hash_matches": true,
"compiled_delta_markers": {
"annexI_goods": [
"assets/project-dossier-DmOH9u9e.js",
"assets/services-zksozm3m.js"
],
"pharma_manufacturing_inputs": [
"assets/project-dossier-DmOH9u9e.js",
"assets/services-zksozm3m.js"
],
"annexI-lei22-2022/1": [
"assets/project-dossier-DmOH9u9e.js"
],
"annexIII-lei22-2022/1": [
"assets/project-dossier-DmOH9u9e.js"
],
"annexIItem": [
"assets/project-dossier-DmOH9u9e.js",
"assets/services-zksozm3m.js"
],
"pharmaAnnexItem": [
"assets/project-dossier-DmOH9u9e.js",
"assets/services-zksozm3m.js"
],
"2912.19.00": [
"assets/project-dossier-DmOH9u9e.js",
"assets/services-zksozm3m.js"
],
"8201.50.00": [
"assets/project-dossier-DmOH9u9e.js"
],
"8701.95.00": [
"assets/project-dossier-DmOH9u9e.js"
]
},
"assets": [
{
"file": "assets/project-dossier-DmOH9u9e.js",
"status": 200,
"sha256": "4cd3c0dbc4466661ce7e73dd4120fb956b9386c6e141b038e5a526cbf7424196"
},
{
"file": "assets/simulation-form-CPZAFZU3.js",
"status": 200,
"sha256": "c6bcf64e60a5eeac0cafe3dc055dc5544162f21942ee08b34d51bc6d52947567"
},
{
"file": "assets/services-zksozm3m.js",
"status": 200,
"sha256": "5b771620208247a10da9d22e78be4fc772f8c1e02afcf38a7e6a47a5cdfefd5d"
},
{
"file": "assets/project-dossier-document-BGVr7IFw.js",
"status": 200,
"sha256": "fa7e832b28fbb762872dd5df448ef20c6f2ce5bafd5226b20c31376b566a25da"
}
],
"simulator_status": 200,
"simulator_entry": "assets/app-CQEv1lby.js",
"existing_fiscal_availability": {
"data": {
"enabled": true,
"coverage_start": "2026-01-01",
"coverage_end": "2026-12-31",
"message": "IVA geral sobre base líquida disponível; enquadramento declarado."
}
},
"synthetic_private_writes": 0,
"method": "Read-only installedrevision/manifest/newcompiledcatalogueandreaders/simulatorentry;acceptedQAproofsreused"
},
"Git": "fresh fetch;feature push;main fast-forward;no force;existing webhook",
"rollback_executed": false
},
"G2L_visual_evidence": {
"method": "Verificação manual pela Tempo, autorizada expressamente na conversa;não foi observação de navegador peloCodex.",
"tool_block": "Permissão guardada/política gerida impediu o Codex de controlar a origemQA18639. Não foi alterada nem contornada.",
"manual_evidence": [
{
"statement": "conferi o SYNTHETIC QA — G2L / Anexo I",
"scope": "Abertura e leitura da páginaQA pelaTempo"
},
{
"statement": "pelo que li e observei não vi nenhuam falha mas tambem não vi nenhum botao gravação/recuperaça",
"scope": "Observação parcial semfalha noquefoivisto;gravação/recuperação ainda não conferidas"
},
{
"statement": "ja procedi com a tua instrução pode verificar",
"scope": "Confirmação pelaTempo da execução da instrução já apresentada:guardar exemploQA,recuperar gravaçãoQA eabrir relatório da gravação recuperada,após clarificação doscontrolos"
}
],
"limits": "Não se atribuem àTempo resultados individuais adicionais não descritos,nem se apresenta captura ou observação visual peloCodex. O ficheiro comprova gravação;isoladamente não comprova cliques de recuperação/abertura. Estes passos são sustentados pela comunicação daTempo.",
"technical_corroboration": {
"record": "iva_l1_g2l_manual_completion_and_actual_UI_payload_20261024",
"saved_at": "2026-10-24T14:32:44.805Z",
"saved_file_sha256": "bfa1b242671b57925d560d1b76a6065a52238f4cbd9f255b17e594384f5e0ef7",
"API_QA": "Ficheiro real→POST/GETprivado,1teste/29asserções;contexto/snapshot exactos;transacção revertida",
"report": "Mesmas funções daQA aplicadas ao snapshot real;contexto,fontes,identidades,versão evalores correspondentes"
},
"existing_references": [
"iva_l1_g2l_manual_verification_route_20261024",
"iva_l1_g2l_manual_partial_controls_20261024",
"iva_l1_g2l_manual_completion_and_actual_UI_payload_20261024",
"iva_l1_g2kl_homologation_20261024"
],
"installed_revision_check_is_visual_proof": false,
"accepted_proofs_repeated": false,
"delivery_closure_preserved": "ccdecbd8/643ba6ed"
}
}
@@ -0,0 +1,288 @@
{
"status": "installed_delta_verified_partial_L1",
"candidate": "0dc2d64b20ae3d6879e0154f5507b3fdc6031733",
"base_remote_main": "ccdecbd8d74596e729f03381d3b37ca22ce5800e",
"coverage": {
"group": "G3",
"branches": [
"P038",
"P039",
"P040",
"P041",
"P042",
"P043",
"P045"
],
"scope": "cessation2026/MZN;explicit continuity;no historical exemption/imports"
},
"counts_before": {
"delivered": 36,
"QA": 7,
"functional_pending": 89,
"documentary": 1,
"total": 133
},
"counts_after_delivery": {
"delivered": 43,
"QA": 0,
"functional_pending": 89,
"documentary": 1,
"total": 133
},
"QA": "ac948bd8/bda6d1e3;manual Tempo visual confirmation0dc2d64b;3frontend+API1/36+types/build;13frozenbooks unchanged;accepted proofs reused",
"visual_provenance": "Manual Tempo;no Codex browser observation claimed. G2L clarification908c8afc is separate from G3 confirmation0dc2d64b.",
"runtime_delta": [
{
"path": "resources/js/components/simulation-operations.tsx",
"sha256_LF": "68e0a98d9b1a3190a96d16210e1bb331c23dbbf9aaa218f973ba05dc9c90df55"
},
{
"path": "resources/js/lib/iva-operations.ts",
"sha256_LF": "5155a96101393e0dca5f183577587b9b3a9c4e3b981e8491adc0d640301bdcb3"
},
{
"path": "resources/js/lib/iva-temporary-benefits.ts",
"sha256_LF": "99bf065703db32709806475f7e8bfdf0d086cce9b15ab30434f44d8df6ed9230"
}
],
"authenticated_preflight": {
"installed": {
"status": "installed",
"commit": "ccdecbd8d74596e729f03381d3b37ca22ce5800e",
"release": "/var/www/investmoz-homologacao/releases/ccdecbd8d74596e729f03381d3b37ca22ce5800e-0967d766",
"previous_release": "/var/www/investmoz-homologacao/releases/e45a1394fa2ca8631593549b3af62093f25d9c13-f5f7e07d",
"database_migrations": 0,
"content_imports": 0
},
"current_link": "/var/www/investmoz-homologacao/releases/ccdecbd8d74596e729f03381d3b37ca22ce5800e-0967d766",
"release_revision": {
"commit": "ccdecbd8d74596e729f03381d3b37ca22ce5800e",
"branch": "main",
"built_at": "2026-10-24T14:40:55.681401+00:00",
"manifest_sha256": "8ee52a7b3f7c4363f10d73382d85325bbfa331c2e6e44ccd08d92e578cdf2776"
},
"service": "ExecMainStatus=0\nActiveState=inactive\nSubState=dead\n",
"configuration_keys": [
"repository",
"branch",
"target_url",
"legacy_root",
"state_root",
"release_root",
"current_link",
"shared_assets",
"php",
"schema_contract",
"ci_environment",
"postgis_image",
"test_database",
"qa_port",
"retention",
"webhook_secret_file"
],
"safe_paths": {
"repository": "nala/Investidor-V2",
"release_root": "/var/www/investmoz-homologacao/releases",
"postgis_image": "postgis/postgis@sha256:01a6a70e41e6c4467c8f55f6063555ed72db2d6662cd0d571040d42eadaeb6f6"
},
"pipeline_sha256": "adec1c17654f3a8658b83b134f1e75f95391b235738552721906c3236e388604"
},
"backup_restore": {
"backup": {
"stage": "/var/backups/investmoz-l1-g3-delivery-20261024/backup",
"target": {
"database": "teste_investidor",
"port": 5432
},
"tables": 174,
"files_verified": 369,
"dump_sha256": "0a9ebaa6f883abbea456f5971a35cb2081031735d56138f0d9354a9325591d7a",
"files_sha256": "ec19f952637953c1b286a5dfd5e8cef7861a0564c7d7c5a3187103fc0305a746",
"restore_verified": false
},
"restore": {
"restore_verified": true,
"tables_verified": 174,
"container_network": "none",
"database": "l1_g3_restore_20261024",
"port": 55441,
"source_dump_sha256": "0a9ebaa6f883abbea456f5971a35cb2081031735d56138f0d9354a9325591d7a",
"active_database_writes": 0
}
},
"activation": "Existing Git FF/webhook/installer;no migrations/imports/permissions/newserver fiscal rule",
"rollback": {
"patch": "docs/investmoz/simulations/l1-g3-readonly-rollback-20261024.patch",
"checked": true,
"applied": false,
"preserves": "catalogue/readers/history/reports;prior release and fresh backup retained",
"old_patch": "Earlier patch no longer applies after new helper;new compatible patch generated,old artifact preserved"
},
"L1_complete": false,
"P001": "05/06only",
"statistics_AI": "deferred",
"served_commit": "6eefe4b3322461b9a23166e2cd1235e3881765f4",
"counts_current": {
"delivered": 43,
"QA": 0,
"functional_pending": 89,
"documentary": 1,
"total": 133
},
"installation": {
"protected": {
"installed": {
"status": "installed",
"commit": "6eefe4b3322461b9a23166e2cd1235e3881765f4",
"release": "/var/www/investmoz-homologacao/releases/6eefe4b3322461b9a23166e2cd1235e3881765f4-e17c49ea",
"previous_release": "/var/www/investmoz-homologacao/releases/ccdecbd8d74596e729f03381d3b37ca22ce5800e-0967d766",
"database_migrations": 0,
"content_imports": 0
},
"runtime_files_verified": 3,
"persistent_files_and_env_verified": 369,
"tables_compared": 174,
"changed_tables": {
"cache": {
"before": {
"rows": 105,
"checksum": "7cb0825e41abb32c82bae73bb0a58da4"
},
"after": {
"rows": 105,
"checksum": "b6d05a7ee1683f104f7fceaee0a6f63f"
}
},
"sessions": {
"before": {
"rows": 17,
"checksum": "453fd7c711ddb39bfdd0105375f3df67"
},
"after": {
"rows": 18,
"checksum": "1920f0ee8d2ddf73ba225bad6a0645d3"
}
}
},
"preserved_counts": {
"published_fiches": 29,
"relations": 28,
"geometries": 408
},
"migration_count": 0,
"content_imports": 0,
"comparison_role": "postgres_before_and_after;sameexportedsnapshotbaseline;noapplicationRLSvisibilityinference",
"writes_by_verification": 0
},
"public": {
"status": "installed_delta_verified",
"served_revision": {
"commit": "6eefe4b3322461b9a23166e2cd1235e3881765f4",
"branch": "main",
"built_at": "2026-10-24T15:02:46.947668+00:00",
"manifest_sha256": "15837af27545a8691647459c00bec56b22d2e624ae9e20033d598d330d686d61"
},
"manifest_hash_matches": true,
"compiled_delta_markers": {
"temporary-benefit-cessation/1": [
"assets/project-dossier-DT-hu-tU.js"
],
"temporary_sugar": [
"assets/project-dossier-DT-hu-tU.js",
"assets/services-C3-fU-ch.js"
],
"temporary_sugar_industry_goods": [
"assets/project-dossier-DT-hu-tU.js"
],
"temporary_oils_soap": [
"assets/project-dossier-DT-hu-tU.js"
],
"temporary_oils_soap_factory": [
"assets/project-dossier-DT-hu-tU.js"
],
"temporary_oils_soap_inputs": [
"assets/project-dossier-DT-hu-tU.js"
],
"temporary_sugar_cane": [
"assets/project-dossier-DT-hu-tU.js",
"assets/services-C3-fU-ch.js"
],
"temporary_solar_inputs": [
"assets/project-dossier-DT-hu-tU.js"
],
"temporaryBenefitOrigin": [
"assets/project-dossier-DT-hu-tU.js",
"assets/services-C3-fU-ch.js"
]
},
"assets": [
{
"file": "assets/simulation-form-CPZAFZU3.js",
"status": 200,
"sha256": "c6bcf64e60a5eeac0cafe3dc055dc5544162f21942ee08b34d51bc6d52947567"
},
{
"file": "assets/project-dossier-document-CU96Nl_4.js",
"status": 200,
"sha256": "56bf3f423b6595b04c870aa8baa2118889152282d87da596f5a807bf5236cc04"
},
{
"file": "assets/project-dossier-DT-hu-tU.js",
"status": 200,
"sha256": "f8f618b305d8f76abfd193d9f73987514279e7c80160de3cfc79871bc02690f4"
},
{
"file": "assets/services-C3-fU-ch.js",
"status": 200,
"sha256": "75c042d62d3c8250b5334be1e38dd99fed88c85a04245a43a539a0c501bcbad0"
}
],
"simulator_status": 200,
"simulator_entry": "assets/app-D6KRT634.js",
"existing_fiscal_availability": {
"data": {
"enabled": true,
"coverage_start": "2026-01-01",
"coverage_end": "2026-12-31",
"message": "IVA geral sobre base líquida disponível; enquadramento declarado."
}
},
"synthetic_private_writes": 0,
"method": "Read-only installedrevision/manifest/newcompiledcatalogueandreaders/simulatorentry;acceptedQAproofsreused"
},
"installer": {
"service": "ExecMainStatus=0\nActiveState=inactive\nSubState=dead\n",
"installed": {
"status": "installed",
"commit": "6eefe4b3322461b9a23166e2cd1235e3881765f4",
"release": "/var/www/investmoz-homologacao/releases/6eefe4b3322461b9a23166e2cd1235e3881765f4-e17c49ea",
"previous_release": "/var/www/investmoz-homologacao/releases/ccdecbd8d74596e729f03381d3b37ca22ce5800e-0967d766",
"database_migrations": 0,
"content_imports": 0
},
"latest_report": {
"status": "installed",
"commit": "6eefe4b3322461b9a23166e2cd1235e3881765f4",
"release": "/var/www/investmoz-homologacao/releases/6eefe4b3322461b9a23166e2cd1235e3881765f4-e17c49ea",
"previous_release": "/var/www/investmoz-homologacao/releases/ccdecbd8d74596e729f03381d3b37ca22ce5800e-0967d766",
"database_migrations": 0,
"content_imports": 0,
"requested_commits": [
"6eefe4b3322461b9a23166e2cd1235e3881765f4"
],
"finished_at": "2026-10-24T15:02:49.533733+00:00"
},
"log_file": "1792854081964720706.log",
"summaries": [
"OK (1 test, 3106 assertions)",
"built in 25.00s",
"OK (59 tests, 317 assertions)",
"# tests 275",
"# pass 275",
"# fail 0"
],
"log_bytes": 108361
},
"rollback_executed": false
}
}
@@ -0,0 +1,19 @@
--- a/resources/js/components/simulation-operations.tsx
+++ b/resources/js/components/simulation-operations.tsx
@@ -17,6 +17,8 @@
const change=(id:string,patch:Partial<SalesOperation>)=>run(()=>save({...book,rows:book.rows.map(r=>r.id===id?{...r,...patch}:r)}));
const continueTemporary=(id:string,target:string)=>run(()=>save({...book,rows:book.rows.map(row=>row.id===id?continueTemporaryOperation(row,target):row)}));
return <section aria-label="Operações IVA por oportunidade" className="space-y-3 rounded border p-3">
+ <p role="status">Novos cálculos temporariamente suspensos; resultados guardados e relatórios disponíveis.</p>
+ <fieldset disabled>
<h4 className="font-semibold">Operações de IVA — enquadramento das vendas</h4>
<p>Oportunidade {String(draft.context_opportunity||'entrada geral')}; moeda original {book.currency||'por indicar'}. Cobertura2026/MZN. Reutilize as vendas e complete apenas o enquadramento. Este bloco classifica as operações; não substitui nem soma novamente a execução mensal geral acima.</p>
<p>Uma empresa pode ter operações com tratamentos diferentes. Os valores são projecções sob pressupostos declarados, sem certificar facturas, reconhecer créditos ou submeter uma declaração à AT.</p>
@@ -82,6 +84,7 @@
{book.periods.map(p=><label className="block" key={p.period}><input type="checkbox" checked={p.complete} onChange={e=>run(()=>save({...book,periods:book.periods.map(v=>v.period===p.period?{...v,complete:e.target.checked}:v)}))}/> {p.period}: incluí todas as operações deste período; lista vazia significa ausência expressamente confirmada.</label>)}
<p>Limites: outras isenções/bases especiais e correspondência do campo06 permanecem por delimitar. IVA incluído a5% conserva a fracção exacta e apresenta um decimal a6casas; a aproximação de apresentação não constitui regra declarativa. O desconhecido nunca é assumido como zero.</p>
<button type="button" disabled={!book.periods.length} className="rounded bg-emerald-800 p-2 text-white disabled:opacity-50" onClick={()=>run(()=>save(recordSales(draft,book)))}>Calcular e guardar operações IVA</button>
+ </fieldset>
{book.result&&<><p role="status">{salesCurrent(draft,book)?'Resultado correspondente às entradas.':'Resultado histórico conservado; reveja as alterações antes de recalcular.'}</p><dl>{salesReportRows(draft).map(([,label,value,origin],index)=><div className="break-inside-avoid border-t py-2" key={index}><dt className="font-semibold">{label}</dt><dd>{value}<small className="block">{origin}</small></dd></div>)}</dl></>}
</section>;
}
@@ -0,0 +1,270 @@
{
"status": "installed_delta_verified_partial_L1",
"candidate": "7b54efb0fca9aae0adf174169711cd1f452fe1fb",
"base_remote_main": "6eefe4b3322461b9a23166e2cd1235e3881765f4",
"coverage": {
"group": "G4A",
"branches": {
"P074": "export_railway_cfm",
"P075": "export_international_passengers",
"P076": "export_work_on_movables",
"P077": "export_gold_bom",
"P079": "export_packaging"
},
"scope": "2026/MZN/05;statutory conditions and explicit evidence/projection assumptions;no automatic input deduction/ATsubmission"
},
"counts_before": {
"delivered": 43,
"QA": 5,
"functional_pending": 84,
"documentary": 1,
"total": 133
},
"counts_after_delivery": {
"delivered": 48,
"QA": 0,
"functional_pending": 84,
"documentary": 1,
"total": 133
},
"QA": "0f0d2e56/7a58fa24;manual Tempo visual confirmation7b54efb0;3frontend+API1/36+types/build;14frozenbooks unchanged;accepted proofs reused",
"visual_provenance": "Manual Tempo;no Codex browser observation;last saved price-basis edit preserved,prior result historical;no automatic recalculation.",
"runtime_delta": [
{
"path": "resources/js/lib/iva-export-operations.ts",
"sha256_LF": "3e9927aa637db678a558beb80bf7a326afd6b010e7ab5117aacd7e82a2c52600"
},
{
"path": "resources/js/lib/iva-operations.ts",
"sha256_LF": "e3ae2cbecd823fc03cd019cfe721cb20ba03ed51c7d0ec2680b55570b0bc7f10"
}
],
"authenticated_preflight": {
"installed": {
"status": "installed",
"commit": "6eefe4b3322461b9a23166e2cd1235e3881765f4",
"release": "/var/www/investmoz-homologacao/releases/6eefe4b3322461b9a23166e2cd1235e3881765f4-e17c49ea",
"previous_release": "/var/www/investmoz-homologacao/releases/ccdecbd8d74596e729f03381d3b37ca22ce5800e-0967d766",
"database_migrations": 0,
"content_imports": 0
},
"current_link": "/var/www/investmoz-homologacao/releases/6eefe4b3322461b9a23166e2cd1235e3881765f4-e17c49ea",
"release_revision": {
"commit": "6eefe4b3322461b9a23166e2cd1235e3881765f4",
"branch": "main",
"built_at": "2026-10-24T15:02:46.947668+00:00",
"manifest_sha256": "15837af27545a8691647459c00bec56b22d2e624ae9e20033d598d330d686d61"
},
"service": "ExecMainStatus=0\nActiveState=inactive\nSubState=dead\n",
"configuration_keys": [
"repository",
"branch",
"target_url",
"legacy_root",
"state_root",
"release_root",
"current_link",
"shared_assets",
"php",
"schema_contract",
"ci_environment",
"postgis_image",
"test_database",
"qa_port",
"retention",
"webhook_secret_file"
],
"safe_paths": {
"repository": "nala/Investidor-V2",
"release_root": "/var/www/investmoz-homologacao/releases",
"postgis_image": "postgis/postgis@sha256:01a6a70e41e6c4467c8f55f6063555ed72db2d6662cd0d571040d42eadaeb6f6"
},
"pipeline_sha256": "adec1c17654f3a8658b83b134f1e75f95391b235738552721906c3236e388604"
},
"backup_restore": {
"backup": {
"stage": "/var/backups/investmoz-l1-g4a-delivery-20261024/backup",
"target": {
"database": "teste_investidor",
"port": 5432
},
"tables": 174,
"files_verified": 369,
"dump_sha256": "a8ada17d7faf38a81ef324064ba3f64d4a65e6040a3381b81cd2109d8d7664b9",
"files_sha256": "e32d2ad5d5fc9a8a65d4010ec9d658f71d120409b5eaf31e0f2de4d4c9d5405f",
"restore_verified": false
},
"restore": {
"restore_verified": true,
"tables_verified": 174,
"container_network": "none",
"database": "l1_g4a_restore_20261024",
"port": 55441,
"source_dump_sha256": "a8ada17d7faf38a81ef324064ba3f64d4a65e6040a3381b81cd2109d8d7664b9",
"active_database_writes": 0
}
},
"activation": "Existing Git FF/webhook/installer;no migrations/imports/permissions/newserver fiscal rule",
"rollback": {
"patch": "docs/investmoz/simulations/l1-g3-readonly-rollback-20261024.patch",
"checked": true,
"applied": false,
"preserves": "catalogue/readers/history/reports;prior release and fresh backup retained"
},
"regulatory_followup": "Official announcement30/09/2026 inventoried separately;not treated as published decree or rule activation;documentary comparison remains specific future work",
"L1_complete": false,
"P001": "05/06only",
"statistics_AI": "deferred",
"served_commit": "b898955603eb7698ab10f4c4ab4115bffd80b7b2",
"counts_current": {
"delivered": 48,
"QA": 0,
"functional_pending": 84,
"documentary": 1,
"total": 133
},
"installation": {
"protected": {
"installed": {
"status": "installed",
"commit": "b898955603eb7698ab10f4c4ab4115bffd80b7b2",
"release": "/var/www/investmoz-homologacao/releases/b898955603eb7698ab10f4c4ab4115bffd80b7b2-55ab681a",
"previous_release": "/var/www/investmoz-homologacao/releases/6eefe4b3322461b9a23166e2cd1235e3881765f4-e17c49ea",
"database_migrations": 0,
"content_imports": 0
},
"runtime_files_verified": 2,
"persistent_files_and_env_verified": 369,
"tables_compared": 174,
"changed_tables": {
"cache": {
"before": {
"rows": 105,
"checksum": "e2ee1520f58e0600f3f2ae64dee97baa"
},
"after": {
"rows": 105,
"checksum": "9f7ac1ea1ff1adf7db54e32f15d8a4f8"
}
},
"sessions": {
"before": {
"rows": 20,
"checksum": "28b47ffbc97aa8265bdf40d6658deaa0"
},
"after": {
"rows": 21,
"checksum": "b08ed52e696c3a91c4e1b889efad552a"
}
}
},
"preserved_counts": {
"published_fiches": 29,
"relations": 28,
"geometries": 408
},
"migration_count": 0,
"content_imports": 0,
"comparison_role": "postgres_before_and_after;sameexportedsnapshotbaseline;noapplicationRLSvisibilityinference",
"writes_by_verification": 0
},
"public": {
"status": "installed_delta_verified",
"served_revision": {
"commit": "b898955603eb7698ab10f4c4ab4115bffd80b7b2",
"branch": "main",
"built_at": "2026-10-24T15:20:59.537796+00:00",
"manifest_sha256": "846e0a05a6ed579d7f9978dc8db94e2e047fecc1c2dc489e55c0716eb75156a5"
},
"manifest_hash_matches": true,
"compiled_delta_markers": {
"export-direct-operations/1": [
"assets/project-dossier-Rt7qSc3z.js"
],
"export_railway_cfm": [
"assets/project-dossier-Rt7qSc3z.js"
],
"export_international_passengers": [
"assets/project-dossier-Rt7qSc3z.js"
],
"export_work_on_movables": [
"assets/project-dossier-Rt7qSc3z.js"
],
"export_gold_bom": [
"assets/project-dossier-Rt7qSc3z.js"
],
"export_packaging": [
"assets/project-dossier-Rt7qSc3z.js"
]
},
"assets": [
{
"file": "assets/services-eQvgi8ww.js",
"status": 200,
"sha256": "1d94e9315eab7d2e2e00c29bf9ae3bef1eadc86faaff73c163daea40709576c0"
},
{
"file": "assets/simulation-form-CPZAFZU3.js",
"status": 200,
"sha256": "c6bcf64e60a5eeac0cafe3dc055dc5544162f21942ee08b34d51bc6d52947567"
},
{
"file": "assets/project-dossier-document-BeYOfJX9.js",
"status": 200,
"sha256": "1f68d9c7de6aff36a051177bf11744a75411560cfe5e8af2d18e52bb4d226d70"
},
{
"file": "assets/project-dossier-Rt7qSc3z.js",
"status": 200,
"sha256": "3ad22a0458da55242ff4d3e88cc22461e5ec6c0f0aadd452936d50a999558a68"
}
],
"simulator_status": 200,
"simulator_entry": "assets/app-BEf0yjMF.js",
"existing_fiscal_availability": {
"data": {
"enabled": true,
"coverage_start": "2026-01-01",
"coverage_end": "2026-12-31",
"message": "IVA geral sobre base líquida disponível; enquadramento declarado."
}
},
"synthetic_private_writes": 0,
"method": "Read-only installedrevision/manifest/newcompiledcatalogueandreaders/simulatorentry;acceptedQAproofsreused"
},
"installer": {
"service": "ExecMainStatus=0\nActiveState=inactive\nSubState=dead\n",
"installed": {
"status": "installed",
"commit": "b898955603eb7698ab10f4c4ab4115bffd80b7b2",
"release": "/var/www/investmoz-homologacao/releases/b898955603eb7698ab10f4c4ab4115bffd80b7b2-55ab681a",
"previous_release": "/var/www/investmoz-homologacao/releases/6eefe4b3322461b9a23166e2cd1235e3881765f4-e17c49ea",
"database_migrations": 0,
"content_imports": 0
},
"latest_report": {
"status": "installed",
"commit": "b898955603eb7698ab10f4c4ab4115bffd80b7b2",
"release": "/var/www/investmoz-homologacao/releases/b898955603eb7698ab10f4c4ab4115bffd80b7b2-55ab681a",
"previous_release": "/var/www/investmoz-homologacao/releases/6eefe4b3322461b9a23166e2cd1235e3881765f4-e17c49ea",
"database_migrations": 0,
"content_imports": 0,
"requested_commits": [
"b898955603eb7698ab10f4c4ab4115bffd80b7b2"
],
"finished_at": "2026-10-24T15:21:02.478696+00:00"
},
"log_file": "1792855174037587994.log",
"summaries": [
"OK (1 test, 3106 assertions)",
"built in 25.42s",
"OK (59 tests, 317 assertions)",
"# tests 278",
"# pass 278",
"# fail 0"
],
"log_bytes": 109100
},
"rollback_executed": false
}
}
@@ -0,0 +1,266 @@
{
"status": "installed_delta_verified_partial_L1",
"candidate": "f946364b",
"QA_record": "0b0e002d",
"Git_preparation_head": "0b0e002d1573c3da838a8a4ea296c7a9094acef6",
"fresh_remote_main": "b898955603eb7698ab10f4c4ab4115bffd80b7b2",
"ancestry": "ancestor;normal nonforce push only after authenticated preflight and fresh backup/restore",
"coverage": {
"group": "G4B",
"branches": {
"P065": [
"international_ship_operations"
],
"P066": [
"international_aircraft_operations"
],
"P068": [
"international_ship_direct_services",
"international_aircraft_direct_services"
]
},
"branch_count": 3,
"treatment_count": 4,
"scope": "2026/MZN/05;eligible vessel/aircraft operations and direct needs services;no supplies/input deduction/ATsubmission"
},
"runtime_delta": [
{
"path": "resources/js/lib/iva-international-assets.ts",
"sha256_LF": "fa99cf40622d8a6aaea4e3078d6c9e41d26a4a2bda5898f5bd114aa4221eaa1c"
},
{
"path": "resources/js/lib/iva-operations.ts",
"sha256_LF": "795e07a1a9b81372c3124b037d6df9626501aafcd7224290bbac2b8ec44f6d9b"
}
],
"counts_current": {
"delivered": 51,
"QA": 0,
"functional_pending": 81,
"documentary": 1,
"total": 133
},
"counts_after_delivery_only": {
"delivered": 51,
"QA": 0,
"functional_pending": 81,
"documentary": 1,
"total": 133
},
"proofs": "3frontend/APIQA1/35/types/build;15previousbooks unchanged;manual Tempo visual0b0e002d;accepted proofs reused,no new browser verification required",
"rollback": "l1-g3-readonly-rollback-20261024.patch checked on current candidate,not applied;preserves catalogue/readers/history/reports;retain prior release and verified new backup",
"activation": "Existing Git FF/webhook/installer;no migrations/imports/permission changes/server fiscal activation",
"authenticated_destination": "Fresh read confirmed b8989556;installer inactive",
"new_backup_restore": "Verified fresh backup and real isolated restore,no active restore performed",
"served_revision_and_delta": "verified",
"P001": "05/06only",
"L1_complete": false,
"statistics_AI": "deferred",
"authenticated_preflight": {
"installed": {
"status": "installed",
"commit": "b898955603eb7698ab10f4c4ab4115bffd80b7b2",
"release": "/var/www/investmoz-homologacao/releases/b898955603eb7698ab10f4c4ab4115bffd80b7b2-55ab681a",
"previous_release": "/var/www/investmoz-homologacao/releases/6eefe4b3322461b9a23166e2cd1235e3881765f4-e17c49ea",
"database_migrations": 0,
"content_imports": 0
},
"current_link": "/var/www/investmoz-homologacao/releases/b898955603eb7698ab10f4c4ab4115bffd80b7b2-55ab681a",
"release_revision": {
"commit": "b898955603eb7698ab10f4c4ab4115bffd80b7b2",
"branch": "main",
"built_at": "2026-10-24T15:20:59.537796+00:00",
"manifest_sha256": "846e0a05a6ed579d7f9978dc8db94e2e047fecc1c2dc489e55c0716eb75156a5"
},
"service": "ExecMainStatus=0\nActiveState=inactive\nSubState=dead\n",
"configuration_keys": [
"repository",
"branch",
"target_url",
"legacy_root",
"state_root",
"release_root",
"current_link",
"shared_assets",
"php",
"schema_contract",
"ci_environment",
"postgis_image",
"test_database",
"qa_port",
"retention",
"webhook_secret_file"
],
"safe_paths": {
"repository": "nala/Investidor-V2",
"release_root": "/var/www/investmoz-homologacao/releases",
"postgis_image": "postgis/postgis@sha256:01a6a70e41e6c4467c8f55f6063555ed72db2d6662cd0d571040d42eadaeb6f6"
},
"pipeline_sha256": "adec1c17654f3a8658b83b134f1e75f95391b235738552721906c3236e388604"
},
"backup_restore": {
"backup": {
"stage": "/var/backups/investmoz-l1-g4b-delivery-20261024/backup",
"target": {
"database": "teste_investidor",
"port": 5432
},
"tables": 174,
"files_verified": 369,
"dump_sha256": "946e9ebc067932184a8db32e1d469edada1c0fd52eec5cabd97958b528bee060",
"files_sha256": "37d5efc4d7b4db3f2bb34bd69ddb8377c26e15fb35f1d95eb512e4ae7aa14962",
"restore_verified": false
},
"restore": {
"restore_verified": true,
"tables_verified": 174,
"container_network": "none",
"database": "l1_g4b_restore_20261024",
"port": 55441,
"source_dump_sha256": "946e9ebc067932184a8db32e1d469edada1c0fd52eec5cabd97958b528bee060",
"active_database_writes": 0
}
},
"served_commit": "a153d0782f0f1f5a553a2c6d7106bc35059a170b",
"installation": {
"protected": {
"installed": {
"status": "installed",
"commit": "a153d0782f0f1f5a553a2c6d7106bc35059a170b",
"release": "/var/www/investmoz-homologacao/releases/a153d0782f0f1f5a553a2c6d7106bc35059a170b-789a22ef",
"previous_release": "/var/www/investmoz-homologacao/releases/b898955603eb7698ab10f4c4ab4115bffd80b7b2-55ab681a",
"database_migrations": 0,
"content_imports": 0
},
"runtime_files_verified": 2,
"persistent_files_and_env_verified": 369,
"tables_compared": 174,
"changed_tables": {
"cache": {
"before": {
"rows": 105,
"checksum": "1d9a40d14abc8a507b9f21c53214cab3"
},
"after": {
"rows": 105,
"checksum": "4ac1b3b4c92159a6c6d5b2001b33c281"
}
},
"sessions": {
"before": {
"rows": 23,
"checksum": "3416544d03e316d171c3c5b4ef17f76d"
},
"after": {
"rows": 24,
"checksum": "5c130a5a49411a488f3dd2e04a3ebf30"
}
}
},
"preserved_counts": {
"published_fiches": 29,
"relations": 28,
"geometries": 408
},
"migration_count": 0,
"content_imports": 0,
"comparison_role": "postgres_before_and_after;sameexportedsnapshotbaseline;noapplicationRLSvisibilityinference",
"writes_by_verification": 0
},
"public": {
"status": "installed_delta_verified",
"served_revision": {
"commit": "a153d0782f0f1f5a553a2c6d7106bc35059a170b",
"branch": "main",
"built_at": "2026-10-24T15:42:16.426339+00:00",
"manifest_sha256": "ae95aa3000f8861d3a092026b04fd18dff05c7e1955f99f7660e18b945e32f15"
},
"manifest_hash_matches": true,
"compiled_delta_markers": {
"international-assets/1": [
"assets/project-dossier-DTxHeV9m.js"
],
"international_ship_operations": [
"assets/project-dossier-DTxHeV9m.js"
],
"international_aircraft_operations": [
"assets/project-dossier-DTxHeV9m.js"
],
"international_ship_direct_services": [
"assets/project-dossier-DTxHeV9m.js"
],
"international_aircraft_direct_services": [
"assets/project-dossier-DTxHeV9m.js"
]
},
"assets": [
{
"file": "assets/simulation-form-CPZAFZU3.js",
"status": 200,
"sha256": "c6bcf64e60a5eeac0cafe3dc055dc5544162f21942ee08b34d51bc6d52947567"
},
{
"file": "assets/project-dossier-DTxHeV9m.js",
"status": 200,
"sha256": "d1db999b1c04537d77ba5613230a9fb0e4cbc6ce06bc5346371bfbb65b98339f"
},
{
"file": "assets/services-Dy0KLLRZ.js",
"status": 200,
"sha256": "e942686d95f79fb4a5b00f670db08f3b70078aa5de1b46eb01c66e3de93149b5"
},
{
"file": "assets/project-dossier-document-DtAisp01.js",
"status": 200,
"sha256": "804ac2e496efeb7c4fc8150295ca8df2c736ec8f38469382ca658f65835fff5c"
}
],
"simulator_status": 200,
"simulator_entry": "assets/app-qEH7_IO_.js",
"existing_fiscal_availability": {
"data": {
"enabled": true,
"coverage_start": "2026-01-01",
"coverage_end": "2026-12-31",
"message": "IVA geral sobre base líquida disponível; enquadramento declarado."
}
},
"synthetic_private_writes": 0,
"method": "Read-only installedrevision/manifest/newcompiledcatalogueandreaders/simulatorentry;acceptedQAproofsreused"
},
"installer": {
"service": "ExecMainStatus=0\nActiveState=inactive\nSubState=dead\n",
"installed": {
"status": "installed",
"commit": "a153d0782f0f1f5a553a2c6d7106bc35059a170b",
"release": "/var/www/investmoz-homologacao/releases/a153d0782f0f1f5a553a2c6d7106bc35059a170b-789a22ef",
"previous_release": "/var/www/investmoz-homologacao/releases/b898955603eb7698ab10f4c4ab4115bffd80b7b2-55ab681a",
"database_migrations": 0,
"content_imports": 0
},
"latest_report": {
"status": "installed",
"commit": "a153d0782f0f1f5a553a2c6d7106bc35059a170b",
"release": "/var/www/investmoz-homologacao/releases/a153d0782f0f1f5a553a2c6d7106bc35059a170b-789a22ef",
"previous_release": "/var/www/investmoz-homologacao/releases/b898955603eb7698ab10f4c4ab4115bffd80b7b2-55ab681a",
"database_migrations": 0,
"content_imports": 0,
"requested_commits": [
"a153d0782f0f1f5a553a2c6d7106bc35059a170b"
],
"finished_at": "2026-10-24T15:42:18.840229+00:00"
},
"log_file": "1792856451333116729.log",
"summaries": [
"OK (1 test, 3106 assertions)",
"built in 25.53s",
"OK (59 tests, 317 assertions)",
"# tests 281",
"# pass 281",
"# fail 0"
],
"log_bytes": 110076
},
"rollback_executed": false
}
}
@@ -0,0 +1,263 @@
{
"status": "installed_delta_verified_partial_L1",
"candidate": "b1c8e0e3",
"QA_record": "2fccbc8ee8d0ff687c9d49a54cf2972546182f3a",
"fresh_remote_main": "a153d0782f0f1f5a553a2c6d7106bc35059a170b",
"coverage": {
"group": "G4C",
"branches": {
"P072": "export_customs_related_services",
"P073": "export_dispatch_services",
"P078": "export_disclosed_intermediation"
},
"branch_count": 3,
"treatment_count": 3,
"scope": "2026/MZN/05; direct customs-related services, dispatch abroad, disclosed intermediation; own service territoriality identified"
},
"runtime_delta": [
{
"path": "resources/js/components/simulation-operations.tsx",
"sha256_LF": "284cb1bac2a2c5646d9f05c0503a57c568079f75081b6cf0cff98747d8564581"
},
{
"path": "resources/js/lib/iva-export-services.ts",
"sha256_LF": "090de228fc5563de98e0c4c3e1646804b05d71a84603d6d42e63b7cebfa32301"
},
{
"path": "resources/js/lib/iva-operations.ts",
"sha256_LF": "8c934a9c3126fc8e6cac005bae00e081fcf8a6d184cf9370757e3aab73995ee3"
}
],
"counts_current": {
"delivered": 54,
"QA": 0,
"functional_pending": 78,
"documentary": 1,
"total": 133
},
"counts_after_delivery_only": {
"delivered": 54,
"QA": 0,
"functional_pending": 78,
"documentary": 1,
"total": 133
},
"proofs": "4frontend;APIQA1/39;16priorbooks intact/current;types/build;Tempo manual visual reply verificada;no accepted proof repeated",
"rollback": "l1-g3-readonly-rollback-20261024.patch checked on G4C candidate, not applied; retains readers/history/reports; previous release and fresh verified backup retained",
"activation": "Existing Git normal FF/webhook/installer; no migrations/imports/permission changes or formal fiscal activation",
"authenticated_preflight_file": "outputs/iva-l1-g4-services-20261024/destination-preflight.txt",
"backup_restore": {
"backup": {
"stage": "/var/backups/investmoz-l1-g4c-delivery-20261024/backup",
"target": {
"database": "teste_investidor",
"port": 5432
},
"tables": 174,
"files_verified": 369,
"dump_sha256": "41dd7cb9e858e4398e23950e9e34289014912f67ad55b9f7ae9f14f94b03584b",
"files_sha256": "58d984f98e2da29ee269a9da91085680c9e8e7e557c65fe4e963d1f871a63a54",
"restore_verified": false
},
"restore": {
"restore_verified": true,
"tables_verified": 174,
"container_network": "none",
"database": "l1_g4c_restore_20261024",
"port": 55441,
"source_dump_sha256": "41dd7cb9e858e4398e23950e9e34289014912f67ad55b9f7ae9f14f94b03584b",
"active_database_writes": 0
}
},
"served_revision_and_delta": "verified",
"P001": "05/06 only",
"L1_complete": false,
"statistics_AI": "deferred",
"authenticated_preflight": {
"installed": {
"status": "installed",
"commit": "a153d0782f0f1f5a553a2c6d7106bc35059a170b",
"release": "/var/www/investmoz-homologacao/releases/a153d0782f0f1f5a553a2c6d7106bc35059a170b-789a22ef",
"previous_release": "/var/www/investmoz-homologacao/releases/b898955603eb7698ab10f4c4ab4115bffd80b7b2-55ab681a",
"database_migrations": 0,
"content_imports": 0
},
"current_link": "/var/www/investmoz-homologacao/releases/a153d0782f0f1f5a553a2c6d7106bc35059a170b-789a22ef",
"release_revision": {
"commit": "a153d0782f0f1f5a553a2c6d7106bc35059a170b",
"branch": "main",
"built_at": "2026-10-24T15:42:16.426339+00:00",
"manifest_sha256": "ae95aa3000f8861d3a092026b04fd18dff05c7e1955f99f7660e18b945e32f15"
},
"service": "ExecMainStatus=0\nActiveState=inactive\nSubState=dead\n",
"configuration_keys": [
"repository",
"branch",
"target_url",
"legacy_root",
"state_root",
"release_root",
"current_link",
"shared_assets",
"php",
"schema_contract",
"ci_environment",
"postgis_image",
"test_database",
"qa_port",
"retention",
"webhook_secret_file"
],
"safe_paths": {
"repository": "nala/Investidor-V2",
"release_root": "/var/www/investmoz-homologacao/releases",
"postgis_image": "postgis/postgis@sha256:01a6a70e41e6c4467c8f55f6063555ed72db2d6662cd0d571040d42eadaeb6f6"
},
"pipeline_sha256": "adec1c17654f3a8658b83b134f1e75f95391b235738552721906c3236e388604"
},
"authenticated_destination": "Fresh read confirmed a153d078; installer inactive",
"new_backup_restore": "Verified fresh backup and real isolated restore, no active restore performed",
"served_commit": "679203d4b13cd5b88ab05a0da539c359c37cc426",
"installation": {
"protected": {
"installed": {
"status": "installed",
"commit": "679203d4b13cd5b88ab05a0da539c359c37cc426",
"release": "/var/www/investmoz-homologacao/releases/679203d4b13cd5b88ab05a0da539c359c37cc426-6ad3a32e",
"previous_release": "/var/www/investmoz-homologacao/releases/a153d0782f0f1f5a553a2c6d7106bc35059a170b-789a22ef",
"database_migrations": 0,
"content_imports": 0
},
"runtime_files_verified": 3,
"persistent_files_and_env_verified": 369,
"tables_compared": 174,
"changed_tables": {
"cache": {
"before": {
"rows": 105,
"checksum": "0fb368359b09686e698bb76c130bec32"
},
"after": {
"rows": 105,
"checksum": "a1a597d8371e7a308d133b1374ddc3fa"
}
},
"sessions": {
"before": {
"rows": 26,
"checksum": "e335b7f5c76ce5d198e96a1d0736ee13"
},
"after": {
"rows": 15,
"checksum": "d8d7871c3369ade4d97c078a5d67899f"
}
}
},
"preserved_counts": {
"published_fiches": 29,
"relations": 28,
"geometries": 408
},
"migration_count": 0,
"content_imports": 0,
"comparison_role": "postgres_before_and_after;sameexportedsnapshotbaseline;noapplicationRLSvisibilityinference",
"writes_by_verification": 0
},
"public": {
"status": "installed_delta_verified",
"served_revision": {
"commit": "679203d4b13cd5b88ab05a0da539c359c37cc426",
"branch": "main",
"built_at": "2026-10-24T15:58:35.074611+00:00",
"manifest_sha256": "7b37d131d7b9564d901d8fc21407a759fcded9ba734c3757ce0fda5c00cc5c56"
},
"manifest_hash_matches": true,
"compiled_delta_markers": {
"export-linked-services/1": [
"assets/project-dossier-B13GvS2h.js"
],
"export_customs_related_services": [
"assets/project-dossier-B13GvS2h.js"
],
"export_dispatch_services": [
"assets/project-dossier-B13GvS2h.js"
],
"export_disclosed_intermediation": [
"assets/project-dossier-B13GvS2h.js"
],
"relatedExport": [
"assets/project-dossier-B13GvS2h.js",
"assets/services-T9xhkEbY.js"
]
},
"assets": [
{
"file": "assets/project-dossier-document-D3wD6GVC.js",
"status": 200,
"sha256": "f785b98c98fa31f087cfe4de205ff24d888b15c0d9aa7e76a1a03c8faa1afb83"
},
{
"file": "assets/project-dossier-B13GvS2h.js",
"status": 200,
"sha256": "1746a5eed08eb3cc85c98324ae5c60cea44ef9878e9e3aa495eb2d642fe0f0fa"
},
{
"file": "assets/services-T9xhkEbY.js",
"status": 200,
"sha256": "c6ffdcf297a76cf91dda66c5ca3ec338d36d638ddf59992c0e1d245f12551286"
},
{
"file": "assets/simulation-form-CPZAFZU3.js",
"status": 200,
"sha256": "c6bcf64e60a5eeac0cafe3dc055dc5544162f21942ee08b34d51bc6d52947567"
}
],
"simulator_status": 200,
"simulator_entry": "assets/app-CKbcQpAl.js",
"existing_fiscal_availability": {
"data": {
"enabled": true,
"coverage_start": "2026-01-01",
"coverage_end": "2026-12-31",
"message": "IVA geral sobre base líquida disponível; enquadramento declarado."
}
},
"synthetic_private_writes": 0,
"method": "Read-only installedrevision/manifest/newcompiledcatalogueandreaders/simulatorentry;acceptedQAproofsreused"
},
"installer": {
"service": "ExecMainStatus=0\nActiveState=inactive\nSubState=dead\n",
"installed": {
"status": "installed",
"commit": "679203d4b13cd5b88ab05a0da539c359c37cc426",
"release": "/var/www/investmoz-homologacao/releases/679203d4b13cd5b88ab05a0da539c359c37cc426-6ad3a32e",
"previous_release": "/var/www/investmoz-homologacao/releases/a153d0782f0f1f5a553a2c6d7106bc35059a170b-789a22ef",
"database_migrations": 0,
"content_imports": 0
},
"latest_report": {
"status": "installed",
"commit": "679203d4b13cd5b88ab05a0da539c359c37cc426",
"release": "/var/www/investmoz-homologacao/releases/679203d4b13cd5b88ab05a0da539c359c37cc426-6ad3a32e",
"previous_release": "/var/www/investmoz-homologacao/releases/a153d0782f0f1f5a553a2c6d7106bc35059a170b-789a22ef",
"database_migrations": 0,
"content_imports": 0,
"requested_commits": [
"679203d4b13cd5b88ab05a0da539c359c37cc426"
],
"finished_at": "2026-10-24T15:58:37.723730+00:00"
},
"log_file": "1792857429090761953.log",
"summaries": [
"OK (1 test, 3106 assertions)",
"built in 24.89s",
"OK (59 tests, 317 assertions)",
"# tests 285",
"# pass 285",
"# fail 0"
],
"log_bytes": 111289
},
"rollback_executed": false
}
}
@@ -0,0 +1,273 @@
{
"status": "installed_delta_verified_partial_L1",
"candidate": "8df721ac",
"QA_record": "40a4ddcb",
"fresh_remote_main": "679203d4b13cd5b88ab05a0da539c359c37cc426",
"coverage": {
"group": "G4D",
"branches": {
"P062": "onboard_seagoing_ship",
"P063": "onboard_rescue_coastal_ship",
"P064": "onboard_departing_warship",
"P067": "onboard_international_aircraft"
},
"branch_count": 4,
"treatment_count": 4,
"scope": "2026/MZN/05; direct exemption under identified conditions; explicit13(2–3) categories/exclusions; no automatic beverage liquidation/deduction/refund"
},
"runtime_delta": [
{
"path": "resources/js/components/simulation-operations.tsx",
"sha256_LF": "a67899e90f72d0b26d93b4f4c666f3f1fd0ed9bd1e47970d1a570b2fe132650c"
},
{
"path": "resources/js/lib/iva-onboard-supplies.ts",
"sha256_LF": "2ae4378998ca4d7f4759155f589b5b7c4f25090512b016211976c9a7c700bde9"
},
{
"path": "resources/js/lib/iva-operations.ts",
"sha256_LF": "eec82e67b2025a1d1738b9d2a41ef3ea7e1a2a17f12b145f02eebef62e4f6b26"
}
],
"counts_current": {
"delivered": 58,
"QA": 0,
"functional_pending": 74,
"documentary": 1,
"total": 133
},
"counts_after_delivery_only": {
"delivered": 58,
"QA": 0,
"functional_pending": 74,
"documentary": 1,
"total": 133
},
"proofs": "4frontend;APIQA1/38;17priorbooks intact/current;types/build;Tempo manual visual reply ja efectuada;no accepted proof repeated",
"rollback": "l1-g3-readonly-rollback-20261024.patch checked on G4D candidate, not applied; retain readers/history/reports; previous release and verified fresh backup",
"activation": "Existing Git normal FF/webhook/installer; no migrations/imports/permission changes or formal fiscal activation",
"backup_restore": {
"backup": {
"stage": "/var/backups/investmoz-l1-g4d-delivery-20261024/backup",
"target": {
"database": "teste_investidor",
"port": 5432
},
"tables": 174,
"files_verified": 369,
"dump_sha256": "f45926e56c1d9544f6ee0e50d690cfed984101307224e8282f93b9f0ec91f705",
"files_sha256": "7ed455443737ca9ef2636a58e84a1b8b9c92cb12fc964c8addf07a5cced0c5f6",
"restore_verified": false
},
"restore": {
"restore_verified": true,
"tables_verified": 174,
"container_network": "none",
"database": "l1_g4d_restore_20261024",
"port": 55441,
"source_dump_sha256": "f45926e56c1d9544f6ee0e50d690cfed984101307224e8282f93b9f0ec91f705",
"active_database_writes": 0
}
},
"served_revision_and_delta": "verified",
"limits": "Beverages c/h follow13(2),amounts/credit/refund not calculated;provisions excluded d;13(2)not extended e. Alternative treatment outside exemption not silently assumed. This increment does not close the complete IVA apuramento.",
"P001": "05/06 only",
"L1_complete": false,
"statistics_AI": "deferred",
"authenticated_preflight": {
"installed": {
"status": "installed",
"commit": "679203d4b13cd5b88ab05a0da539c359c37cc426",
"release": "/var/www/investmoz-homologacao/releases/679203d4b13cd5b88ab05a0da539c359c37cc426-6ad3a32e",
"previous_release": "/var/www/investmoz-homologacao/releases/a153d0782f0f1f5a553a2c6d7106bc35059a170b-789a22ef",
"database_migrations": 0,
"content_imports": 0
},
"current_link": "/var/www/investmoz-homologacao/releases/679203d4b13cd5b88ab05a0da539c359c37cc426-6ad3a32e",
"release_revision": {
"commit": "679203d4b13cd5b88ab05a0da539c359c37cc426",
"branch": "main",
"built_at": "2026-10-24T15:58:35.074611+00:00",
"manifest_sha256": "7b37d131d7b9564d901d8fc21407a759fcded9ba734c3757ce0fda5c00cc5c56"
},
"service": "ExecMainStatus=0\nActiveState=inactive\nSubState=dead\n",
"configuration_keys": [
"repository",
"branch",
"target_url",
"legacy_root",
"state_root",
"release_root",
"current_link",
"shared_assets",
"php",
"schema_contract",
"ci_environment",
"postgis_image",
"test_database",
"qa_port",
"retention",
"webhook_secret_file"
],
"safe_paths": {
"repository": "nala/Investidor-V2",
"release_root": "/var/www/investmoz-homologacao/releases",
"postgis_image": "postgis/postgis@sha256:01a6a70e41e6c4467c8f55f6063555ed72db2d6662cd0d571040d42eadaeb6f6"
},
"pipeline_sha256": "adec1c17654f3a8658b83b134f1e75f95391b235738552721906c3236e388604"
},
"authenticated_destination": "Fresh read confirmed679203d4;installer inactive",
"new_backup_restore": "Verified fresh backup and real isolated restore;no active restore performed",
"beverages_followup": {
"source": "CIVA13(2),20(1)(d)",
"L2": "Dedução do IVA da via13(2),com montante/documento/condições próprios",
"L3": "Restituição da via13(2),conforme procedimento aplicável;pedido não equivale a deferimento",
"closed_by_G4D": false
},
"served_commit": "686328a0853a1165872b5eb8163f7223600033ea",
"installation": {
"protected": {
"installed": {
"status": "installed",
"commit": "686328a0853a1165872b5eb8163f7223600033ea",
"release": "/var/www/investmoz-homologacao/releases/686328a0853a1165872b5eb8163f7223600033ea-81b13983",
"previous_release": "/var/www/investmoz-homologacao/releases/679203d4b13cd5b88ab05a0da539c359c37cc426-6ad3a32e",
"database_migrations": 0,
"content_imports": 0
},
"runtime_files_verified": 3,
"persistent_files_and_env_verified": 369,
"tables_compared": 174,
"changed_tables": {
"cache": {
"before": {
"rows": 105,
"checksum": "de9a629fcda8ca89c2e1a4110abd00bb"
},
"after": {
"rows": 105,
"checksum": "84c52bab36d0972dfa8ef321f459c97f"
}
},
"sessions": {
"before": {
"rows": 17,
"checksum": "beb831efe057fd44c63bd504eb5d735f"
},
"after": {
"rows": 18,
"checksum": "388df19f76a7047a5d994b07b8e48c88"
}
}
},
"preserved_counts": {
"published_fiches": 29,
"relations": 28,
"geometries": 408
},
"migration_count": 0,
"content_imports": 0,
"comparison_role": "postgres_before_and_after;sameexportedsnapshotbaseline;noapplicationRLSvisibilityinference",
"writes_by_verification": 0
},
"public": {
"status": "installed_delta_verified",
"served_revision": {
"commit": "686328a0853a1165872b5eb8163f7223600033ea",
"branch": "main",
"built_at": "2026-10-24T16:09:18.914806+00:00",
"manifest_sha256": "c8a33831cec8c9c6cb0dea4a54083f2a86c1395879c4378470d2da61e4a97a60"
},
"manifest_hash_matches": true,
"compiled_delta_markers": {
"onboard-supplies/1": [
"assets/project-dossier-Dr4Yp1R0.js"
],
"onboard_seagoing_ship": [
"assets/project-dossier-Dr4Yp1R0.js"
],
"onboard_rescue_coastal_ship": [
"assets/project-dossier-Dr4Yp1R0.js"
],
"onboard_departing_warship": [
"assets/project-dossier-Dr4Yp1R0.js"
],
"onboard_international_aircraft": [
"assets/project-dossier-Dr4Yp1R0.js"
],
"supplyCategory": [
"assets/project-dossier-Dr4Yp1R0.js",
"assets/services-Cckqil_k.js"
]
},
"assets": [
{
"file": "assets/project-dossier-Dr4Yp1R0.js",
"status": 200,
"sha256": "51098ef65c988ab0452035a92f9ab0a51907ef28fe94bc837dfe2409d3240052"
},
{
"file": "assets/simulation-form-CPZAFZU3.js",
"status": 200,
"sha256": "c6bcf64e60a5eeac0cafe3dc055dc5544162f21942ee08b34d51bc6d52947567"
},
{
"file": "assets/services-Cckqil_k.js",
"status": 200,
"sha256": "7f51adf59981b7f7b5c393dd44d68bfcdbd22814031fb079c2626c17eb4ac834"
},
{
"file": "assets/project-dossier-document-eCa4uUtB.js",
"status": 200,
"sha256": "1cb1f92e49041f4d5a27bc82a64dc5c5d7c6e7ba8fdfc0b80f0b49d8f60be66e"
}
],
"simulator_status": 200,
"simulator_entry": "assets/app-CxtsWs-S.js",
"existing_fiscal_availability": {
"data": {
"enabled": true,
"coverage_start": "2026-01-01",
"coverage_end": "2026-12-31",
"message": "IVA geral sobre base líquida disponível; enquadramento declarado."
}
},
"synthetic_private_writes": 0,
"method": "Read-only installedrevision/manifest/newcompiledcatalogueandreaders/simulatorentry;acceptedQAproofsreused"
},
"installer": {
"service": "ExecMainStatus=0\nActiveState=inactive\nSubState=dead\n",
"installed": {
"status": "installed",
"commit": "686328a0853a1165872b5eb8163f7223600033ea",
"release": "/var/www/investmoz-homologacao/releases/686328a0853a1165872b5eb8163f7223600033ea-81b13983",
"previous_release": "/var/www/investmoz-homologacao/releases/679203d4b13cd5b88ab05a0da539c359c37cc426-6ad3a32e",
"database_migrations": 0,
"content_imports": 0
},
"latest_report": {
"status": "installed",
"commit": "686328a0853a1165872b5eb8163f7223600033ea",
"release": "/var/www/investmoz-homologacao/releases/686328a0853a1165872b5eb8163f7223600033ea-81b13983",
"previous_release": "/var/www/investmoz-homologacao/releases/679203d4b13cd5b88ab05a0da539c359c37cc426-6ad3a32e",
"database_migrations": 0,
"content_imports": 0,
"requested_commits": [
"686328a0853a1165872b5eb8163f7223600033ea"
],
"finished_at": "2026-10-24T16:09:21.362571+00:00"
},
"log_file": "1792858071888964336.log",
"summaries": [
"OK (1 test, 3106 assertions)",
"built in 24.76s",
"OK (59 tests, 317 assertions)",
"# tests 289",
"# pass 289",
"# fail 0"
],
"log_bytes": 112499
},
"rollback_executed": false
}
}
@@ -0,0 +1,512 @@
{
"status": "installed_delta_verified_partial_L1",
"candidate": "4a35d63cd3535195e4e2a37740b2f52813ff1da9",
"base_remote_main": "1655f57e698fef4099c2886069a79cd1c920f792",
"fetch": "completed;noforce;localmainnotused",
"bundle": {
"path": "outputs\\iva-l1-g2-social-20261024\\l1-joint-4a35d63c.bundle",
"candidate": "4a35d63cd3535195e4e2a37740b2f52813ff1da9",
"base": "1655f57e698fef4099c2886069a79cd1c920f792",
"sha256": "7e23cabda77c8e7b117091a08613436f02c32a9d23d023d4d030c9041eb43146",
"bytes": 166937,
"verified": true,
"content": "FunctionalQAcommit4a35d63c+historyfromorigin/main;receiptmetadatafinalizedseparately;noactivepush"
},
"coverage": {
"initial_QA": "544068e8/d89912e5:10conditionaltreatments",
"rational_QA": "689e7cbe/8719e916;exactincluded5%andreaders",
"G1": "5030116e/89ab2883:4branches/4treatments",
"G2A": "675cf38f/0e644b55:5branches/5treatments",
"G2B": {
"AUD-SIM-L1-P009": [
"social_assistance_public",
"social_assistance_nonprofit"
],
"AUD-SIM-L1-P011": [
"social_care_public",
"social_care_nonprofit"
],
"AUD-SIM-L1-P012": [
"activity_facilities_public",
"activity_facilities_nonprofit"
]
},
"conditional_treatments_total": 25,
"indeterminate_options": 2,
"QA_covered_inventory_IDs": [
"AUD-SIM-L1-P003",
"AUD-SIM-L1-P004",
"AUD-SIM-L1-P005",
"AUD-SIM-L1-P006",
"AUD-SIM-L1-P007",
"AUD-SIM-L1-P009",
"AUD-SIM-L1-P011",
"AUD-SIM-L1-P012",
"AUD-SIM-L1-P017",
"AUD-SIM-L1-P018",
"AUD-SIM-L1-P029",
"AUD-SIM-L1-P030"
],
"pending_functional_IDs": [
"AUD-SIM-L1-P002",
"AUD-SIM-L1-P008",
"AUD-SIM-L1-P010",
"AUD-SIM-L1-P013",
"AUD-SIM-L1-P014",
"AUD-SIM-L1-P015",
"AUD-SIM-L1-P016",
"AUD-SIM-L1-P019",
"AUD-SIM-L1-P020",
"AUD-SIM-L1-P021",
"AUD-SIM-L1-P022",
"AUD-SIM-L1-P023",
"AUD-SIM-L1-P024",
"AUD-SIM-L1-P025",
"AUD-SIM-L1-P026",
"AUD-SIM-L1-P027",
"AUD-SIM-L1-P028",
"AUD-SIM-L1-P031",
"AUD-SIM-L1-P032",
"AUD-SIM-L1-P033",
"AUD-SIM-L1-P034",
"AUD-SIM-L1-P035",
"AUD-SIM-L1-P036",
"AUD-SIM-L1-P037",
"AUD-SIM-L1-P038",
"AUD-SIM-L1-P039",
"AUD-SIM-L1-P040",
"AUD-SIM-L1-P041",
"AUD-SIM-L1-P042",
"AUD-SIM-L1-P043",
"AUD-SIM-L1-P044",
"AUD-SIM-L1-P045",
"AUD-SIM-L1-P046",
"AUD-SIM-L1-P047",
"AUD-SIM-L1-P048",
"AUD-SIM-L1-P049",
"AUD-SIM-L1-P050",
"AUD-SIM-L1-P051",
"AUD-SIM-L1-P052",
"AUD-SIM-L1-P053",
"AUD-SIM-L1-P054",
"AUD-SIM-L1-P055",
"AUD-SIM-L1-P056",
"AUD-SIM-L1-P057",
"AUD-SIM-L1-P058",
"AUD-SIM-L1-P059",
"AUD-SIM-L1-P060",
"AUD-SIM-L1-P061",
"AUD-SIM-L1-P062",
"AUD-SIM-L1-P063",
"AUD-SIM-L1-P064",
"AUD-SIM-L1-P065",
"AUD-SIM-L1-P066",
"AUD-SIM-L1-P067",
"AUD-SIM-L1-P068",
"AUD-SIM-L1-P069",
"AUD-SIM-L1-P070",
"AUD-SIM-L1-P071",
"AUD-SIM-L1-P072",
"AUD-SIM-L1-P073",
"AUD-SIM-L1-P074",
"AUD-SIM-L1-P075",
"AUD-SIM-L1-P076",
"AUD-SIM-L1-P077",
"AUD-SIM-L1-P078",
"AUD-SIM-L1-P079",
"AUD-SIM-L1-P080",
"AUD-SIM-L1-P081",
"AUD-SIM-L1-P082",
"AUD-SIM-L1-P083",
"AUD-SIM-L1-P084",
"AUD-SIM-L1-P085",
"AUD-SIM-L1-P086",
"AUD-SIM-L1-P087",
"AUD-SIM-L1-P088",
"AUD-SIM-L1-P089",
"AUD-SIM-L1-P090",
"AUD-SIM-L1-P091",
"AUD-SIM-L1-P092",
"AUD-SIM-L1-P093",
"AUD-SIM-L1-P094",
"AUD-SIM-L1-P095",
"AUD-SIM-L1-P096",
"AUD-SIM-L1-P097",
"AUD-SIM-L1-P098",
"AUD-SIM-L1-P099",
"AUD-SIM-L1-P100",
"AUD-SIM-L1-P101",
"AUD-SIM-L1-P102",
"AUD-SIM-L1-P103",
"AUD-SIM-L1-P104",
"AUD-SIM-L1-P105",
"AUD-SIM-L1-P106",
"AUD-SIM-L1-P107",
"AUD-SIM-L1-P108",
"AUD-SIM-L1-P109",
"AUD-SIM-L1-P110",
"AUD-SIM-L1-P111",
"AUD-SIM-L1-P112",
"AUD-SIM-L1-P113",
"AUD-SIM-L1-P114",
"AUD-SIM-L1-P115",
"AUD-SIM-L1-P116",
"AUD-SIM-L1-P117",
"AUD-SIM-L1-P118",
"AUD-SIM-L1-P119",
"AUD-SIM-L1-P120",
"AUD-SIM-L1-P121",
"AUD-SIM-L1-P122",
"AUD-SIM-L1-P123",
"AUD-SIM-L1-P124",
"AUD-SIM-L1-P125",
"AUD-SIM-L1-P126",
"AUD-SIM-L1-P127",
"AUD-SIM-L1-P128",
"AUD-SIM-L1-P129",
"AUD-SIM-L1-P130",
"AUD-SIM-L1-P131",
"AUD-SIM-L1-P132",
"AUD-SIM-L1-P133"
],
"pending_documentary_IDs": [
"AUD-SIM-L1-P001"
]
},
"runtime_delta": [
{
"path": "resources/js/components/simulation-monthly-iva.tsx",
"sha256_LF": "27e9f7b0a6cd011d6278d5bf507c8df0a290432006d795e9f7bf03b05fc6b350"
},
{
"path": "resources/js/components/simulation-operations.tsx",
"sha256_LF": "ae8fafbff339c4b52bae11ad479caf0fb451e5543e59bfbf15becf9aab4c5d27"
},
{
"path": "resources/js/lib/fiscal-rational.ts",
"sha256_LF": "91234efa465a8660f71a56e48d280a602c56ecf2ccce9cf7a8d91db513a3ffd3"
},
{
"path": "resources/js/lib/iva-acquisitions.ts",
"sha256_LF": "846dbd2d2dbdd54ffcddae8623eeaa2ae4f7686c6e2db05590ffa893d3ffbfb0"
},
{
"path": "resources/js/lib/iva-operations.ts",
"sha256_LF": "fb41bf3d6cf14ee65bf242f5a2504f9d4758c8d87bb4c4e9eda4822f74aa4d7f"
},
{
"path": "resources/js/lib/project-dossier.ts",
"sha256_LF": "5a6ea8a8c7261fa1d24cca56e92617cd66f72bd027dbafec22d051e686e927d7"
}
],
"schema_routes_permissions_dependencies_changed": false,
"database_imports_migrations_seeds": [],
"server_fiscal_rule_activation": false,
"activation": {
"method": "ExistingGitFF/merge+build+webhook;no new mandatory flag",
"preflight": [
"Re-fetchorigin/main;reconcileconcurrentchangeswithoutforce",
"Confirmactualservedrevisionandvalidbackup/restoreresultthroughauthenticatedexistingprocess",
"Usecompiledassets;excludeoutputs/syntheticdata/publichot/secrets",
"No globalmigration,seed,taxpublication or datareplacement"
],
"installed_delta_only": [
"servedrevisionandmanifesthash",
"simulatorusesnewasset",
"newoptions/readerscontextvisible;existingdraftrecoverable",
"prioracceptedproofsreused;nosyntheticwritesinactive"
],
"completed": true,
"database_migrations": 0,
"content_imports": 0
},
"reversal": {
"preferred": "ForwardGitcompatibilitycontainmentcommitusingpreparedreadonlypatch,notDBrestore;revertcontainmentcommitafterfix",
"patch": {
"patch": "docs\\investmoz\\simulations\\l1-joint-readonly-rollback-20261024.patch",
"patch_sha256": "d25a81f025ffeeb5869161404eb23b9762d87e07b4a820c14b63d29359d0db0e",
"component_before_sha256": "37676ccb4302e5fdf5dceb58291809f120ea204c2a8c6a59ede9585f8753aa73",
"git_apply_check": true,
"live_component_changed": false,
"purpose": "Operational compatibility rollback: suspend edits/calculations in L1 panel only;keep catalogue,readers,history,API,otherforms and reports;no DBrestore or broad path disable"
},
"QA_UI": "L1inputs/calculationdisabled;details/result600MZN/revision3/readers/reportsremain;otherforms/APIpermissionsunchanged",
"limitations": "UIoperationalcontainment,notAPIauthorizationchange;fullrollbackto1655wouldhidenewL1readersandisnotpreferred"
},
"destination_precheck": {
"public_revision_url": "https://teste-investidor.tempo.co.mz/build/revision.json",
"result": "Authenticateddestinationverified;existingdeliveryHTTPclient200;defaulturllib403/Cloudflare1010",
"served_revision_verified_this_pass": true,
"protected_installer_or_current_backup_verified": true,
"historical_initial_result": "HTTP403 before client diagnostic",
"diagnostic": [
{
"request": "default",
"status": 403,
"headers": {
"Content-Type": "text/plain; charset=UTF-8",
"Server": "cloudflare",
"CF-RAY": "a4f8f78b4cb51d20-JNB"
},
"body_sha256": "2938e9f1284180959e33ab1718d0793a72ff6e4cdb8108c34dcd14e69446de5c",
"error_excerpt": "error code: 1010\n"
},
{
"request": "existing_delivery",
"status": 200,
"headers": {
"Content-Type": "application/json",
"Server": "cloudflare",
"CF-RAY": "a4f8f78bdf3c3575-JNB"
},
"body_sha256": "ad3f581baf0ef17706246b1f87c5fd0fd3659b14c6ed8f7661a19d68d838d40b",
"commit": "1655f57e698fef4099c2886069a79cd1c920f792"
}
],
"cloudflare_reference": "https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-1xxx-errors/error-1010/",
"conclusion": "Cloudflare1010forurllibdefault;existingdeliveryclient200;specificCloudflarerulenotinspected;noapplicationpermissioncauseorconfigurationchangerequired"
},
"excluded": [
"P001mapping",
"120unimplementedbranches",
"newtaxes",
"IRPC/IRPS",
"statistics/AI",
"syntheticQArecordsandruntimefiles"
],
"delivery_performed": true,
"integration_preview": {
"remote": "1655f57e698fef4099c2886069a79cd1c920f792",
"merge_tree": "2284cf875e1b2ee6dd34ae5d182f57a3c194bf22",
"candidate_tree_equal": true,
"fast_forward_possible": true,
"conflicts": false,
"main_not_moved": true,
"scope": "Historicalpreparationpreview,beforeauthorizedmainfastforward"
},
"delivery_commit": "490527b92cf1ca18122679440ff3a38933b7e0c2",
"previous_main": "1655f57e698fef4099c2886069a79cd1c920f792",
"installation": {
"authenticated_preflight": {
"installed": {
"status": "installed",
"commit": "1655f57e698fef4099c2886069a79cd1c920f792",
"release": "/var/www/investmoz-homologacao/releases/1655f57e698fef4099c2886069a79cd1c920f792-fe9d3b11",
"previous_release": "/var/www/investmoz-homologacao/releases/cd10cccbf45f53836d8bf7b2bd90794d99602cb9-a38feaad",
"database_migrations": 0,
"content_imports": 0
},
"current_link": "/var/www/investmoz-homologacao/releases/1655f57e698fef4099c2886069a79cd1c920f792-fe9d3b11",
"release_revision": {
"commit": "1655f57e698fef4099c2886069a79cd1c920f792",
"branch": "main",
"built_at": "2026-10-24T10:18:11.360273+00:00",
"manifest_sha256": "dfb82481796aaf5826e8a5108575de3807ee787faffa92f38a56bb8d9caf5ce7"
},
"service": "ExecMainStatus=0\nActiveState=inactive\nSubState=dead\n",
"configuration_keys": [
"repository",
"branch",
"target_url",
"legacy_root",
"state_root",
"release_root",
"current_link",
"shared_assets",
"php",
"schema_contract",
"ci_environment",
"postgis_image",
"test_database",
"qa_port",
"retention",
"webhook_secret_file"
],
"safe_paths": {
"repository": "nala/Investidor-V2",
"release_root": "/var/www/investmoz-homologacao/releases",
"postgis_image": "postgis/postgis@sha256:01a6a70e41e6c4467c8f55f6063555ed72db2d6662cd0d571040d42eadaeb6f6"
},
"pipeline_sha256": "adec1c17654f3a8658b83b134f1e75f95391b235738552721906c3236e388604"
},
"backup": {
"stage": "/var/backups/investmoz-l1-joint-delivery-20261024/backup",
"target": {
"database": "teste_investidor",
"port": 5432
},
"tables": 174,
"files_verified": 369,
"dump_sha256": "6e9a2b0b350b0effe0812e7e5faa5c9c1886611a50c1be5f8b00515d7ef0c5ea",
"files_sha256": "53c170aa33714e78d997790cb7c75d672e9680052f7b2ffa5bccf2b719ca248e",
"restore_verified": false
},
"restore": {
"restore_verified": true,
"tables_verified": 174,
"container_network": "none",
"database": "l1_joint_restore_20261024",
"port": 55441,
"source_dump_sha256": "6e9a2b0b350b0effe0812e7e5faa5c9c1886611a50c1be5f8b00515d7ef0c5ea",
"active_database_writes": 0
},
"installer": {
"service": "ExecMainStatus=0\nActiveState=inactive\nSubState=dead\n",
"installed": {
"status": "installed",
"commit": "490527b92cf1ca18122679440ff3a38933b7e0c2",
"release": "/var/www/investmoz-homologacao/releases/490527b92cf1ca18122679440ff3a38933b7e0c2-d41ae12f",
"previous_release": "/var/www/investmoz-homologacao/releases/1655f57e698fef4099c2886069a79cd1c920f792-fe9d3b11",
"database_migrations": 0,
"content_imports": 0
},
"latest_report": {
"status": "installed",
"commit": "490527b92cf1ca18122679440ff3a38933b7e0c2",
"release": "/var/www/investmoz-homologacao/releases/490527b92cf1ca18122679440ff3a38933b7e0c2-d41ae12f",
"previous_release": "/var/www/investmoz-homologacao/releases/1655f57e698fef4099c2886069a79cd1c920f792-fe9d3b11",
"database_migrations": 0,
"content_imports": 0,
"requested_commits": [
"490527b92cf1ca18122679440ff3a38933b7e0c2"
],
"finished_at": "2026-10-24T12:30:02.029150+00:00"
},
"log_file": "1792844919670368682.log",
"summaries": [
"OK (1 test, 3106 assertions)",
"built in 23.74s",
"OK (59 tests, 317 assertions)",
"# tests 247",
"# pass 247",
"# fail 0"
],
"log_bytes": 100122
},
"protected_preservation": {
"installed": {
"status": "installed",
"commit": "490527b92cf1ca18122679440ff3a38933b7e0c2",
"release": "/var/www/investmoz-homologacao/releases/490527b92cf1ca18122679440ff3a38933b7e0c2-d41ae12f",
"previous_release": "/var/www/investmoz-homologacao/releases/1655f57e698fef4099c2886069a79cd1c920f792-fe9d3b11",
"database_migrations": 0,
"content_imports": 0
},
"runtime_files_verified": 6,
"persistent_files_and_env_verified": 369,
"tables_compared": 174,
"changed_tables": {
"cache": {
"before": {
"rows": 104,
"checksum": "41ddf6abf1cc00b85fb98a5c22da0ee1"
},
"after": {
"rows": 105,
"checksum": "23e7205245a904489ac3c12248d6b1ac"
}
},
"sessions": {
"before": {
"rows": 17,
"checksum": "436718228e6cb875393809c4a84ebd43"
},
"after": {
"rows": 18,
"checksum": "becbef33ee3be158db37e1878aec832b"
}
}
},
"preserved_counts": {
"published_fiches": 29,
"relations": 28,
"geometries": 408
},
"migration_count": 0,
"content_imports": 0,
"comparison_role": "postgres_before_and_after;sameexportedsnapshotbaseline;noapplicationRLSvisibilityinference",
"writes_by_verification": 0
},
"public_delta": {
"status": "installed_delta_verified",
"served_revision": {
"commit": "490527b92cf1ca18122679440ff3a38933b7e0c2",
"branch": "main",
"built_at": "2026-10-24T12:29:59.442400+00:00",
"manifest_sha256": "b9f7c6d05c78754dd1f9efb71bf5ff59cdfaa1167e136a71138c0fd194b19a33"
},
"manifest_hash_matches": true,
"compiled_delta_markers": {
"iva-operations-l1/2": [
"assets/project-dossier-Cqjhibc1.js"
],
"financial_stamp": [
"assets/project-dossier-Cqjhibc1.js"
],
"insurance_stamp": [
"assets/project-dossier-Cqjhibc1.js"
],
"health_assistive": [
"assets/project-dossier-Cqjhibc1.js"
],
"patient_transport": [
"assets/project-dossier-Cqjhibc1.js"
],
"social_assistance_": [
"assets/project-dossier-Cqjhibc1.js"
],
"social_care_": [
"assets/project-dossier-Cqjhibc1.js"
],
"activity_facilities_": [
"assets/project-dossier-Cqjhibc1.js"
],
"nonprofit": [
"assets/project-dossier-Cqjhibc1.js"
],
"exactFields": [
"assets/project-dossier-Cqjhibc1.js"
],
"20/21": [
"assets/project-dossier-Cqjhibc1.js"
]
},
"assets": [
{
"file": "assets/services-DUPANwbE.js",
"status": 200,
"sha256": "cfdd24a5527c693b0a227726babd1a054425c19cc4a0ebe5f215f582ba5bf302"
},
{
"file": "assets/simulation-form-CPZAFZU3.js",
"status": 200,
"sha256": "c6bcf64e60a5eeac0cafe3dc055dc5544162f21942ee08b34d51bc6d52947567"
},
{
"file": "assets/project-dossier-Cqjhibc1.js",
"status": 200,
"sha256": "937fd99184c12b1321abf86bf67a196c6d74db5296304bc7a746536653560e64"
},
{
"file": "assets/project-dossier-document-91ZtwN0x.js",
"status": 200,
"sha256": "73cb4b1b4ea8928de313cfa858896bfc613dfd0adfb091744a78c81cf5f47764"
}
],
"simulator_status": 200,
"simulator_entry": "assets/app-DVti_AMl.js",
"existing_fiscal_availability": {
"data": {
"enabled": true,
"coverage_start": "2026-01-01",
"coverage_end": "2026-12-31",
"message": "IVA geral sobre base líquida disponível; enquadramento declarado."
}
},
"synthetic_private_writes": 0,
"method": "Read-only installedrevision/manifest/newcompiledcatalogueandreaders/simulatorentry;acceptedQAproofsreused"
},
"git_method": "Freshfetch+ancestry/hashcheck+branchpush+fastforwardmain;noforce;normalwebhook",
"rollback_activated": false
}
}
@@ -0,0 +1,19 @@
--- a/resources/js/components/simulation-operations.tsx
+++ b/resources/js/components/simulation-operations.tsx
@@ -9,6 +9,8 @@
const save=(next:SalesBook)=>onChange('modelo_a_snapshot',saveSalesBook(draft,next));
const change=(id:string,patch:Partial<SalesOperation>)=>run(()=>save({...book,rows:book.rows.map(r=>r.id===id?{...r,...patch}:r)}));
return <section aria-label="Operações IVA por oportunidade" className="space-y-3 rounded border p-3">
+ <p role="status">Novos cálculos de operações IVA temporariamente suspensos. Resultados guardados e relatórios permanecem disponíveis.</p>
+ <fieldset disabled>
<h4 className="font-semibold">Operações de IVA — enquadramento das vendas</h4>
<p>Oportunidade {String(draft.context_opportunity||'entrada geral')}; moeda original {book.currency||'por indicar'}. Cobertura2026/MZN. Reutilize as vendas e complete apenas o enquadramento. Este bloco classifica as operações; não substitui nem soma novamente a execução mensal geral acima.</p>
<p>Uma empresa pode ter operações com tratamentos diferentes. Os valores são projecções sob pressupostos declarados, sem certificar facturas, reconhecer créditos ou submeter uma declaração à AT.</p>
@@ -36,6 +38,7 @@
{book.periods.map(p=><label className="block" key={p.period}><input type="checkbox" checked={p.complete} onChange={e=>run(()=>save({...book,periods:book.periods.map(v=>v.period===p.period?{...v,complete:e.target.checked}:v)}))}/> {p.period}: incluí todas as operações deste período; lista vazia significa ausência expressamente confirmada.</label>)}
<p>Limites: outras isenções/bases especiais e correspondência do campo06 permanecem por delimitar. IVA incluído a5% conserva a fracção exacta e apresenta um decimal a6casas; a aproximação de apresentação não constitui regra declarativa. O desconhecido nunca é assumido como zero.</p>
<button type="button" disabled={!book.periods.length} className="rounded bg-emerald-800 p-2 text-white disabled:opacity-50" onClick={()=>run(()=>save(recordSales(draft,book)))}>Calcular e guardar operações IVA</button>
+ </fieldset>
{book.result&&<><p role="status">{salesCurrent(draft,book)?'Resultado correspondente às entradas.':'Resultado histórico conservado; reveja as alterações antes de recalcular.'}</p><dl>{salesReportRows(draft).map(([,label,value,origin],index)=><div className="break-inside-avoid border-t py-2" key={index}><dt className="font-semibold">{label}</dt><dd>{value}<small className="block">{origin}</small></dd></div>)}</dl></>}
</section>;
}
@@ -1,5 +1,81 @@
# Reconciliação do IVA com o Novo Modelo A
## 24/10/2026 — lote08–10/14–18 entregue na homologação em1655f57e
**Estado actual: integrado, instalado e delta conferido; saldo deste lote: zero.** Candidata funcional `d18ff0f0`, registo QA `1655f57e`; revisão efectivamente servida `1655f57e698fef4099c2886069a79cd1c920f792`. Fetch anterior à integração encontrou `origin/main` em `cd10cccb`, antepassado da candidata; push por fast-forward, sem force ou alterações concorrentes a reconciliar. O webhook do processo existente instalou a revisão. Não se editou a pasta servida.
Conferência exclusivamente do delta instalado: `/build/revision.json` em1655f57e, branchmain; manifesto SHA256 `dfb82481796aaf5826e8a5108575de3807ee787faffa92f38a56bb8d9caf5ce7`, igual ao anunciado pela revisão; quatro assets HTTP200, com nove marcadores da nova funcionalidade e recuperação existente. `/simulador-fiscal` HTTP200 usa a entrada deste build; disponibilidade existente do IVA geral mantida. Conteúdo dos bundles verificado contra o próprio manifesto instalado, sem presumir nomes/bytes iguais entre Windows e Linux.
Fontes de moeda/tesouraria, recuperação mensal e motor fiscal publicado, schema, configuração, rotas e executor sem delta face a `cd10cccb`. Referência `276d833a` antepassada; PDF aceite S3 conserva SHA256 `7719a05136f6dba668b621f551626060d10db5fcbb84815cdad112a1eab9079b`, sem regeneração. As provas QA abaixo foram reutilizadas. Sem importações, migrações ou pedidos/cálculos sintéticos criados na homologação. Não se afirma nova auditoria autenticada à base; a prova desta entrega é revisão, manifesto, assets e entradas servidos. Evidência privada: `outputs/iva-acquisitions-delivery-20261024/installed-delta.json`.
Fecho limitado às aquisições08–10 e totais14–18 nas condições demonstradas. Não é apuramento integral do IVA. IRPC/IRPS permanecem inventariados para trabalho posterior; estatísticas/IA adiadas. Os estados QA/pendência de integração seguintes são histórico anterior a esta disponibilização, não o saldo actual.
## 24/10/2026 — aquisições08–10 e totais14–18 implementados e demonstrados em QA
**Estado actual: lote concluído em QA, candidata `d18ff0f0`, ramo `codex/modelo-a-aquisicoes-20261024`; ainda não integrado/disponibilizado na homologação.** S1–S3 continuam encerrados em `cd10cccb`, recibo `355656b5`; referência `276d833a` preservada. Esta secção sucede à proposta e ao cotejo parcial históricos abaixo. Sem IRPC/IRPS, publicação de regras, migração, mudança de permissões ou escrita em dados activos.
### Cotejo concluído antes da codificação
`VAT Return.pdf`: 285479bytes, SHA256 `9c0b99a810c7db53eb75d63c22ee22fb86a50ba57bd5509041ed80ee10f75741`, duas páginas lidas e renderizadas. Comparação com a imagem dos dois DOCX sobre fundo branco e instruções já reconciliadas. Originais intactos. O PDF não fornece critérios adicionais de elegibilidade por aquisição, nem prova nova edição/vigência pela sua existência.
| Campo/instrução | PDF versus DOCX | Tratamento executável |
|---|---|---|
|08–10|Mesma numeração: imobilizado, existências, outros bens/serviços; coluna de imposto a favor do sujeito passivo|Somar apenas IVA elegível das linhas, não orçamento, custo ou valor bruto de compras|
|14|Mesma soma `01+03+05+06+07`|Determinar apenas com parcelas conhecidas|
|15|Mesma soma `08+09+10+11+12`|Aquisições08–10 completas e11/12 determinados; sem operações deve ser declaração expressa|
|16|Mesma soma `02+04+13`|Reutilizar02 da execução mensal actual;04/13 não são zero implícito|
|17/18|Mesmas diferenças `16−15` / `15−16`, conforme o sentido|Diferenças antes de créditos anteriores; não são pagamento ou reembolso reconhecido|
|Regularizações|Ambos dizem11/12 no texto, mas as caixas são12/13|Regularizações fora deste lote; divergência não bloqueia08–10 nem somas inequívocas|
|Créditos/reembolso|Mantêm-se as remissões18/19 versus19/20 e art.20 no rodapé|Afectam o futuro tratamento19–27; não são activadas por esta passagem|
|Preenchimentos/layout|PDF tem cabeçalho completo, duas páginas, inicial/dentro do prazo assinalados, UGC/Província/Localidade Maputo; DOCX tem caixas vazias e imagem do corpo, com fluxo de leitura diferente|Não herdar selecções, prazo ou Maputo para qualquer investimento; não corrigir ou substituir originais|
### Correspondência e percurso executáveis
Componente existente de IVA mensal conserva a execução01/02 no servidor. Novo bloco ligado ao mesmo formulário e relatório guarda `modelo_a_snapshot` no mecanismo privado/versionado existente, com livros separados pela oportunidade em tratamento. Sem escolha numa entrada com várias oportunidades, pede a escolha; nunca assume a primeira. A API conserva as permissões de proprietário e a concorrência por ETag.
Compras/encomendas são reutilizadas com valor/moeda/mês de origem, por classificar como líquido ou bruto. O mês de encomenda/orçamento é conservado separadamente do mês do documento e da dedução; adoptar uma origem actualizada não altera silenciosamente o período fiscal editado. Para08/10 é possível escolher explicitamente o orçamento de activos/despesas operacionais já existente como referência, sem o converter em factura. Só se pede a diferença fiscal/documental. Mudança da origem é sinalizada e exige adopção explícita; não substitui edições deliberadas. Moeda conhecida é conservada; moeda ausente exige confirmação expressa, sem conversão de montantes.
Por linha: líquido/IVA/bruto (dois valores permitem obter o terceiro por soma/diferença, sem taxa de compra inventada), documento/referência/linha/data, fornecedor/inscrição, posse/forma legal, período, natureza projectada ou efectiva declarada, aquisição interna, afectação e exclusões. O adquirente confirma regime normal de IVA. Documento repetido sem linha distinta é recusado. Uma compra só registada, orçamento, documento incompleto, uso misto/especial ou período divergente não gera dedução. IVA expressamente zero e despesas expressamente não elegíveis ficam distintos de informação em falta.
Fundamento dirigido: CIVA republicado pela Lei13/2016, PDF14–16, arts.18(1)(a),18(3–5),19(1)(a),20 e21(1–3); Lei22/2022, art.20 (exclusões/17-A/excepções); Lei10/2025, PDF13, arts.18(2)/(6) e19(2). Reutilização das fontes oficiais aceites, sem nova validação de credibilidade. Âmbito executado: interno geral, MZN, 2026, afectação exclusiva a operações tributadas, mesmo período de emissão/dedução, sem exclusões/especialidades/dedução parcial. É o recorte técnico solicitado, não prazo de vigência legal nem nova regra organizacional. Em projecções, as condições são pressupostos explícitos, sem certificação documental.
Por mês, confirmação expressa de lista completa08–10 e de inexistência de operações nos campos fora deste lote. Sem confirmação, as parcelas e totais dependentes permanecem indeterminados; declarações em conflito com importações/vendas de outros enquadramentos registadas são recusadas.14–18 usam aritmética decimal exacta. Resultados, condições e origem ficam congelados; alterações tornam a versão histórica visivelmente desactualizada. O relatório reutiliza o resultado guardado sem recalcular e identifica oportunidade, localização, período, moeda, fontes, versão e declarações de ausência. A nota da execução isolada01/02 remete agora para o bloco separado, evitando apresentar dois estados contraditórios.
### Provas dirigidas e saldo
- **11 testes frontend aprovados:** oito do novo lote e três da correspondência afectada. Condições incompletas, exclusões, uso misto, documento/fornecedor, data/moeda, duplicações, ausência versus zero, origem alterada, orçamentos reutilizados, fórmulas08–10/14–18, histórico e segunda oportunidade. Exemplo com08=32,09=16,10=8:15=56;16=160.0048;17=104.0048. Também diferença credora18 e vendas em falta.
- **API real QA: dois testes/19 asserções aprovados**, base isolada `simulator_fiscal_delta_20261021_test:55441`, guarda de identidade e transacções revertidas. Payload calculado na interface da segunda oportunidade exportado por acção própria de QA → gravação privada real → recuperação exacta → relatório. Outra conta recusada; primeira oportunidade preservada; fingerprint de todas as regras igual. Nenhuma regra criada/publicada/suspensa.
- **Visual Edge, componentes reais numa interface isolada:** compra sem condições fica indeterminada; edição/cálculo da segunda produz17=`128.0048`; actualizar a página conserva a segunda; regressar à primeira conserva17=`144.0048`. O armazenamento da interface visual é local ao browser; a persistência no servidor foi comprovada separadamente com o mesmo payload na API real de QA.
- **Relatório da segunda oportunidade recuperada pela API:** CSV, Word e PDF apresentam `128.0048`, `160.0048`, MZN, Manica, oportunidade310, período e versão correspondentes, sem valores do livro309. PDF final com seis páginas conferidas visualmente, sem cortes/sobreposição. Abril deliberadamente sem vendas mantém01/02/14/16/17/18 indeterminados; a projecção financeira incompleta é identificada, sem fabricar resultado. Nenhum PDF ou exportação aceite de S1–S3 foi substituído.
- **TypeScript e build aprovados.** Provas privadas em `outputs/iva-operations-qa-20261024`; relatório `acquisitions-final.pdf`, hashes no recibo integrado. A interface de ensaio não é incluída nos assets do portal.
Saldo deste recorte em QA: zero. Integração e disponibilização na homologação continuam por executar. Futuro fora deste recorte: activação de taxa reduzida/isenções, mistos/pro rata/excepções, importações, regularizações, créditos19–27, juros/pagamento/reembolso e submissão AT. IRPC/IRPS permanecem apenas inventariados. Estatísticas e IA adiadas. O histórico abaixo não reabre S1–S3 nem converte esta entrega QA em homologação.
## Actualização de 24/10/2026 — comparação e próximo lote proposto
S1–S3 permanecem encerrados na homologação em `cd10cccb`, recibo `355656b5`, saldo zero. Esta passagem é reconciliação documental/código e proposta; não altera regras, dados activos ou impostos. Reutiliza a leitura visual e as provas aceites de 21/10, sem repetir ensaios.
Os dois originais nas Notas foram relidos por bytes: tamanhos, SHA256 e imagem incorporada coincidem com os valores documentados abaixo. Inventário actual completo das duas pastas: nove documentos nas Notas e quatro em Modelos, além de seis ficheiros temporários/de bloqueio inventariados separadamente, registados com nome, tamanho e hash no recibo integrado, chave `modelo_a_next_scope_20261024`. Os quatro modelos são `VAT Return.pdf`, `IRPC_IRPS.xlsx`, `Cópia de IRPS-IMOP.xlsx` e `IRPC M-22- DECLARACAO DE RENDIMENTOS.pdf`. Os três de IRPC/IRPS entram apenas no inventário; conteúdo fiscal/fórmulas ainda não analisados. `VAT Return.pdf` é exemplar adicional inventariado, ainda por cotejar com os dois DOCX antes de afirmar equivalência ou diferença. Nenhum original alterado, importado ou publicado nesta passagem.
| Bloco | Já suportado / reutilizável | Falta concreta |
|---|---|---|
| Identificação e período, quadros 1–6 | Oportunidade escolhida, dossier, organização, contactos, meses, moeda e origem | Ligar os campos fiscais; confirmar apenas diferenças de NUIT/sucursal/área fiscal/CAE/domicílio fiscal. Sector e localização do projecto não provam CAE ou domicílio fiscal. Tipo de declaração não é versão de projecção. |
| Campos 01/02 | Vendas mensais líquidas e IVA calculado pela versão publicada, recuperação pelo ID, moeda original e exportações aceites | Sem lacuna neste âmbito aceite; continua componente de planeamento, não imposto final a pagar. |
| Campos 03–07 | Calendário de vendas como origem | Classificação por operação, bases separadas, âmbito temporal das categorias e regras correspondentes; mapeamento não é cálculo implementado. |
| Campos 08–11 | Compras/encomendas mensais e pressupostos do plano | Valores líquido/IVA/bruto discriminados, documentos, fornecedor, afectação, exclusões e elegibilidade. Compras e investimento global não são IVA dedutível. |
| Campos 12/13 | Correspondência documental | Regularizações individualizadas, motivo, documento e período; resolver a remissão interna divergente. |
| Campos 14–18 | Fórmulas impressas mapeadas | Consolidação: 14=01+03+05+06+07; 15=08+09+10+11+12; 16=02+04+13; diferenças devedora/credora 17/18. Actualmente indeterminadas: parcelas ausentes não são zero. |
| Campos 19–27 | Planeamento pode conservar estimativas separadas | Créditos efectivos/comunicados, substituição, juros, pagamento, reporte e pedido de reembolso. Não implementados como apuramento declarativo. |
| Quadros 7, 12 e 13 | Autenticação e histórico do portal | Inexistência de operações exige informação completa; assinatura/submissão fiscal e campos reservados à AT não decorrem do login ou da simulação. |
**Diferenças e instruções:** os DOCX diferem por bytes e segmentação textual, com a mesma imagem do formulário; não está demonstrada alteração fiscal entre eles. Mantêm-se as divergências já documentadas: regularizações 11/12 no texto versus caixas 12/13; créditos 18/19 versus caixas 19/20; remissão de reembolso art.20 versus alteração de 2025 no art.21; remissões ambíguas ao quadro8. A duplicação de25 era artefacto de extracção, já resolvido. A edição/período aplicável e os dispositivos pertinentes devem ser cotejados para cada regra nova, reutilizando as fontes oficiais aceites.
**Proposta de lote seguinte — IVA por operação, primeiro âmbito interno geral em MZN:** reutilizar vendas e aquisições do plano por oportunidade/período; guardar origem/versionamento, previsto ou efectivo e classificação explícita. Implementar a discriminação líquido/IVA/bruto e a elegibilidade documentada das aquisições internas de imobilizado, existências e outros bens/serviços (08–10), após cotejo dirigido das condições e exclusões nas fontes existentes. Manter 01/02 e o motor publicado. Ligar 14–18 apenas quando todas as parcelas necessárias estiverem conhecidas ou expressamente declaradas sem operações, sem permitir que essa declaração apague operações existentes. Mostrar a parcela em falta quando o total não puder ser determinado.
Ficam fora deste lote proposto: activação de taxa reduzida, isenções/mistas/pro rata, importações, regularizações, créditos anteriores, substituições, juros, pagamentos, reembolsos e submissão à AT. Podem ser identificados na classificação, mas mantêm resultado indeterminado e explicação quando aplicáveis. IRPC/IRPS permanecem inventário. A proposta estreita o lote histórico abaixo; a estimativa histórica de28–52h não é orçamento deste novo recorte.
Fecho dirigido do lote proposto: reutilização sem preenchimento repetido; aquisição elegível/excluída/sem documento; zero versus ausência; alteração da segunda oportunidade preservando a primeira; mudança de origem cria versão sem reescrever histórico; gravação/recuperação e ecrã/exportações com iguais montantes, moeda, período, oportunidade, fonte e regra. Consolidar apenas os dispositivos efectivamente usados, sem nova validação genérica das fontes. Nenhuma implementação iniciada nesta reconciliação.
21/10/2026. Referência AUD-SIM-INT02, sem nova matriz/backlog. Preparação progressiva em QA; não é apuramento completo, submissão ou aceitação pela AT. A componente16% existente continua independente das restantes componentes por cadastrar/desenvolver. A leitura e aceitação documental da Tempo não é apresentada como validação jurídica independente.
## Exemplar e preservação
@@ -1,5 +1,921 @@
# Rastreabilidade, utilização e formação
## 24/10/2026 — G4D entregue na homologação 686328a0
P062/abastecimento de embarcação em alto mar, P063/salvamento-assistência-pesca costeira, P064/navio de guerra em saída para destino estrangeiro, P067/avião de companhia principalmente internacional: quatro ramos/quatro tratamentos, com categoria13(3) e condições próprias. Entrega pelo Git existente, fast-forward sobre679203d4, após conferência fresca autenticada e novo backup/restauro isolado real sem rede. Preservados174tabelas,369ficheiros/configuração e29fichas/28relações/408geometrias por comparação de identidade PostgreSQL equivalente; somente diferenças operacionais cache/sessões registadas. Zero migrações/importações, alterações de permissões ou ensaios sintéticos no activo.
Revisão efectivamente servida, manifesto/hash, marcadores compilados, três ficheiros funcionais e simuladorHTTP200 conferidos. Prova manual Tempo «ja efectuada» registada em `40a4ddcb`; código/API/provas anteriores reutilizados. Release anterior e backup conservados, contenção compatível de novos cálculos verificada, não aplicada. Montante/moeda/período e histórico preservados ao alterar categoria.
**Limites mantidos:** provisões (incluindo bebidas) excluídas na alínea d; bebidas nas alíneas c/h identificam a via13(2) de dedução/restituição sem calcular liquidação/crédito/restituição nem assumir taxa ou zero; a enumeração13(2)não é estendida à alínea e. O apuramento dessa via permanece no lote fiscal correspondente, independente deP001. Esta entrega não fecha o IVA integral.
[Manifesto/recibo](../simulations/l1-g4d-delivery-20261024.json), registo `iva_l1_g4d_homologation_20261024`. **58 entregues +74 funcionais pendentes +P001=133; sem candidatas QA por disponibilizar.** G4:15entregues/4porimplementar no âmbito descrito. P001 só05/06; L1 aberto; Estatísticas/IA adiadas.
## 24/10/2026 — G4D: conferência visual manual concluída pela Tempo
A Tempo respondeu «ja efectuada» ao pedido dirigido da página `http://127.0.0.1:18639/g4d.html`: quatro abastecimentos, categoria, bebidas no primeiro caso com via de dedução/restituição e apuramento indeterminado sem apagar preço, Guardar → Recuperar → Relatório. Registo `iva_l1_g4d_manual_Tempo_visual_QA_closed_20261024`. Esta prova manual encerra a pendência visual descrita abaixo; não é atribuída à extensão nem à conferência da revisão instalada. Código/API/provas anteriores reutilizados sem repetição. **G4D concluído em QA: candidata `8df721ac`, quatro ramos P062/P063/P064/P067. Saldo 54 entregues +4 QA +74 funcionais pendentes +P001=133.** Homologação permanece `679203d4/25cae1d9` até entrega; L1 aberto, P001 apenas05/06, Estatísticas/IA adiadas.
## 24/10/2026 — G4D executável em QA; conferência visual pendente
Candidata `8df721ac51c6b1aa77a09c21141ddd76c61eb27d`: P062/abastecimentos de navegação marítima em alto mar, P063/salvamento-assistência-pesca costeira, P064/navio de guerra em saída para destino estrangeiro, P067/avião de companhia principalmente internacional. **Quatro ramos/quatro tratamentos**, com motor e persistência existentes. Homologação permanece `679203d4/25cae1d9`; 54 ramos entregues preservados.
Fonte: CIVA republicado Lei13/2016,13(1)(c/d/e/h),13(2–3),PDF12/p.1426(270),19(1)(b)(i),PDF15/p.1426(273);Lei22/2022art.1/PDF3p.2252(27) eLei10/2025art.1/PDF12–13p.2180(12)–(13),não alteram13 e conservam19(1)(b)(i). Imagem da página1426(270) conferida, incluindo13(2–3). Categorias13(3): provisões de consumo exclusivo da tripulação/passageiros, combustíveis/lubrificantes/produtos de propulsão/aparelhos técnicos, produtos acessórios da preparação/tratamento/conservação de mercadorias transportadas. Único campo adicional `supplyCategory`; não inferido por sector ou localização. Categoria desconhecida é indeterminada. Bens postos a bordo e natureza/utilização do meio devem constar do documento ou pressuposto expresso; não basta cliente militar, barco de recreio ou voo internacional isolado.
**Diferenças executáveis:** provisões de bordo (incluindo bebidas) excluídas em13(1)(d); a exclusão é aplicada antes de inferir uma isenção. Bebidas em c/h seguem a via de dedução/restituição de13(2), sem aplicação de20(1)(d) para esse efeito, e não recebem automaticamente isenção directa/zero na venda. O cálculo da liquidação e do crédito/restituição dessa via continua por implementar no lote de apuramento correspondente; não encerrado por G4D nem confundido com P001. A enumeração13(2) não inclui e: bebidas a bordo do navio de guerra elegível não são excluídas por analogia. Fornecimento misto deve ser discriminado pelas parcelas efectivas, sem repetir o montante total. 2026/MZN; isenção directa apenas quando condições e natureza estão determinadas. Bebidas em c/h: via13(2) de dedução/restituição reconhecida, sem calcular liquidação, crédito ou restituição neste incremento. Provisões, incluindo bebidas, excluídas em d. Regra13(2) não estendida a e. Sem novas taxas, dedução automática de aquisições, importação, certificação de meios/documentos ou submissãoAT.
Quatro testes novos: condições, montante/preço líquido ou incluído, todas as combinações meio/categoria, desconhecido/exclusões, histórico e relatório. API privada QA1teste/38asserções, guarda `simulator_fiscal_delta_20261021_test:55441`, transacção revertida. Tipos, produção e página QA gerados com sucesso; avisos existentes de timings/plugins e compatibilidade futura Vite registados. Dezassete livros anteriores íntegros e actuais sem recálculo. Exemplo326/Manica/MZN/2026-12: provisões em alto mar, combustível em salvamento, bebidas em navio de guerra e produtos para carga no avião, 100MZN cada; campo05=400,00/IVA0,00. Alterar a categoria para rota excluída/indeterminada conserva preço e resultado anterior histórico, sem total fiscal presumido. Modelo/HTML do snapshot API recuperado conservam categorias, contexto, fontes e versão. Exportadores/formatação numérica inalterados: provas Word/PDF aceites reutilizadas, sem afirmar nova paginação.
**Falta conferência visual dirigida** em `http://127.0.0.1:18639/g4d.html`: quatro abastecimentos/categorias; bebidas no primeiro caso explicam dedução/restituição e mantêm cálculo indeterminado, sem apagar preço; Guardar → Recuperar → Relatório. Página sintética local com gravação própria, distinta da API privada já testada. Solicitada prova manual da Tempo; nenhuma resposta G4D ainda atribuída. Bloqueio guardado/gerido da extensão não contornado e não reabre provas anteriores.
**Saldo54 entregues +78 funcionais abertos +P001=133**; nos78, quatro G4D implementados/código-API aprovados com visual pendente e74 por implementar. G4:11 entregues, quatro neste incremento e quatro por implementar. L1 aberto; P001 só05/06; Estatísticas/IA adiadas. Registo `iva_l1_g4d_onboard_supplies_code_qa_visual_pending_20261024`, artefactos `outputs/iva-l1-g4-supplies-20261024/`.
## 24/10/2026 — G4C entregue na homologação 679203d4
P072/serviços ligados aos regimes indicados em13(1)(m), P073/expedição para o estrangeiro, P078/intermediação em nome e por conta de outrem: três ramos/três tratamentos, pelo processo Git existente, fast-forward sobre a153d078. Destino e main conferidos por leitura fresca autenticada; novo backup e restauro isolado real sem rede verificados. Preservados 174 tabelas, 369 ficheiros/configuração, 29 fichas, 28 relações e408 geometrias, com identidade PostgreSQL equivalente. Apenas diferenças operacionais de cache/sessões admitidas e registadas; zero migrações/importações, alterações de permissões ou ensaios sintéticos no activo.
Revisão efectivamente servida, manifesto/hash, marcadores compilados, três ficheiros funcionais e simulador HTTP200 conferidos. Referência opcional conserva identidade e preço próprio do serviço; não comprova condições nem duplica montantes. Prova manual Tempo «verificada» registada em `2fccbc8e`, distinta da conferência de instalação e não reaberta pelo bloqueio da extensão. Provas código/API e exportadores aceites reutilizadas. Release anterior/backup conservados e contenção de novos cálculos compatível verificada, não aplicada; leitores, histórico e relatórios preservados.
[Manifesto/recibo](../simulations/l1-g4c-delivery-20261024.json), registo `iva_l1_g4c_homologation_20261024`. **54 entregues +78 funcionais pendentes +P001=133; sem candidatas QA por disponibilizar.** G4:11 entregues/8 por implementar. P001 só05/06; L1 aberto; Estatísticas/IA adiadas. Limites2026/MZN mantidos, sem apuramento integral IVA, certificação formal de regimes ou dedução automática de compras.
## 24/10/2026 — G4C: conferência visual manual concluída pela Tempo
A Tempo respondeu «verificada» ao pedido dirigido da página `http://127.0.0.1:18639/g4c.html`: escolha dos três serviços, referência sem alterar o preço e Guardar → Recuperar → Relatório. Registo `iva_l1_g4c_manual_Tempo_visual_QA_closed_20261024`. Esta prova manual encerra a pendência visual descrita abaixo; não é atribuída à extensão nem à conferência da revisão instalada. Código/API/provas anteriores reutilizados sem repetição. **G4C concluído em QA: candidata `b1c8e0e3`, três ramos P072/P073/P078. Saldo 51 entregues +3 QA +78 funcionais pendentes +P001=133.** Homologação permanece `a153d078/117f2a70` até entrega; L1 aberto, P001 apenas05/06, Estatísticas/IA adiadas.
## 24/10/2026 — G4C executável em QA; conferência visual pendente
Candidata `b1c8e0e343bca6b752343f178cc23f35a11aa374`: P072/serviços ligados aos regimes aduaneiros indicados em 13(1)(m), P073/serviços ligados à expedição para o estrangeiro em 13(1)(n), P078/intermediação em nome e por conta de outrem em 13(1)(s). Três ramos e três tratamentos. Os 51 ramos entregues permanecem encerrados; homologação `a153d078`, recibo `117f2a70`, sem alteração.
**Fonte e condições:** CIVA republicado Lei 13/2016, art. 13(1)(m/n/s), PDF 12/p.1426(270); remissões 12(1)(c), PDF 11/p.1426(269), 14, PDF 13/p.1426(271), 19(1)(b)(i), PDF 15/p.1426(273). Lei 22/2022 art.1, PDF 3/p.2252(27), e Lei 10/2025 art.1, PDF 12–13/p.2180(12)–(13), não alteram 13 e conservam 19(1)(b)(i). P072 exige ligação concreta do serviço aos bens e ao regime identificado; não basta a localização numa zona. P073 exige expedição para o estrangeiro e ligação concreta do serviço. Ambos excluem os serviços referidos no artigo 9. P078 exige mandato/actuação em nome e por conta de outrem e operação subjacente abrangida em 13 ou realizada fora do território. O próprio serviço deve ter territorialidade identificada em Moçambique; a localização da operação subjacente não substitui esse enquadramento. P001, relativo a 05/06, permanece isolado e o tratamento anterior de operação estrangeira não foi alterado. Âmbito 2026/MZN/05, sem certificar regimes, documentos, declarações ou deduções de compras. O comunicado regulamentar de 30/09/2026 mantém o cotejo documental próprio; não é tratado como decreto publicado nem activa procedimentos formais novos.
**Reutilização:** oportunidade, localização, moeda, preço líquido/incluído, período, estabelecimento, descrição, fundamento e condições já existentes. Único dado adicional opcional: referência à identidade de outra operação do mesmo livro/oportunidade, conservando ID, descrição e tratamento no snapshot e relatório. Há alternativa de fundamento/documento externo, sem exigir cadastro artificial de outra venda. A escolha não copia o valor dos bens para o preço do serviço e não confirma automaticamente as condições. Referência removida ou com descrição/tratamento alterados deixa cálculo indeterminado até actualização e revisão explícitas; resultado anterior fica no histórico. Dados desconhecidos não se tornam zero.
**Provas dirigidas:** quatro testes novos do motor; API privada QA com um teste/39 asserções, guarda `simulator_fiscal_delta_20261021_test:55441`, transacção revertida; tipos, compilação de produção e compilação da página QA passaram. O build QA emitiu aviso de compatibilidade futura da configuração Vite e gerou os artefactos. Dezasseis livros anteriores permanecem integrais e actuais sem recálculo. Persistência sintética da página testada em directório temporário, sem servidor ou rede, distinta da persistência privada pela API. Exemplo oportunidade 325/Manica, MZN, 2026-12: bens 1000 + três serviços 100 = campo 05 de 1300,00 e IVA 0,00. A referência do serviço de expedição mantém o preço 100,00 e o ID `g4c-goods`. Modelo e HTML gerados exclusivamente do snapshot recuperado conservam referência, contexto, fontes e versão. Formatação numérica/exportadores inalterados: provas aceites Word/PDF de fracções reutilizadas, sem afirmar nova conferência de paginação.
**Falta apenas a conferência visual deste delta:** selecção dos serviços e condições; referência sem substituição do preço; guardar → recuperar → relatório. Página `http://127.0.0.1:18639/g4c.html`, mesma origem autorizada, com gravação sintética separada. Extensão continua impedida por permissão guardada/gerida, sem contorno; não constitui falha do portal nem reabre provas anteriores da Tempo. Conferência manual solicitada, ainda sem observação G4C registada.
**Saldo: 51 entregues + 81 funcionais abertos + P001 = 133.** Dentro dos 81: três G4C com código/API aprovados e visual pendente, 78 por implementar. G4: oito entregues, três nesta verificação e oito por implementar. Não contar G4C como demonstrado em QA ou entregue antes da prova. L1 aberto; Estatísticas e IA adiadas. Registo `iva_l1_g4c_linked_services_code_qa_visual_pending_20261024`; artefactos `outputs/iva-l1-g4-services-20261024/`.
## 24/10/2026 — G4B entregue na homologação a153d078
P065/operações sobre embarcações,P066/operações sobre aviões,P068/necessidades directas:três ramos/quatro tratamentos,pelo processoGit existente,fast-forward sobreb8989556,após destino/main frescos ebackup/restauro real isolado semrede.174tabelas/369ficheiros/configuração preservados;29fichas,28relações e408geometrias intactas,comparadas por identidadePostgreSQL equivalente;diferenças operacionais apenas cache/sessões registadas. Zero migrações/importações,alterações de permissões ou ensaios sintéticos noactivo.48fechos anteriores,release anterior ebackup preservados.
Revisão servida,manifesto/hash,assets,dois ficheiros funcionais e simuladorHTTP200 conferidos. ProvasQA aceites reutilizadas;prova visualmanualTempo0b0e002d preservada,sem reabertura pelo bloqueio da ferramenta. Controlos normais doinstalador passaram. Contenção compatível conferida,não aplicada;catálogo/leitores/histórico/relatórios mantidos. Sem recálculo automático ou sobrescrita deedições.
[Manifesto/recibo](../simulations/l1-g4b-delivery-20261024.json),registo `iva_l1_g4b_homologation_20261024`. **51entregues+81funcionaispendentes+P001=133;QApendenteentrega0.** G4:8entregues/11porimplementar. P001só05/06;L1aberto;Estatísticas/IAadiadas. Cotejo do comunicado regulamentar permanece documentado,sem activação ou afirmação de diploma conferido.
## 24/10/2026 — G4B: prova visual pela Tempo; QA concluída
A Tempo confirmou «prova visual efectuada» para G4B. Registada como **verificação manual pela Tempo**, distinta das provas técnicas e sem atribuir observação de navegador ao Codex ou inventar resultados individuais. O ficheiro guardado às17:29:52 locais (15:29:52.114Z) conserva324/Manica/2026-12/MZN,quatro operações e resultado actual:05=400,00/IVA0,00. Ficheiro não sobrescrito durante a conferência. Testes técnicos3frontend/APIQA1teste35asserções/tipos/build/15livros anteriores preservados reutilizados,sem repetição.
**G4B/P065,P066,P068 concluído emQA**,candidata `f946364b`:três ramos/quatro tratamentos,sem inflacionar IDs. Registo `iva_l1_g4b_visual_completion_20261024`,com origem manual e corroboração técnica explícitas. Mantêm-se âmbito2026/MZN,condições específicas e limites:sem abastecimentos,dedução automática,certificação documental ou declaraçãoAT.
**Saldo48entregues+3QA+81funcionaispendentes+P001=133**. Homologação permanece `b8989556/3846be8f`;G4B ainda não disponibilizado. Próximo passo:preparação/integração Git,main/destino ebackup/restauro frescos,seguida apenas do delta instalado. P001só05/06;L1aberto;Estatísticas/IAadiadas.
## 24/10/2026 — G4B executável emQA; conferência visual pendente
Candidata `f946364baa8c2c29334879f60f0c64564ba9a78b`. P065/operações sobreembarcações,P066/operações sobreaviões,P068/serviços para necessidades directas: **3ramos/4tratamentos**,distinguindo serviços deembarcação e deavião. G4 tem5entregues(G4A),3emverificação e11porimplementar. Homologação permanece `b8989556/3846be8f`,48fechos preservados.
Fonte:CIVA republicadoLei13/2016,13(1)(c/d/f/g/i),PDF12/p1426(270),19(1)(b)(i),PDF15/p1426(273),imagens conferidas;conjugadasLei22/2022art1/PDF3p2252(27) eLei10/2025art1/PDF12–13p2180(12)–(13),sem alteração13 nestesdiplomas e mantendo19(1)(b)(i). Âmbito2026/MZN/05,sem dedução automática deaquisições. P065 exigeembarcação afecta àsactividades c/d eoperação enumerada em f;P066 exigeavião decompanhia principalmente internacional eoperação enumerada g,não apenas umvoo internacional. Aslistas conservam asdiferenças:aluguer autónomo deobjectos deavião não é acrescentado àenumeração g. P068 exige serviço distinto dosmencionados f/g,ligado anecessidades directas domeio elegível ourespectivacarga,não qualquer serviço aooperador. Regra debebidas13(2),restrita c/d/e/h,não é estendida a f/g/i;abastecimentos permanecem noutrosramos.
Nenhum campo novo:reutilizados contexto,moeda,vendas/preço,período,estabelecimento,descrição,fundamento econtrolos existentes decondições. Meio/operador/utilização/ligação devem estaridentificados nodocumento oupressuposto expresso daprojecção;sem certificação automática dematrícula,novasaprovações ou licenças inventadas. Desconhecido/condição/fundamento emfalta→indeterminado,semzero. Cálculo,gravação/recuperação,relatório ehistórico reutilizam omotorentregue.
3testesfrontend novos eAPIprivadaQA1teste/35asserções,guarda `simulator_fiscal_delta_20261021_test:55441` etransacção revertida;tipos,buildprodução epáginaQA passaram.15livros anteriores integrais eactuais semrecálculo. FicheiroQA G4A tem gravação posterior17:28:06,com4operações eresultado500histórico;preservado semsobrescrita neminferência decausa. Orecibo aceite anterior conserva oseuhash original. Exemplo324/Manica/MZN/2026-12,4operações100MZN,05=400,00/IVA0,00,preço líquido/incluído;retirada decondição deixa totalindeterminado e preserva cálculoanterior nohistórico. SnapshotAPIrecuperado coincide;modelo/HTML conservamfontes/versão/contexto. Exportadores/formatação numérica inalterados:provasWord/PDF/fracções aceites reutilizadas,sem nova afirmação depaginação.
**Falta conferência visual dirigida**:selecção/condições,ligaçãoao meio/necessidade directa,condição retirada/reposta,guardar→recuperar→relatório dapassagemreal. Página `http://127.0.0.1:18639/g4b.html`,namesma origem,gravação sintética separada deG4A. Após correcçõescomunicadas pelaTempo,aextensãoEdge voltou aligar,mas apermissão guardada/gerida continua abloquear aorigem antesda abertura. Nãocontornado,nãodemonstra falha doportal. Via manualTempo autorizadadisponível;nenhuma observaçãoG4B atribuída porantecipação. Comunicado regulamentar30/09/2026mantém cotejopróprio;sem declarar decreto/publicação/procedimentos formaisconferidos.
**Saldo48entregues+84funcionaisabertos+P001=133**;dos84,3G4Bimplementados/code/APIaprovados comvisualpendente e81porimplementar. Nãosomados aosdemonstradosQA. P001só05/06;L1aberto;Estatísticas/IAadiadas. Registo `iva_l1_g4b_international_assets_code_qa_visual_pending_20261024`,artefactos `outputs/iva-l1-g4-transport-20261024/`.
## 24/10/2026 — G4A entregue na homologação b8989556
P074/CFM, P075/passageiros internacionais, P076/trabalhos em bens móveis para reexpedição, P077/ouro não trabalhado para Banco deMoçambique eP079/embalagens para exportação:cinco ramos disponibilizados peloGit existente,fast-forward sobre6eefe4b3,após main/destino frescos ebackup/restauro real isolado.174tabelas/369ficheiros/configuração preservados;29fichas,28relações e408geometrias intactas. Diferenças operacionais apenas cache/sessões registadas,comparadas por identidadePostgreSQL equivalente. Zero migrações/importações,alterações de permissões ou execuções privadas sintéticas noactivo.43fechos anteriores,release anterior ebackup conservados.
Revisão servida,manifesto/hash,assets,dois ficheiros funcionais e simuladorHTTP200 conferidos;controlos normais doinstalador passaram;provasQA aceites reutilizadas. Prova visual:manualTempo7b54efb0,sem observação de navegador peloCodex. Última edição sintética conservada,com resultado anterior histórico;nenhum recálculo automático ou sobrescrita. Contenção compatível conferida,não aplicada,conserva catálogo/leitores/histórico/relatórios.
[Manifesto/recibo](../simulations/l1-g4a-delivery-20261024.json),registo `iva_l1_g4a_homologation_20261024`. **48entregues+84funcionaispendentes+P001=133;QApendenteentrega0.** G4:5entregues/14porimplementar. Comunicado regulamentar30/09/2026 mantém inventário/cotejo próprio,não é diploma activado. P001só05/06;L1aberto;Estatísticas/IAadiadas.
## 24/10/2026 — G4A: conferência visual pela Tempo; QA concluída
A Tempo respondeu «verificado» à passagem dirigidaG4A:tratamento/condições,retirada/reposição decondição ecálculo,guardar→recuperar→relatório. Registado comoverificação manual pelaTempo,sem observação donavegador peloCodex ou resultados individuais inventados. Provas técnicas3frontend/APIQA1teste36asserções/tipos/build/14livros preservados reutilizadas,sem repetição.
Ficheiro real guardado17:14:13 locais,323/Manica/2026-11/MZN,5operações. Última linha alterada desemIVA paraIVAincluído após ocálculo guardado:resultado05=500,00é **histórico,nãoactual**,assinalado pelachave deactualidade;osdados editados ficaram conservados,semrecálculo automático. Aconferência não sobrescreveu ogravadopelaTempo nemapresenta esse resultadohistórico comoactual. Alteração nãoépor sisó falha:as duas representações foramtestadas tecnicamente eahistória éconservada.
**G4A/P074–P077/P079 concluídoQA**,candidata `0f0d2e56`,registo `iva_l1_g4a_visual_completion_20261024`. Saldo **43entregues+5QA+84funcionaispendentes+P001=133**. Homologação permanece `6eefe4b3/82e010c4`;nenhum destes5ramos entregueainda. Próximopasso:preparaçãoGit,main/destino ebackup/restauro frescos,delta instalado apenas. P001só05/06;L1aberto;Estatísticas/IAadiadas.
## 24/10/2026 — G4A executável em QA; conferência visual pendente
Candidata `0f0d2e566f0d00185588a4c1eef5e3cb83bb1618`:P074/CFM comcompanhias ferroviárias estrangeiras,P075/transporte internacional depassageiros,P076/trabalhos embens móveis parareexpedição,P077/ouro não trabalhado paraBanco deMoçambique,P079/taras eembalagens demercadorias aexportar. Cinco dos19ramosG4;14continuam porimplementar. Os43ramos entregues são preservados,homologação `6eefe4b3/82e010c4` inalterada.
Fonte conferida visualmente:CIVA republicadoLei13/2016,13(1)(o/p/q/r/t),PDF12/p1426(270);19(1)(b)(i),PDF15/p1426(273). Conjugadas Lei22/2022art1/PDF3/p2252(27) eLei10/2025art1/PDF12–13/p2180(12)–(13),que mantêm aenumeração19(1)(b)(i),sem alteração13 nestes diplomas. Âmbito2026/MZN,campo05,sem dedução automática deaquisições ou submissãoAT.
Condições poroperação:o exigeCFM como prestador/transmitente ecompanhia ferroviária estrangeira noquadro daexploração daferrovia/equipamento;p exigepercurso depassageiros proveniente doou comdestino aoestrangeiro,não nacionalidade;q exigebens adquiridos/importados paratrabalhos noterritório nacional,reexpedição deseguida eexpedidor/interveniente elegível;r exigeouro embarra/outra forma não trabalhada eBanco deMoçambique comoadquirente;t exigetaras/embalagens como invólucro demercadorias aexportar eafectação identificada. Reutilizados dados comuns econtrolo existente decondições/fundamento;nenhum campo económico novo. Desconhecido/condição/fundamento/valor em falta→indeterminado,semzero. O fundamento pode serpressuposto expresso deprojecção,sem certificar umaoperação real.
3testesfrontend novos;APIprivadaQA1teste/36asserções comguarda `simulator_fiscal_delta_20261021_test:55441` etransacção revertida;tipos,buildprodução epáginaQA passaram.14livros anteriores integrais eactuais semrecálculo;nenhuma ronda dos43ramos aceites repetida. Exemplo323/Manica/MZN/2026-11,cinco operações100cada,05=500,00/IVA0,00;preço líquido/incluído,condições retiradas/repostas,histórico,snapshot→API→recuperação→modelo/HTML conferidos. Exportadores inalterados;provasWord/PDF/fracções aceites reutilizadas,sem nova afirmação depaginação.
**Falta somente aconferência visual dirigida donovo delta**:escolha/condições específicas,informação em falta egravação/recuperação/relatório dapassagem real. Página namesma origem `http://127.0.0.1:18639/g4a.html`,comficheiro sintético separado deG2L/G3 econtrolos explícitos. Apermissão guardada daferramenta nãofoi contornada nemnovamente ensaiada;nenhuma prova visualG4A atribuída àTempo ouaoCodex porantecipação.
Inventariado comunicado oficial doGoverno30/09/2026 sobreaprovação dealterações aoRegulamentoIVA:https://portaldogoverno.gov.mz/governo-introduz-alteracoes-nos-regulamentos-fiscais-para-reforcar-eficiencia-tributaria/. Comunicado nãoé textododecreto nemcomprova publicação/entradaemvigor. Cotejo documental do diploma pendente;nenhuma alteração concreta aestascinco classificações estatutárias demonstrada pelanotícia,sem activarregra ou criar bloqueio genérico. Esteincremento nãocertifica procedimentos formais documentais nemdeclara cotejado todooregulamento futuro.
**Saldo43entregues+89funcionaisabertos+P001=133**;dos89,5G4A implementados/code/API aprovados comvisualpendente e84porimplementar. Nãocontados comodemonstradosQA antesdaprova. P001só05/06;L1aberto;Estatísticas/IAadiadas. Registo `iva_l1_g4a_direct_operations_code_qa_visual_pending_20261024`;artefactos `outputs/iva-l1-g4-export-20261024/`.
## 24/10/2026 — G3 entregue na homologação6eefe4b3
Sete ramosP038–P043/P045,cessação2026/MZN econtinuidade expressa,peloGit existente:fast-forward sobreccdecbd8,após destino/main frescos ebackup/restauro real isolado.174tabelas/369ficheiros/configuração preservados;29fichas,28relações e408geometrias intactas. ComparaçãoPostgreSQL equivalente,com diferenças operacionais apenas cache/sessões registadas. Zero migrações/importações,alterações de permissões ou ensaios sintéticos noactivo.36fechos anteriores mantidos;release anterior ebackup guardados.
Revisão servida,manifesto/hash,assets,3ficheiros funcionais e simuladorHTTP200 conferidos. ProvasQA aceites reutilizadas;controlos normais doinstalador passaram. Prova visualG3:manualTempo,0dc2d64b;explicitaçãoG2L:908c8afc,distinta da revisão instalada. Contenção antiga não encaixava após novo auxiliar;patchG3compatível foi gerado/conferido,não aplicado,preservando leitores/catálogo/histórico/relatórios.
[Manifesto/recibo](../simulations/l1-g3-delivery-20261024.json),registo `iva_l1_g3_homologation_20261024`. **43entregues+89funcionaispendentes+P001=133IDs;QApendenteentrega0.** Não é cálculo histórico2025,importações,prorrogação ou apuramento integralIVA.P001só05/06;L1aberto;Estatísticas/IAadiadas.
## 24/10/2026 — G3: conferência visual confirmada pela Tempo; QA concluída
A Tempo confirmou expressamente «foi feita a conferencia visual»,em resposta à pendência dirigidaG3. Registada como **verificação manual pelaTempo**,sem atribuir observação de navegador aoCodex,nem inventar resultados individuais não descritos. O ficheiro sintético guardado às16:56:23,322/Manica/2026-10,conserva as sete operações combenefício terminado e totais indeterminados;comprova esse estado,sem demonstrar por si cliques de continuidade para alternativas. As provas técnicas separadas —3frontend,APIprivadaQA1/36,tipos/compilação,relatório recuperado e13livros preservados— são reutilizadas;nenhum ensaio foi repetido.
**G3/P038–P043/P045 concluído emQA**,no âmbito decessação2026/MZN e continuidade explícita demonstrada tecnicamente,candidata `ac948bd8`. Registo `iva_l1_g3_visual_completion_20261024`,com declaração manual e limites da corroboração técnica explícitos. Não é cálculo histórico2025,prorrogação,importações nem apuramento integralIVA.
**Saldo36entregues+7QA+89funcionaispendentes+P001=133IDs.** Homologação permanece `ccdecbd8/643ba6ed`;não se declara entregaG3. Próxima acção:preparação/integração peloGit existente,com destino/main,backup/restauro frescos e conferência somente do delta. P001só05/06;L1aberto;Estatísticas/IAadiadas.
## 24/10/2026 — G3 executável em QA: cessação e continuidade; conferência visual pendente
Candidata `ac948bd8b7ff34d661dd4cb7cbe88221093dfd83`. **Sete ramos P038–P043/P045**,agrupados por termo e dados comuns;nenhuma das36entregas foi reaberta. Homologação continua `ccdecbd8`,recibo `643ba6ed`. A explicitação da prova visualG2L foi registada separadamente em `908c8afc`:via manualTempo,distinta da API e da revisão instalada,sem repetição.
Fontes e períodos:Lei3/2025,art.1/2,PDF1–2/p478(1)–(2),9(13)(a–f),termo31/12/2025 e entrada na publicação21/05/2025;Lei22/2022,art.1,PDF2/p2252(26),9(16),mesmo termo,art.3(2)/6,PDF4/p2252(28),AnexoIV e efeitos01/01/2023. Lei10/2025,art.1,PDF12/p2180(12),não altera9 nem prorroga estes termos e retira remissões9(13)/9(16) do12(1)(a);art.5,PDF15/p2180(15),efeitos01/01/2026. Isto delimita as fontes analisadas,não uma afirmação de pesquisa universal de legislação. CIVA2016,9(14),PDF10/p1426(268),exige documentos aduaneiros apropriados ou declaração do adquirente para b/f,consoante o caso;essa remissão não se estende a todo o grupo. A redacção2025 de b diz **efectuadas pela indústria nacional do açúcar**,distinta da antiga formulação para a indústria:registada sem aplicação retroactiva.
Âmbito implementado:cessação nas operações internas de2026/MZN. O benefício terminado é identificado como não aplicável;**o imposto continua por determinar**,sem o transformar em zero ou aplicar16% automaticamente. A pessoa escolhe expressamente outro enquadramento e confirma as suas condições. A continuidade conserva IDda operação,moeda,montante,representação do preço,período,estabelecimento,origem e fundamento;acrescenta `temporaryBenefitOrigin`,limpa somente confirmações para revisão e conserva resultados anteriores. Para cana,existe acesso explícito à análise da produção agrícola própria9(7)(a),independente do benefício terminado,sem a presumir. Outros enquadramentos disponíveis podem ser escolhidos no controlo existente. Não é necessário preencher documentos de uma isenção já terminada para prosseguir em2026.
Reutilizam-se motor,campos,snapshots,API e exportadores.Nenhum novo campo económico obrigatório. Não se implementou nem declarou elegibilidade histórica2025,classificação executável dos AnexosII/IV,importações,dedução automática ou declaraçãoAT. A ausência desses cálculos não é substituída porzero.
Provas novas:3testesfrontend;APIprivadaQA1teste/36asserções,guarda `simulator_fiscal_delta_20261021_test:55441` e transacção revertida;tipos,compilação de produção e páginaQA passaram.13livros entregues permanecem integrais e actuais sem recálculo. Exemplo recuperado:322/Manica/MZN/2026-10,8operações,01=700,00;02=112,00;05=100,00;preço incluído116→base100/IVA16 após escolha/condições gerais;primeiro resultado indeterminado conservado no histórico. Modelo/HTML correspondem ao snapshot recuperado. Provas Word/PDF/fracções aceites reutilizadas,exportadores e representações monetárias inalterados,sem nova afirmação de paginação.
**Falta conferência visual dirigida do novo delta**:aviso de cessação/condições em falta,escolha e continuidade pelos controlos,gravação/recuperação/relatório da passagem real. Página preparada na mesma origem: `http://127.0.0.1:18639/g3.html`,com controlos explícitos guardar→recuperar→relatório,ficheiro sintético separado deG2L. A ferramenta tem impedimento guardado já documentado;não foi repetida tentativa nem contornado por outra origem. Via manualTempo existente disponível;nenhuma observaçãoG3 foi atribuída àTempo ou aoCodex por antecipação. Os testes API não substituem essa observação.
**Saldo continua36entregues+96funcionaisabertos+P001=133**:dentro dos96,7G3implementados/verificados em código eAPI com visual pendente e89por implementar. Não se somam estes7 aos demonstradosQA. P001 só05/06;calendário/fechos preservados;L1aberto;estatísticas/IAadiadas. Registo `iva_l1_g3_cessation_code_qa_visual_pending_20261024`. Artefactos privados `outputs/iva-l1-g3-temporary-20261024/`.
## 24/10/2026 — Referência explícita da prova visual de G2L
A via de conclusão foi **verificação manual pela Tempo**,autorizada na conversa,depois de a ferramenta doCodex continuar bloqueada. A Tempo comunicou leitura/observação semfalha,assinalou oscontrolos em falta e,depois de corrigido o apoioQA,confirmou ter seguido a instrução guardar→recuperar→abrir relatório. O Codex conferiu o ficheiro real e o percurso técnicoAPI/relatório;isto é corroboração técnica,sem inventar uma captura ou observação própria do navegador. Não se inferem resultados individuais além do comunicado. O ficheiro isolado comprova gravação;recuperação/abertura manuais têm como origem a declaração daTempo.
Referências já existentes no recibo integrado:`iva_l1_g2l_manual_verification_route_20261024`, `iva_l1_g2l_manual_partial_controls_20261024` e `iva_l1_g2l_manual_completion_and_actual_UI_payload_20261024`. Esta explicitação consta agora de `G2L_visual_evidence` no manifesto/reciboG2K/G2L e de `iva_l1_g2l_visual_provenance_clarification_20261024`. A revisão instalada foi conferida separadamente e não substitui prova visual. Sem repetição de ensaios ou reabertura da entrega `ccdecbd8/643ba6ed`.
## 24/10/2026 — G2K/G2L entregues na homologação ccdecbd8
Dois ramos: **P008 / `pharma_manufacturing_inputs`** e **P035 / `annexI_goods`**,disponibilizados em `ccdecbd8` pelo processoGit existente,fast-forward sobre `e45a1394`,após fetch fresco e conferência autenticada.170posiçõesAnexoIII e172AnexoI são opções documentais dentro desses dois ramos;continuidade explícita conserva a identidade e reutiliza os tratamentos9(10) existentes.34ramos anteriores,calendário,S1–S3 e restantes fechos mantidos. Não se declara apuramento integralIVA.
Backup e restauro real isolado:174tabelas/369ficheiros/configuração;contentor semrede e contagens/checksums correspondentes. Após instalação,identidadesPostgreSQL equivalentes confirmam preservação dos dados de negócio,regras,resultados,ficheiros e configuração;diferenças operacionais cache/sessões ficam no recibo.29fichas,28relações e408geometrias conservadas. Zero migrações,importações,alterações de acesso ou execuções privadas sintéticas no activo. Release anterior/backup mantidos;contenção compatível conferida,não aplicada.
Delta instalado conferido porleitura:revisão efectivamente servida,manifesto/hash,marcadores compilados,quatro ficheiros funcionais e simuladorHTTP200. Controlos normais do instalador passaram;provasQA aceites reutilizadas,sem repetição manual. Observação da demonstração e execução dos controlos comunicadas pelaTempo;conferência técnica do ficheiro real/API/relatório peloCodex,sem atribuir a este uma observação de navegador. [Manifesto e recibo de instalação](../simulations/l1-g2kl-delivery-20261024.json). Registo integrado `iva_l1_g2kl_homologation_20261024`,com objectos históricos preservados.
**Saldo:36entregues+96funcionaispendentes+P001documental=133IDs;nenhum ramoQA deste conjunto aguarda entrega.** G2:32ramosentregues. P001 exclusivamente05/06;L1aberto;estatísticas/IAadiadas. Artefactos privados `outputs/l1-g2kl-delivery-20261024/`.
## 24/10/2026 — G2K/G2L preparados após conferência autenticada e restauro
Destino e main frescos em `e45a1394`,sem avanço concorrente detectado. G2K/P008 eG2L/P035 demonstradosQA;dois novos ramos/dois tratamentos,170opçõesAnexoIII e172AnexoI. Provas aceites reutilizadas;origem manualTempo e técnicaCodex conservadas. Quatro ficheiros funcionais,sem migrações,importações,activação de regra fiscal no servidor,alterações de permissões ou outros impostos.
Backup novo `/var/backups/investmoz-l1-g2kl-delivery-20261024/backup`:174tabelas e369ficheiros/configuração verificados;dumpSHA256 `8c6d8f2745ebb3dc6883d67fb8d9810593d47ad44fb0e20859e3547044adee6c`. Restauro real em contentor isolado sem rede,174contagens/checksums correspondentes;zeroescritas de teste no activo. Contenção compatível passou `git apply --check`,não aplicada,conservando catálogo,leitores,histórico e relatórios;release anterior ebackup mantidos.
[Manifesto da entrega](../simulations/l1-g2kl-delivery-20261024.json). Preparação não equivale a instalação:34entregues+2QA+96funcionaispendentes+P001=133. Próxima acção:novo fetch,pushmain semforce pelo processoGit existente e conferência somente do delta instalado. P001só05/06;calendário/fechos preservados;L1aberto;estatísticas/IAadiadas.
## 24/10/2026 — G2L: passagem manual e ficheiro real conferidos; QA concluída
A Tempo comunicou primeiro não encontrar falhas no que leu/observou e, após clarificação dos controlos, confirmou ter seguido as instruções guardar → recuperar → relatório. Esta é a origem da observação manual; não se atribuem pormenores adicionais não comunicados, captura de ecrã ou observação visual pelo Codex. O bloqueio da ferramenta permanece distinto de uma falha do portal e não foi contornado.
O ficheiro real da interface `outputs/iva-l1-g2-agro-annex-20261024/ui-saved-state.json` existe,720228bytes,gravado em24/10/2026 às16:32:44 locais (`14:32:44.805Z`),SHA256 `bfa1b242671b57925d560d1b76a6065a52238f4cbd9f255b17e594384f5e0ef7`. Não foi sobrescrito durante a conferência. Oportunidade321/Manica/MZN/2026-09;10operações;07=800,00;05=200,00;IVA0,00;resultado revisão1 actual. Posições,identidades,qualificadores,origens e versão conservados;12livros anteriores integrais sem recálculo. Relatório derivado desse snapshot com as mesmas funções usadas pelo botão,contexto/data da gravação e correspondência documental conferidos em código.
Passagem técnica nova limitada ao payload real guardado pela interface:POST→GET naAPIprivadaQA isolada `simulator_fiscal_delta_20261021_test:55441`,1teste/29asserções aprovado,guarda de destino e transacção revertida;contexto e snapshot recuperados exactamente. Não se repetiram os ensaios fiscais aceites. A gravação de ficheiro da demonstração e a persistência privada naAPI são provas distintas; não se apresenta uma como substituta da outra.
**G2L/P035 concluído em QA**, candidata funcional `74468283`,em conjunto comG2K/P008 `8882dc54/1fe74256`. O novo registo no recibo integrado é `iva_l1_g2l_manual_completion_and_actual_UI_payload_20261024`. **Saldo34entregues+2QA+96funcionaispendentes+P001=133IDs.** Os172posicionamentos doAnexoI não aumentam o número de ramos. Homologação continua `e45a1394/eb9e0dbc`;não houve instalação. Entrega conjunta depende agora de conferência autenticada fresca do destino,backup/restauro e activaçãoGit existente,com delta apenas. P001 só05/06;calendário e34fechos preservados;L1aberto;estatísticas/IAadiadas.
## Histórico de 24/10/2026 — G2L / P035 antes da passagem manual concluída
**Candidata `744682835a91f08aece9258380466ae746bc7353`; G2L ainda não concluído em QA.** Código executável,4 testesfrontend eAPIprivada1teste/29asserções passaram;tipos/build passaram. Falta a prova dirigida da interface e a conferência visual do relatório. A ferramenta de controlo do navegador bloqueia `http://127.0.0.1:18639` por permissão guardada/política gerida, apesar de autorização recebida e nova tentativa expressamente pedida. Não é uma recusa actual de autorização da Tempo nem pendência jurídica. Não foi tentado contorno por outro porto,navegador,protocolo ou mecanismo. Prova visual não declarada.
### Fonte e cobertura executável
CIVA republicado Lei13/2016,PDF10/p.1426(268),9(12)(h):transmissões de bens de equipamento,sementes,reprodutores,adubos,pesticidas,herbicidas,fungicidas e similares,redes,anzóis e outros aprestos para pesca,constantes da Pauta e discriminados noAnexoI. Artigo19(1),PDF15/p.1426(273):a alínea9(12)(h) não está na enumeração19(1)(b)(v);não presumir direito à dedução por presença no anexo. AvisoBR89/2017,PDF1/p.569,rectifica os anexos. Lei22/2022,art.3(1),PDF4/p.2252(28),substituiAnexoI,PDF5–11/p.2252(29)–(35),efeitos01/01/2023 peloart.6. Sete páginas conferidas visualmente. Lei3/2025 incide em9(13);Lei10/2025art.1 não altera9(12)(h). Âmbito técnico2026/MZN,sem extensão histórica.
`annexI-lei22-2022/1`:172posições distintas,com identidade,código,designação,página e qualificadores originais. A descrição8201.50.00 continua daPDF8para9;ambas são guardadas. O cabeçalho sem código«Outros tractores» acompanha somente as cinco posições8701.91–95,sem ser anexado à descrição do tractor de lagartas8701.30. Não se inventam medições,certificações ou classificações. A confirmação de qualificadores aplica-se apenas aos que a linha exige. A lista inclui bens com destinos específicos de nutrição/indústria: não se impõe um destino agrícola genérico nem integraçãoSNSou declaração9(14),que não pertencem a esta alínea.
### Sobreposições e reutilização dos tratamentos existentes
O cotejo identificou13posições com correspondência potencial a tratamentos9(10) já disponíveis,com consequências no19(1)(b)(v). Não se transforma toda a lista em07. Três designações coincidentes — tomate fresco/refrigerado0702.00.00,farinha de milho1102.20.00 e insecticidas3808.91.00 — encaminham para os tratamentos existentes por escolha explícita,sem fallback07. Dez outras posições dependem da natureza/destino efectivo,por exemplo farinha de trigo versus mistura comcenteio,ou leite em pó industrial versus destino específico a lactente: escolher a continuidade aplicável ou indicar expressamente no fundamento por que o caso pertence apenas a9(12)(h). Desconhecido não presume ausência de outro enquadramento. A correspondência não certifica a mercadoria nem inventa uma prioridade fiscal genérica.
`continueAnnexIOperation` conserva IDda linha,posição doanexo,valor,moeda,preço,período,estabelecimento,descrição e fundamento;acrescenta a origem documental e adopta o IDdo tratamento existente escolhido. Explica o impacto antes do botão e limpa apenas as confirmações que precisam de revisão. O cálculo antigo permanece no histórico;nenhuma passagem é automática. Os leitores,catálogo,chaves e regras dos tratamentos entregues não foram alterados.
### Dados, provas disponíveis e falta delimitada
Reutiliza contexto/localização,moeda,estabelecimento,valor,representação do preço,período e fundamento. Novo opcional `annexIItem`; `annexIOnly` só é pedido onde a intersecção depende dos factos. Pesquisa mantém a selecção; mudar posição conserva dados comuns e exige rever condições específicas. 4testes novos cobrem172posições,qualificadores/continuação/cabeçalho,desconhecido,13intersecções,passagem explícita,conservação dos montantes e relatório/contexto. Fixture congelada preserva12livros completos e actuais, incluindo G2K ecalendáriov2,sem recálculo nem repetição dos ensaios aceites.
APIprivada POST→GET naQAisolada `simulator_fiscal_delta_20261021_test:55441`,com guarda de destino e transacção revertida:1teste/29asserções. Amostra10linhas de100MZN:07=800,00;05=200,00;IVA0,00;contexto321/Manica/2026-09. Duas linhas usam os IDs existentes de tomate/insecticidas após continuidade explícita;mistura comcenteio e leite industrial têm fundamento próprio. Modelo eHTML recuperados com origens/páginas/versão;nenhuma conferência visual desseHTML alegada. Exportadores Word/PDF eprecisão aceites reutilizados,inalterados.
Falta a observação dirigida da pesquisa/selecção de posição, das condições e informação em falta, e da gravação/recuperação com correspondência no relatório; a continuidade aplica-se quando a posição escolhida a apresenta. Decisão expressa da Tempo nesta passagem: a observação pode ser registada como **verificação manual pela Tempo**, separada dos testes automáticos, ou ser feita pelo Codex após revisão da permissão da ferramenta. A autorização na conversa não altera essa permissão guardada. O impedimento da ferramenta não demonstra falha do portal. Não repetir os testes aprovados nem contornar a restrição. A Tempo comunicou observação parcial: não encontrou falhas no que leu e observou, mas não identificou botões de gravação/recuperação. Isto não demonstra essas acções nem autoriza atribuir aprovação individual às verificações não descritas. G2L permanece aberto. Artefactos privados `outputs/iva-l1-g2-agro-annex-20261024/`.
### Observação manual parcial e correcção da demonstração
A leitura do código confirmou uma limitação do apoio de QA: as edições eram mantidas automaticamente no navegador, o botão técnico apenas escrevia um ficheiro e o relatório ligado era estático. «Restaurar exemplo sintético recuperado» repunha a fixture inicial, não recuperava uma gravação feita pela pessoa. A causa aqui identificada é da demonstração; não se declara uma falha nova da persistência do portal. O simulador existente tem gravação automática com estado visível, «Guardar e continuar mais tarde» e recuperação pela identidade do rascunho; a prova privada POST→GET de G2L permanece válida e separada.
Na mesma origem QA `http://127.0.0.1:18639/`, os controlos ficam destacados no topo: **1. Guardar exemplo QA → 2. Recuperar gravação QA → 3. Abrir relatório da gravação recuperada**. A gravação é explicitamente um ficheiro sintético local, sem base de dados do portal; apresenta confirmação/data e erros. A recuperação lê esse ficheiro e pede confirmação antes de substituir entradas divergentes. O relatório usa exclusivamente o snapshot recuperado, com oportunidade e data da gravação, em vez do HTML estático. O cálculo continua no botão existente «Calcular e guardar operações IVA»; a gravação QA não recalcula nem inventa regras. O exemplo inicial e os artefactos API aceites não foram substituídos.
Verificação nova limitada ao apoio QA: compilação da página e ensaio directo de armazenamento em directório temporário, recuperação integral, conservação após gravação inválida e relatório derivado do recuperado passaram. Não foi acedida a origem por outro mecanismo, nem exercido controlo de navegador; não se declara prova visual nem um novo ensaio da API. Falta observar os controlos e a correspondência no relatório; os restantes pontos sem descrição individual da Tempo conservam o seu estado, sem repetição dos ensaios fiscais aceites. A Tempo pode actualizar a página existente; não é necessário refazer a leitura já realizada. Homologação e candidata funcional inalteradas.
### Entrega conjunta preparada, ainda não disponibilizada
[Manifesto G2K/G2L](../simulations/l1-g2kl-delivery-20261024.json):P008eP035,dois ramos/dois tratamentos novos,170+172opções documentais. G2K8882dc54/1fe74256 mantém-se concluído emQA. G2L está emverificação. Fetch fresco confirmou main `e45a1394`,ancestral,sem avanço concorrente detectado. Patch de contenção existente passou `git apply --check`,não aplicado,conserva catálogo/leitores/históricos/API/relatórios. Antes de entregar:prova visual G2L,destino/main frescos,backup/restauro isolado e activaçãoGit existente,seguida apenas da conferência do delta. Não se afirma backup novo nem instalação nesta passagem.
**Saldo permanece34entregues+1QA(G2K)+97funcionaisabertos+P001=133IDs.** Dentro dos97:P035implementado com prova visual pendente e96por implementar. G2:30entregues+G2KQA+G2Lemverificação=32. Código contém74tratamentoscondicionados+2opçõesindeterminadas;isso não declara G2L demonstrado. Homologação permanece na referênciae45a1394/eb9e0dbc;34fechos,calendário eP001apenas05/06preservados. L1aberto;estatísticas/IAadiadas.
## 24/10/2026 — G2K / P008 demonstrado em QA
**Candidata `8882dc54d0973bc058b04009bdbc36c9da2cc31b`; um ramo, um tratamento: `pharma_manufacturing_inputs`.** Homologação permanece em `e45a1394`, recibo `eb9e0dbc`; os34 ramos entregues, incluindo G2I/G2J e calendário, continuam encerrados. L1 aberto; P001 exclusivamente05/06. Estatísticas/IA adiadas.
### Fonte, cobertura e correspondência executável
CIVA republicado Lei13/2016, PDF9/p.1426(267),9(1)(g): transmissão pelo próprio estabelecimento público ou privado integrado no Serviço Nacional de Saúde, de bens a utilizar como matérias-primas, produtos intermédios ou componentes para fabrico de medicamentos, constantes da Pauta e discriminados no AnexoIII. Não basta que o adquirente seja hospital nem o sector do investimento. Sem inscrição, aprovação adicional ou certificação inventadas. Artigo19(1),PDF15/p.1426(273): campo07, isenção sem direito nesta operação; não se deduzem compras automaticamente.
Aviso BR89/2017,PDF1/p.569,rectifica os anexosI/II/III. Lei22/2022,art.3(1),PDF4/p.2252(28),substituiAnexoIII,PDF12–16/p.2252(36)–(40),efeitos01/01/2023 peloart.6. As cinco páginas foram conferidas visualmente. Lei3/2025,art.1,altera9(13),sem alterar9(1)(g)/AnexoIII; Lei10/2025,art.1,enumera alterações sem9(1)(g). Aplicação técnica deste incremento: Janeiro–Dezembro2026/MZN; nenhuma extensão histórica do motor.
Catálogo `annexIII-lei22-2022/1`:170linhas documentais/169códigos distintos, todas com identidade própria, código, designação e página. `2912.19.00` aparece duas vezes com designações diferentes: identidades084/085,sem fusão nem escolha automática pelo código. `2935.` permanece como impresso, sem completar dígitos. Continuações de2827.39.00 e2922.49.00 conservam ambas as páginas. A transposição de letras da camada textual em«Antibióticos» foi ajustada ao texto impresso, sem alterar o original. As demais grafias do exemplar são preservadas; o catálogo não presta classificação aduaneira automática.170linhas não são170ramos nem170desenvolvimentos.
### Dados e percurso
Reutilizados oportunidade,localização,moeda original,estabelecimento,valor,preço líquido/IVA incluído,período e fundamento. Único novo campo fiscal opcional nas linhas deste tratamento: `pharmaAnnexItem`,identidade da posição. Pesquisa por código/designação apenas filtra opções; conserva a selecção actual, mesmo fora do filtro. Os dados antigos dos outros tratamentos não ganham campos obrigatórios. Condições específicas no controlo existente: operação interna, integração do transmitente noSNS, uso no fabrico e correspondência cumulativa código/designação. Desconhecido/código livre/outra edição/anexo/fundamento em falta→indeterminado,sem conversão emzero.
Selecção,identidade/edição/página,condições e fundamento seguem no snapshot e no relatório da oportunidade em tratamento. Alterar para outra linha com o mesmo código torna o resultado anterior histórico; não o substitui automaticamente. Não se alteraram schema,rotas,permissões,fórmulas,calendário nem regras entregues. A chave de actualidade mantém-se limitada aos tratamentos usados em cada livro.
### Provas novas e preservação
3testesfrontend:170linhas enumeradas e rastreáveis,duplicações/posição incompleta/continuações,condições cumulativas,informação insuficiente,moeda/período divergentes,troca entre identidades com o mesmo código,relatório/recuperação. Fixture congelada G2I/G2J preserva11livros completos e actuais sem recálculo, incluindo `production-option/2`. Não foram repetidos os ensaios aceites dos34ramos.
APIprivada POST→GET naQAisolada `simulator_fiscal_delta_20261021_test:55441`,com guarda de destino e transacção revertida:1teste/27asserções. Interface real: pesquisa2912.19 conserva escolha1108.11.00; posição em falta→indeterminado; integração do transmitente retirada→indeterminado; reposta→cálculo/guarda revisão4; actualização do ecrã recupera estado. Payload real da interface→API→recuperação→relatórioHTML visualmente conferido. Cinco linhas de100MZN,preço líquido/incluído,07=500,00;05=0,00;IVA0,00;contexto320/Manica/2026-12;as duas identidades2912.19.00 e2935. preservadas. Tipos/build passaram. Exportadores inalterados: provas Word/PDF/fracções aceites reutilizadas, sem nova afirmação de paginação. Artefactos privados `outputs/iva-l1-g2-pharma-inputs-20261024/`.
### Reconciliação documental, sem implementar G3
Obtido o original oficial integral [BR95/2025,Lei3/2025](../simulations/source-archive/BR-95-I-Suplemento-2025-05-21.pdf),2páginas,origem no arquivo de boletins,hash `e0e682e2c027c3cd9c1d46a73a3f48bc5f6bdbf05667fd97314d7a3f6a456358`. Art.1/PDF1/p.478(1):9(13)a–e e termo31/12/2025;PDF2/p.478(2):9(13)f,art.2 entrada na publicação eAnexoII. Registado no inventário de fontes existente e nas dependências deP038–P043; deixa de ser correcta a pendência«texto integral ainda não obtido». Estes seis IDs continuam funcionais pendentes: transição/cessação e condições por executar; não se prorroga o benefício para2026. Nenhum cálculo deG3 foi activado e nenhum original publicado/importado na base. P045 conserva a dependência específica relativa a9(16),não resolvida por esta fonte.
**Saldo:34 entregues+1QA(G2K/P008)+97funcionais pendentes+P001=133IDs.** G2:32=30entregues+1QA+P035pendente. Motor73tratamentoscondicionados+2opçõesindeterminadas. G2K fica preparado para a próxima entrega conjunta pelo processoGit existente, com destino/main e backup/restauro frescos; esta passagem não declara disponibilização. P00105/06 eL1 permanecem abertos.
## 24/10/2026 — G2I/G2J entregues na homologação e45a1394
Cinco ramos P016/P019–P022, nove tratamentos, disponibilizados em `e45a1394` pelo processo Git existente: fast-forward sobre `d4eae917`, após fetch fresco e conferência autenticada do destino. Calendário de G2I corrigido por Código Civil279(c)/296 e CIVA11(3): termo às24h, último dia do mês quando necessário, declaração antes da expiração e efeitos no Janeiro seguinte sem antecipar permanência mínima. Só as três opções G2I mudam de chave; resultados anteriores preservados no histórico. Os29ramos anteriormente entregues mantêm os fechos.
Backup/restauro:174 tabelas,369 ficheiros/configuração; contentor isolado sem rede. Conferência posterior com identidade PostgreSQL equivalente: dados de negócio, regras, resultados, ficheiros e configuração preservados; diferenças operacionais de cache/sessões documentadas no recibo.29fichas,28relações e408geometrias conservadas. Zero migrações/importações/alterações de acesso e zero execuções privadas sintéticas no activo. Release anterior e backup mantidos; contenção compatível conferida, não aplicada.
Delta instalado conferido por leitura: revisão efectivamente servida, manifesto/hash, nove marcadores compilados, quatro ficheiros funcionais e simuladorHTTP200. Controlos automáticos normais do instalador passaram; provas QA aceites reutilizadas, sem nova ronda manual. [Manifesto/recibo de instalação](../simulations/l1-g2ij-delivery-20261024.json); objectos anteriores do registo integrado conservados intactos.
**Saldo:34 entregues+98 funcionais pendentes+P001 documental=133IDs; nenhum ramo QA aguarda entrega deste conjunto.** G2:30 entregues+2pendentes(P008/P035). Motor72tratamentoscondicionados+2opçõesindeterminadas. P001 exclusivamente05/06; L1aberto; estatísticas/IAadiadas. Artefactos privados `outputs/l1-g2ij-delivery-20261024/`.
## 24/10/2026 — G2I/G2J preparados para entrega conjunta
Candidata QA `72f4187d`; cinco ramos P016/P019–P022, nove tratamentos. Calendário corrigido e G2J demonstrado sem repetir as provas aceites. Consulta fresca de main e destino pelo canal autenticado: `d4eae917`, ancestralidade confirmada e instalador inactivo. Backup novo privado:174 tabelas,369 ficheiros/configuração; restauro real isolado sem rede,174 contagens/checksums correspondentes, zero escrita de teste no activo. Dump SHA256 `a75cb8751146ad0a59ecd62fa13e4d9ede3fd98ad2f4ebda092b48f7c2526c32`.
Delta: componente existente, catálogo, módulo de opção e módulo de manifestações ocasionais. Sem migrações, importações, permissões ou outros impostos. Contenção compatível conferida por `git apply --check`, não aplicada; conserva catálogo, leitores, histórico e relatórios, suspendendo apenas edição/cálculo. Release anterior e backup preservados. Activação pelo processo Git existente, após nova conferência de main; verificar revisão servida, assets e preservação, apenas no delta.
[Manifesto da entrega](../simulations/l1-g2ij-delivery-20261024.json). Preparação não declara entrega:29 entregues+5 QA+98 funcionais pendentes+P001=133. P001 só05/06;L1 aberto;estatísticas/IA adiadas.
## 24/10/2026 — calendário G2I corrigido; G2J demonstrado em QA
**Candidata QA: G2I/G2J, por integrar. Homologação d4eae917/recibo7696af68 inalterada.** Os29ramos entregues continuam encerrados;L1aberto;P001 exclusivamente05/06. Estatísticas/IAadiadas.
### Correcção dirigida do calendário e do regresso (P020–P022)
Fonte conferida visualmente: [Código Civil, exemplar FAO](https://faolex.fao.org/docs/pdf/moz210121.pdf), PDF27/p.1909,279.º,c), termo às24h do dia correspondente ou último dia do mesmo mês; PDF29/p.1911,296.º, aplicação aos prazos legais na falta de regra especial. Original privado SHA256 `a0212d4e3b1bd0f809f63fb69326c13d5e53d953e4653cd2a885ffe6c1ccef83`; consulta não importa/publica nem activa cálculos. CIVA republicado Lei13/2016, PDF11/p.1426(269),11(3), conferido em recorte ampliado: exige entrega da declaração antes de expirar o prazo e fixa efeitos no1Janeiroseguinte. O resumo/código anterior omitira a condição de entrega e invertia a comparação; essa comparação foi corrigida, conservando o histórico.
**29/02/2024+5anos→28/02/2029 às24h.** Uma declaração admissível de2029 produz efeitos em01/01/2030, sem cessação desde o início de28/02. Declaração anterior à opção é divergência; entrega após o termo não tem efeitos presumidos por este tratamento; efeitos que antecipem o fim da permanência mínima são recusados. Sem declaração, a tributação continua, sem caducidade automática. Datas registadas por dia: a data do termo representa o dia até às24h, não o início desse dia. Não foi adicionada convenção de hora de entrega.
Motor específico `production-option/2`; apenas as três opções tributadas deG2I mudam de chave. Snapshots/resultadosv1 continuam guardados como históricos; não são apresentados como cálculo actual v2 nem recalculados automaticamente. Isenção agrícolaP019 não tem opção11 e não depende deste calendário. Restantes provasG2Ife69a16e/a5ac8ca1 reutilizadas.
Provas dirigidas:2testesfrontend (art11 efronteira279c), incluindo termo de2029 e efeitos2030, último dia do mês, viragem de ano, declaração antes do termo, entrega tardia e efeitos prematuros. Verificação de calendário não estende o calculadorIVA além de2026. APIQAisolada `simulator_fiscal_delta_20261021_test:55441`,1teste/10asserções, transacção revertida: datas, versão,48,00MZN e resultado anterior no histórico conservados. Relatório recuperado: início29/02/2020, termo28/02/2025 às24h, ausência expressa de declaração e continuidade tributada emOutubro2026, contexto318/Manica; conferência visual HTML. Provas finais Word/PDF aceites reutilizadas: renderizadores inalterados, sem nova afirmação de paginação. Artefactos `outputs/iva-l1-g2-production-20261024/calendar-*`.
### G2J — P016 angariação ocasional de fundos
Um ramo, dois tratamentos: `fundraising_public` e `fundraising_nonprofit`. CIVA2016PDF10/p.1426(268),9(2)(h); PDF15/p.1426(273),19(1); Lei22/2022art1PDF1/p.2252(25),9(1–3), ePDF2/p.2252(26),10(1–2). Operação interna2026/MZN, campo07, isenção sem direito nesta operação. Exige actividade habitual elegível9(1)a/9(2)a,b,c,d,e,g/9(3)a,b, condições da actividade/entidade, manifestação ocasional em proveito exclusivo e máximo8manifestações/ano por entidade. Não estender a qualquer angariação ou contar vendas como manifestações.
Reutiliza oportunidade/localização/moeda/valor/preço/período e condições/fundamento. Só neste tratamento são pedidos referência da entidade, total anual incluindo actividades fora do dossier, número da manifestação e actividade habitual elegível. Desconhecido/nona manifestação/actividade incompatível→indeterminado; totais divergentes da mesma entidade/ano no livro são explicados, sem substituir dados. O total é declarado, sem alegar cruzamento automático de todos os dossiers.
2testesfrontend novos: entidades pública/sem fins lucrativos,oitava/nona manifestação, retirada individual de condições, actividade incompatível, total desconhecido, totais divergentes e duas vendas na mesma manifestação. Preservados integralmente10livros anteriores:9continuam actuais sem recálculo; sóG2I passa a histórico por mudança deliberada do calendário. APIprivadaQA1teste/10asserções; interface real alterou8→9(indeterminado)→8,cálculo/guarda revisão3→API→recuperação→relatórioHTML,07=200,00MZN,05=0,00,contexto319/Manica/2026-11, fontes/versão e totais anuais1/8. Tipos/buildpassaram. Sem schema/importação/permissão/outro imposto. Artefactos `outputs/iva-l1-g2-fundraising-20261024/`.
**Saldo:29entregues+5QA(G2I4/G2JP016)+98funcionaispendentes+P001=133IDs.** G2:32=25entregues+5QA+2pendentes(P008/P035). Motor72tratamentoscondicionados+2opçõesindeterminadas. Correcção de calendário não cria ID nem fechaP001. Entrega conjuntaG2I/G2J: ainda requer destino/main frescos, backup/restauro, activação pelo processoGit e conferência só do delta; nenhuma instalação declarada nesta passagem.
## 24/10/2026 — G2I produção própria e opção tributada em QA
**Candidata fe69a16eeab6e401c1d02635c873cf8903eafe02; quatro ramos P019–P022, sete tratamentos.** Base instalada d4eae917/recibo7696af68;29ramosentreguespreservadossemreensaios. Homologação inalterada nesta passagem;L1aberto.
| Ramo | Operações / campos | Fonte exacta |
| --- | --- | --- |
| P019 | Produção agrícola,incluindoavicultura/apicultura;05,isençãocomdireitonascondiçõeslegais;semopção11 | CIVA9(7)(a),19(1)(b)(v) |
| P020 | Produçãosilvícola;07isençãoou01/02poropçãoeficaz | CIVA9(7)(b),11,19(1) |
| P021 | Produçãopecuária;07isençãoou01/02poropçãoeficaz | CIVA9(7)(c),11,19(1) |
| P022 | Pesca;07isençãoou01/02poropçãoeficaz | CIVA9(7)(d),11,19(1) |
CIVA republicado Lei13/2016PDF10,p.1426(268),9(7):própriaprodução,recursospróprios;transformaçãoapenasacessória,pelopróprioprodutorsobreprodutospróprios,pormeiosgeralmenteutilizadosnasexplorações.Nãoinferirisençãoapartirdosectorouaplicararevenda. PDF11,p.1426(269),11(1)limitaopçãoàs alíneasb/c/d;11(2)define declaração àDirecçãodaÁreaFiscalcompetente,efeitos1Janeiroanoseguinteouiníciodaactividadesenarespectivadeclaração;11(3)impõeperíodomínimodecincoanos,continuidadeatédeclaraçãoadequadaderegressocom efeitosno1Janeiroanoseguinte.PDF15,p.1426(273),19(1)(b)(v)enumeraapenas9(7)(a)paradireitonaisençãodestegrupo. Lei22/2022art1PDF2,p.2252(26),mantém9(7),taxanormal16%no17(1);Lei10/2025art34paraIVAincluídogeral,semalterar11.Reutilizadoocotejoposteriorregistado;nenhumaautenticaçãogenéricadafonterepetida.
**Dados e regras executáveis:**reutilizamoportunidade,localização,moeda,valor,representaçãodopreço,período,condiçõese fundamento.Sónaopçãotributada aparecem tipo/data da declaração,data de início quando aplicável,data da operação e estado explícito do regresso(nãoexiste/existe/aindadesconhecido);dataderegressoseexistir.Desconhecidonãoéausência;estadonegativocomdataguardadaédivergênciaa resolverexplicitamente.Nãoapagarvaloresocultosnemrepartirmontantesautomaticamente.Daopçãoanualderiva1Janeiroseguinte;opçãonadeclaraçãodeinícioderivadata de início comdeclaraçãonãoposterior;datasfora doperíodo/opçãoineficaz/regressoantesdoscincoanosoujáeficazdãolinhaindeterminada,semreclassificarautomaticamente.Terpassadocincoanosnãocessaopção.Semregressodeclarado,continuaatributação.Data/resultadodaopçãoeficazseguemno relatório e snapshot/histórico. Móduloderegra`production-option/1`,versãoespecíficasónostrêsnovostratamentosoptantes;chavesdosanterioresinalteradas.
**Reutilização da opção:**a origem pode ser escolhida entre as linhas do dossier; não se assume automaticamente a primeira nem a equivalência dos sujeitos passivos. Antes de substituir dados deliberados, a interface explica o impacto e pede confirmação. A data específica da operação de destino é conservada; a origem copiada segue no snapshot e no relatório. Prova dirigida: reutilizar de g2i-2(data da operação15/10) para g2i-4 preservou20/10, com declaração/estado comuns e origem identificada; revisão final5 recuperada pela API.
**Limitação inicial, superada pela correcção acima (registo histórico):**inícioem29/02edeclaraçãoderegressoem28/02doquintoano,semcorrespondênciadeaniversárionocalendário,nãoéresolvidopelasfontesfiscaisconferidas.Permaneceindeterminadonestecaso,sem inventar convenção fiscal;declarar em data inequivocamente posterior ou confirmar a regra de contagem aplicável. Élimitaçãointerna às opções P020–P022,nãonovoIDnemalargamentodeP001;asrestantesdatas/operaçõesavançam.P001continuaexclusivamente05/06.
**Provas dirigidas:**3testesfrontendcobrem7tratamentos,datasanuais/início,efeitosfuturos,regressodeclaradoeficaz,cincoanos,ausênciaexplícita,estadodesconhecido,divergênciadata/estado,calendárioinválido,29/02→28/02indeterminado,regressoposterior,nãocaducidadeealteraçãoqueconservaresultadohistórico.FixturecongeladaG2Hpreservanovecontextosanteriorescomentradas/resultados/chavesactuais,semrecálculo.Naamostra:01=300,00;02=48,00;05=100,00;07=300,00MZN,preçolíquido/incluído.APIprivadaPOST→GET,QAisolada `simulator_fiscal_delta_20261021_test:55441`,guardadedestino/transacçãorevertida,1teste/14asserções;snapshotintegral,datas e campos recuperados.Interface real:opçãoanualde2026→efeitos2027/indeterminado;dataválidareposta→cálculo;regressodesconhecido→indeterminado;ausênciaexplicitada→revisão3guardada;payloadreal→API→recuperação→relatórioHTMLcomdatas/efeitos/versão/valores/contexto318Manica/2026-10.MoedaMZN. Tipos/buildpassaram. Renderizadoresinalterados,provasWord/PDF/fracçõesaceitesreutilizadas,semnovaafirmaçãodepaginação.
**Saldo:**133IDs=29entregues+4QA+99funcionaispendentes+P001documental.G2total32=25entregues+4QA+3pendentes(P008/P016/P035).Motor70tratamentoscondicionados(10iniciais+60dosgrupos),mais2opçõesindeterminadas.Sete tratamentos correspondem a quatro ramos.29fechospreservados;semnovaentreganestapassagem.Estatísticas/IAadiadas.Artefactosprivados `outputs/iva-l1-g2-production-20261024/`.
## 24/10/2026 — G2G/G2H entregues na homologação d4eae917
**Cinco ramos entregues:**P010(segurança por entidade pública),P027(fornecimentos oficiais elegíveis),P031(operações sujeitas aSISA),P032(alienação com três fundamentos) eP026(produtos enumerados9(10)). São24tratamentos(G2G6/G2H18),não24IDs. Revisão efectivamente servidad4eae917,integrada por fast-forward9a56d982→d4eae917apósconsulta fresca do remoto e destino SSH autenticado,semforce. Provas G2G9dbfdd67/2440cb44 eG2H48146089/b297058d reutilizadas;os24anteriores mantêm os fechos. ProcessoGit/webhook/instalador existente;zero migrações/importações/alterações de acesso ou cálculo de outro imposto.
Conferência apenas do delta instalado:revisão/manifesto/hash,catálogo novo nos assets,entrada do simuladorHTTP200,hash do único ficheiro funcional. Controlos automáticos normais do instalador passaram;semnova ronda manual aceita nem execuções privadas sintéticas no activo. Fonte9(10)enumera18opções;direito19(1)(b)(v)conservado sem dedução automática de compras. P032mantémtrêsfundamentos,histórico/fundamentoobrigatórios. SISA nãofoicalculada.
Backup/restauro real isolado descritos abaixo:174tabelas,369ficheiros/configuração. Leitura posterior com a mesma identidade/contextoPostgreSQL confirma dados de negócio/regras/resultados preservados,diferenças operacionais documentadas no recibo.29fichas,28relações,408geometrias e369ficheiros/configuração preservados. Release9a56d982e backup mantidos;patch de contenção compatível,nãoaplicado,conserva catálogo/leitores/snapshots/relatórios;nenhumareversãoexecutada.
**Saldo:**133IDs=29entregues+103funcionaispendentes+P001documental;nenhumramoQAaguardaentreganesteconjunto.Motor63tratamentoscondicionados+2opçõesindeterminadas.G2total32=25entregues+7pendentes. P00105/06permaneceisolado;05/07nãoaresolve.L1aberto;estatísticas/IAadiadas. Manifesto[l1-g2gh-delivery-20261024.json](../simulations/l1-g2gh-delivery-20261024.json);recibo acrescentado no registo integrado sem alterar objectos anteriores. Evidência privada `outputs/l1-g2gh-delivery-20261024/`.
## 24/10/2026 — G2G/G2H preparados para entrega conjunta
Cinco ramos P010/P026/P027/P031/P032,24tratamentos(G2G6/G2H18),sem aumentar IDs por opção. Consulta fresca de main e destino autenticado:9a56d982,ancestralidade confirmada,sem avanço concorrente detectado,instalador inactivo. Backup novo `/var/backups/investmoz-l1-g2gh-delivery-20261024/backup`:174tabelas,369ficheiros/configuração;dump SHA256 `ffe24d9e324cc1ad2354e8feec088e072db437eb54d1f5b6dfd3830865940b40`. Restauro real isolado `l1_g2gh_restore_20261024:55441`,rede desactivada,174contagens/checksums correspondentes,container próprio removido,zero escrita de teste no activo.
Provas G2G9dbfdd67/2440cb44 eG2H48146089/b297058d reutilizadas. Único delta funcional:catálogo `iva-operations.ts`;sem migrações/importações/permissões ou outro cálculo fiscal. Patch de contenção anterior continua compatível,não aplicado;preserva catálogo/leitores/snapshots/relatórios. Activação pelo Git fast-forward/webhook/instalador existente;conferir revisão servida,assets do delta e preservação após instalação. Preparação não declara os cinco ramos entregues. Manifesto[l1-g2gh-delivery-20261024.json](../simulations/l1-g2gh-delivery-20261024.json);P00105/06isolado,L1aberto,estatísticas/IAadiadas.
## 24/10/2026 — G2H produtos enumerados demonstrado em QA
**Candidata 48146089cdcef6ed3c2068b78fc6e48ccac434c8; P026 é um ramo com18tratamentos de produto.** G2G9dbfdd67/2440cb44 permanece com4ramos/6tratamentos emQA para entrega conjunta.24ramos entregues mantêm os fechos;homologação9a56d982inalterada.
**Enumeração executável:**milho,farinha de milho,arroz,pão,sal iodado,leite em pó para lactente até um ano,trigo,farinha de trigo,tomate fresco ou refrigerado,batata,cebola,carapau congelado,petróleo de iluminação,gás domésticoGPL,jetfuel,bicicletas comuns e de ferro até4velocidades,preservativos,insecticidas. Cada opção guarda identidade `listed_*`,natureza/qualificador e fundamento próprios; não se generaliza a todos os alimentos,combustíveis,produtos químicos ou material médico. Texto das bicicletas conserva a enumeração legal,sem inventar nova categoria ou regra de velocidades.
**Fonte exacta:**Lei22/2022,artigo1,PDF2,p.2252(26),9(10),substitui a enumeração2016(incluindo bicicletas comuns e de ferro até4velocidades). CIVA republicado Lei13/2016,PDF15,p.1426(273),19(1)(b)(v),inclui9(10)nasoperaçõescomdireitoàdedução. Reutilizado o cotejo posterior registado;Lei10/2025nãoaltera9e mantém19(1). Âmbito técnico Janeiro–Dezembro2026/MZN. Campo05;isenção comdireito nas condiçõeslegais,nãotaxazero nem dedução automática de compras. P00105/06nãoéresolvidoporestaopção05nem pela distinção05/07.
**Motor e reutilização:**sócatálogodeoperações,comcampos/componentesexistentes;oportunidade/localização,moeda,valor,representação do preço,período e fundamento reutilizados. Sem schema,API,migração,importação,permissão,fórmulaououtroimpostonovo. Seleccionar produto enumerado e completar condições em falta;desconhecido nãoézero nem produto elegível.
**Provas dirigidas:**2testesfrontend novos cobrem18opções,100,00MZNcada,05=1800,00,07=0,00,IVA0,00,preçoslíquidos/incluídos;retiradaindividualdecada condição/fundamento,moeda/períodoincompatível e identidade de produto fora do catálogo→indeterminado. FixturecongeladaG2G preserva oitocontextosanteriores completos eactuais,semrecálculo. APIprivadaPOST→GET,QAisolada `simulator_fiscal_delta_20261021_test:55441`,guardadedestino/transacçãorevertida,1teste/28asserções;18linhas e snapshotintegralrecuperados. Interface real:leite sem confirmação de destino para lactente atéumano→indeterminado;completado→calcular/guardar revisão3;payloadreal→API→recuperação→relatórioHTML. Relatório18linhas,05=1800,00,contexto317/Manica,2026-09,MZN,origem/fontes/versão;semtratamentosdosoutroscontextos. Tipos/buildpassaram. Word/PDF/fracçõesaceitesreutilizados,renderizadoresinalterados,semnovaprova de paginação. Ensaiosdos24entregues eG2Gnãorepetidos.
**Saldo:**133IDs=24entregues+5QA(G2G4/G2H1)+103funcionaispendentes+P001documental.G2total32=20entregues+5QA+7pendentes.Motor63tratamentoscondicionados(10iniciais+53dosgrupos),mais2opçõesindeterminadas.18opçõesnãoacrescentam18IDs. Próximaentrega conjuntaG2G/G2H pelo Git existente com destino/concorrênciafrescos,backup/restauro,activaçãoeconferênciaapenasdelta. L1aberto;estatísticas/IAadiadas. Artefactosprivados `outputs/iva-l1-g2-listed-20261024/`.
## 24/10/2026 — G2G condicionado demonstrado em QA
**Candidata 9dbfdd67ad2d2ad54c9bb8a12fb8dae0f053c226; quatro ramos, seis tratamentos.** Prosseguimento do G2 sobre a entrega9a56d982/recibo541ea704. Os24entregues permanecem encerrados. Reutilizado o motor,os campos,API e relatórios existentes;sem schema,importação,migração ou cálculo de outro imposto. Homologação inalterada nesta prova.
| ID | Tratamento executável / condições específicas | Fonte exacta |
| --- | --- | --- |
| P010 | `public_security`:bens/serviços ligados à segurança pela própria entidade pública definida10(1);não presumir segurança social nem prestador privado contratado | CIVA2016PDF9/p.1426(267),9(2)(b);Lei22/2022PDF1/p.2252(25),9(2)mantido,ePDF2/p.2252(26),10(1) |
| P027 | `official_military_supplies`:material de guerra/aquartelamento,fardamento militar/paramilitar,utilização oficial das Forças de Defesa e Segurança Nacional,actividade exclusivamente para aqueles serviços,estabelecimento reconhecido pelo Ministério competente | CIVA2016PDF10/p.1426(268),9(11);Lei22/2022PDF2/p.2252(26),11mantido |
| P031 | `sisa_subject_operation`:operação sujeita aSISA,mesmo isenta desse imposto,com fundamento identificado;não qualquer operação imobiliária | CIVA2016PDF10/p.1426(268),9(12)(d);Lei22/2022PDF2/p.2252(26),12(d)mantida |
| P032 | Três fundamentos guardados separadamente:`exempt_activity_asset_sale`(afectaçãoexclusivaaactividadeisenta);`no_deduction_right_asset_sale`(inexistênciadedireitoanterior,nãoapenasdireitonãoexercido);`excluded_deduction_asset_sale`(aquisiçãocomexclusão20,identificarnúmero/alíneaeconferirexcepções20(3)) | CIVA2016PDF10/p.1426(268),9(12)(e);PDF15/p.1426(273),20(1);Lei22/2022PDF2/p.2252(26),12(e)mantida,ePDF3/p.2252(27),20(2–3) |
Todos usam07,isençãosemdireitoàdeduçãonestaoperação,àluzdo19(1),CIVA2016PDF15/p.1426(273). O exercício do20nãoé presumido pela falta de factura nem por não ter sido deduzido IVA;histórico e fundamento continuam explícitos. Não se calculou SISA,nem se declarou concluído o loteSISA. Reutilizado o cotejo posterior registado;Lei10/2025art1enumeraalterações3/6/12/18/19/21/23/25/26/27/31/32/33/34,nãoaltera9/10/20;19(1)mantido. Lei22/2022altera20:oconteúdo20(2–3)foiconferido,nãoseusouanumerçãoantiga20(2)paraexcepções. Aplicação técnica Janeiro–Dezembro2026/MZN;semperíodohistóricopresumido.
**Provas novas:**2testesfrontend,6linhas100,00MZN,07=600,00,05=0,00,IVA0,00;ausência individualdecadacondição/fundamento,moeda/períodoincompatível→indeterminado. FixturecongeladaG2F preserva sete livros anteriores completos e actuais,semrecálculo. APIprivadaPOST→GET na QAisolada `simulator_fiscal_delta_20261021_test:55441`,guardadedestino/transacçãorevertida,1teste/16asserções. Interface real:histórico da inexistência de direito não confirmado→indeterminado;completado→calculado/guardado revisão3;payloadreal→API→recuperação→relatórioHTML. Relatórioseislinhas,600,00no07,contexto316/Manica,2026-08,MZN,origem/fontes/versão,semtratamentosdosoutroscontextos. Tipos/buildpassaram;renderizadoresinalterados;Word/PDF/fracçõesaceitesreutilizados,semnovaafirmaçãodepaginação. Nãoforamrepetidosensaiosdos24entregues.
**Saldo:**133IDs=24entregues+4QA+104funcionaispendentes+P001documental.G2total32=20entregues+4QA+8pendentes.Motor45tratamentoscondicionados(10iniciais+35dosgrupos),mais2opçõesindeterminadas. P00105/06isolado;L1aberto;estatísticas/IAadiadas. PróximaentregaGitconferiráapenasdeltaapósbackup/restauro/destinofresco,preservandocatálogo/leitores/histórico. Artefactosprivados `outputs/iva-l1-g2-conditional-20261024/`.
## 24/10/2026 — explicitação dos três ramos G2F entregues
G2F corresponde exactamente a `AUD-SIM-L1-P023` → `special_tax_games` (jogos/operações sujeitos ao imposto especial sobre o jogo), `AUD-SIM-L1-P028` → `stamped_values` (transmissão de valores selados, redacção2022) e `AUD-SIM-L1-P037` → `public_passenger_transport` (transporte público de passageiros). Os três usam07 nas condições demonstradas; não calculam o imposto especial. Revisão instalada9a56d982,recibo541ea704. G2E elevou17→21 e G2F21→24;sete ramos entregues no mesmo conjunto,sem repetir provas. P00105/06 permanece aberto. Corrigida somente a referência de pasta das provas G2F em três linhas da matriz para `outputs/iva-l1-g2-services-20261024/`;o estado de entrega mantém-se.
## 24/10/2026 — G2E/G2F entregues na homologação9a56d982
**Sete ramos entregues:**P023/P028/P033/P034/P036/P037/P044, sete tratamentos condicionais. Integração por fast-forward3b788ec0→9a56d982,semforce,após consulta fresca do remoto e destino SSH autenticado. ProvasQA G2E33d18b9e/30760cab eG2F8171c799/9b0f4370 reutilizadas;os17anteriores mantêm os seus fechos. Processo Git/webhook/instalador existentes;sem migrações/importações/alterações de acesso ou cálculo de outros impostos.
Revisão efectivamente servida9a56d982,manifesto/hash e marcadores das sete opções nos assets conferidos;entrada do simuladorHTTP200. Controlos automáticos normais do instalador passaram,sem repetir rondas manuais aceites. Não se criaram execuções/dossiers sintéticos no activo. Hash do único ficheiro funcional corresponde ao manifesto.
Backup novo e restauro real isolado descritos abaixo:174tabelas e369ficheiros/configuração. Conferência posterior por leitura PostgreSQL sob a mesma identidade/contexto;dados de negócio/regras/resultados preservados,diferenças operacionais documentadas no recibo.29fichas/28relações/408geometrias e369ficheiros/configuração preservados. Release3b788ec0 ebackup mantidos;contenção compatível conserva catálogo/leitores/snapshots/relatórios;nenhuma reversão executada.
**Saldo:**133IDs=24entregues+108funcionaispendentes+P001documental;nenhumramoQAaguardaentreganesteconjunto.Motor39tratamentoscondicionados+2opçõesindeterminadas. P00105/06permaneceisolado;a distinção05/07nãoaresolve. L1aberto;estatísticas/IAadiadas. [Manifesto](../simulations/l1-g2ef-delivery-20261024.json);recibo acrescentado ao registo integrado,sem alterar objectos anteriores. Evidência privada `outputs/l1-g2ef-delivery-20261024/`.
## 24/10/2026 — G2E/G2F: destino e backup/restauro conferidos
Leitura SSH autenticada confirmou main/revisão instalada/current3b788ec0 e instalador inactivo; consulta remota fresca sem avanço concorrente. Conjunto G2E33d18b9e/30760cab eG2F8171c799/9b0f4370 compatível por ancestralidade. Backup novo `/var/backups/investmoz-l1-g2ef-delivery-20261024/backup`,174tabelas e369ficheiros/configuração verificados; dump SHA256 `e23ea1909ede1cb3be7a5e5751f5580e8b8c0b2452c53772c8e28d06ec999b20`. Restauro real isolado `l1_g2ef_restore_20261024:55441`,rede desactivada,174contagens/checksums correspondentes,container próprio removido;zero escrita de teste na base activa.
Pronto para activação pelo Git/webhook/instalador existentes. Único ficheiro funcional alterado:catálogoIVA;sem migrações/importações/permissões ou cálculo de outro imposto. Provas QA reutilizadas;patch de contenção compatível,não aplicado;conserva catálogo/leitores/snapshots/relatórios. Manter release anterior e backup;verificar apenas revisão servida,delta e preservação após instalação. Esta preparação ainda não declara os sete ramos entregues. P001permanece05/06;L1aberto.
## 24/10/2026 — entrega conjunta G2E/G2F preparada; autenticação necessária
G2E33d18b9e/30760cab e G2F8171c799/9b0f4370: sete ramos P023/P028/P033/P034/P036/P037/P044, sete tratamentos condicionais. `git fetch origin` confirmou main3b788ec0, ancestral da candidata, sem alterações concorrentes detectadas. Só o catálogo `iva-operations.ts` constitui delta funcional; sem migrações/importações/permissões ou cálculo de outro imposto. Provas válidas de ambos os grupos reutilizadas; patch de contenção anterior continua compatível por `git apply --check`, não aplicado.
Manifesto [l1-g2ef-delivery-20261024.json](../simulations/l1-g2ef-delivery-20261024.json). Próximas acções dependentes do canal autenticado: destino/revisão/instalador, backup novo/restauro isolado, nova consulta a main imediatamente antes do fast-forward, activação pelo processo Git e conferência apenas do delta instalado/preservação. A sessão SSH anterior está encerrada; nenhuma credencial é guardada. Não foi actualizado main nem instalada esta candidata nesta preparação. Saldo17entregues+7QA+108funcionais+P001=133;homologação3b788ec0;L1aberto. P00105/06 permanece distinto de05/07. Estatísticas/IAadiadas.
## 24/10/2026 — G2F operações por natureza em QA; G2E preservado
**Candidata 8171c7992e3254924545c617a8bfdd812bd7788c; três ramos P023/P028/P037, três tratamentos.** Continuação do agrupamentoG2. G2E33d18b9e/30760cab mantém quatro ramos emQA; os17entregues em3b788ec0 permanecem encerrados. Sem nova disponibilização nesta prova.
| Ramo | Operação e condições | Fonte / correspondência |
| --- | --- | --- |
| P023 | Exploração/prática de jogos de fortuna/azar ou diversão social na legislação própria, respectivas comissões e operações sujeitas ao imposto especial, incluindo títulos de apostas/bilhetes de ingresso; identificar fundamento da sujeição especial | CIVA9(8);07,sem direito à dedução nesta operação |
| P028 | Transmissão de valores selados, identificados; sem abranger automaticamente comissões/serviços autónomos | CIVA9(12)(a),redacçãoLei22/2022;07 |
| P037 | Serviço de transporte público de passageiros, não inferido apenas da entidade pública; discriminar de mercadorias,locação ou serviços autónomos | CIVA9(12)(j);07 |
**Cotejo:** Lei13/2016/CIVA PDF10/p.1426(268),9(8),9(12)(a/j);PDF15/p.1426(273),19(1). Lei22/2022art.1 PDF2/p.2252(26) mantém9(8),9(12)(j),mas substitui9(12)(a) por “as transmissões de valores selados”. A menção antiga a selos pelo valor facial/comissões de venda não é transportada automaticamente para2026; comissões exigem enquadramento próprio. Não foi inventado limite de preço nem autorização pública adicional. Renúncia11/Lei13PDF11afecta9(7)(b–d),nãoestesramos. Cotejo posterior já aceite reutilizado:Lei16/2020afecta9(13);Lei10/2025nãoaltera9nem19(1). Âmbito técnico Janeiro–Dezembro2026/MZN. P001 permanece documental05/06;05/07nãoaresolve. O imposto especial sobre o jogo é condição de enquadramentoIVA,não novo cálculo desse imposto; permanece no inventário fiscal próprio.
**Execução e provas:** catálogo existente recebe três opções/condições,sem schema,migrações,importações,permissões,API ou fórmulas novas. Reutiliza oportunidade/localização,moeda,valor,período,base líquida/incluída e campos de fundamento.2testesfrontend novos:3linhas100,00MZN,07=300,00,05=0,00,IVA0,00; ausência individualdecada condição/fundamento ou período/moeda incompatível→indeterminado. FixturecongeladaG2E preserva seis livros anteriores completos e chaves actuais,semrecálculo. APIprivadaPOST→GET,QAisolada `simulator_fiscal_delta_20261021_test:55441`,guardadedestino/transacçãorevertida,1teste/13asserções. Interface real:retirar confirmação de sujeição especial→indeterminado;completar→calculareguardar revisão3;payloadreal→API→recuperação→relatórioHTML. Relatório confere trêslinhas,300,00no07,contexto315/Manica,2026-07,MZN,origem/fontes/versão. Tipos/buildpassaram. Word/PDF/fracções aceites reutilizados,renderizadoresinalterados,semnovaprova de paginação. Ensaios dos17entregues eG2Enãorepetidos.
**Saldo:**133=17entregues+7QA(G2Equatro/G2Ftrês)+108funcionaispendentes+P001documental. G2total32=13entregues+7QA+12pendentes.Motor39tratamentoscondicionados=10iniciais+29dosgrupos,maisduasopçõesindeterminadas. NenhumIDeliminado/fundido. Entrega conjuntaG2E/G2F a preparar pelo Git existente,conferênciafrescadodestino/concorrência,backup/restauro eapenasdelta. L1aberto;estatísticas/IAadiadas. Artefactos privados `outputs/iva-l1-g2-services-20261024/`.
## 24/10/2026 — G2E agropecuário demonstrado em QA
**Candidata 33d18b9efc7afac2271187dd9db8165289659b37; quatro ramos P033/P034/P036/P044, quatro tratamentos.** Continuação do G2 existente sobre a entrega3b788ec0/recibo0aac0d15;17ramos entregues preservados,semrepetirensaiosaceites. Homologação inalterada;L1aberto.
| Ramo | Operação/condições | Correspondência |
| --- | --- | --- |
| P033 | Bens resultantes da produção industrial de rações para animais de reprodução e abate para consumo humano | 05;9(12)(f),19(1)(b)(v),comdireitoàdeduçãonascondiçõeslegais |
| P034 | Grão de soja,bagaço de soja,soja integral,farinha de peixe,farinha de carne,pós de osso,monofosfato de cálcio,lisina,metionina;matéria-prima para essa produção industrial/destino | 07;9(12)(g),19(1),sem direito nesta operação |
| P036 | Agulhas,seringas e medicamentos de uso veterinário | 07;9(12)(i),19(1),sem direito nesta operação |
| P044 | Abertura de canais,ceifa,drenagem,água para irrigação,limpeza de valas de drenagem,pulverização da terra,efectuadas no âmbito agrícola | 07;9(15),19(1),sem direito nesta operação |
**Fonte/período:** CIVA republicado Lei13/2016 PDF10/p.1426(268),9(12)(f/g/i),9(15);PDF15/p.1426(273),19(1),particularmente19(1)(b)(v),que enumera12(f),não12(g/i)nem15. Lei22/2022 art.1 PDF2/p.2252(26) mantém estas alíneas/número. Renúncia11,PDF11/p.1426(269),abrange9(7)(b–d),não estes quatro ramos; não foi acrescentado impedimento genérico por renúncia. Reutilizado cotejo posterior aceite:Lei16/2020afecta9(13);Lei10/2025nãoaltera9/11nem19(1). Aplicação técnica Janeiro–Dezembro2026/MZN;semcálculohistóricopresumido.P001nãoafectaestesramos. Originais já existentes,preservados.
**Implementação:** quatro opções/condições específicas no motor existente;semreconstrução do simulador,novoformulário,schema,API,migração,importação,permissão ou regra fiscal de servidor. Reutiliza oportunidade,localização,moeda,valor,representação do preço,período e campos de fundamento/condições. P033 não confunde isenção com taxa zero nem gera dedução automática de compras:documento,afectação e elegibilidade continuam no percurso próprio de aquisições. Nosoutrosramos,a ausência da enumeração do19(1)éconservada. Nãoestenderabenefícioaqualquerprodutoveterinário,ração,obraoufornecimentodeágua.
**Provas dirigidas:**2testesfrontendpassaram:quatroramos,100,00MZNcada,preçolíquido/incluído;05=100,00;07=300,00;IVA0,00;ausência individualdecadacondição/fundamento,moedaincompatível/períodoforacobertura→indeterminado. FixturecongeladadaQA G2D preserva cinco livros anteriores integralmente,comchavesactuais,semrecálculo. APIprivadaPOST→GET,baseQAisolada `simulator_fiscal_delta_20261021_test:55441`,guardadedestino/transacçãorevertida,1teste/14asserções,snapshotintegralrecuperadoe05/07conferidos. Interface real:afectaçãodosinsumosdesconhecida→indeterminado;completada→calculado/guardadorevisão3;payloadreal→API→recuperação→relatórioHTML. Relatórioquatrooperações,contexto314/Manica,2026-06,MZN,origens/fontes/versão;05/07coerentes,semoperaçõesdosoutroscontextos. Tipos/compilação passaram. Renderizadores não alterados;Word/PDF/fracções aceites reutilizados,semnovaafirmaçãodepaginação.
**Saldo:**133IDs=17entregues+4QA+111funcionaispendentes+P001documental.G2total32=13entregues+4QA+15pendentes.Motor36tratamentoscondicionados=10iniciais+26dosgrupos;duasopçõesindeterminadasmantidas. IDsnenhumfundido/eliminado. Estatísticas/IAadiadas. EntregafuturaGitcomconferênciafrescadodestino/concorrência,backup/restauroedelta;nenhumadisponibilizaçãoexecutadanestapassagem. Contençãodeveconservarcatálogo/leitores/snapshots,históricoerelatórios;patchcompatívelanteriornãoseaplicaautomaticamente. Artefactosprivados `outputs/iva-l1-g2-agro-20261024/`.
## 24/10/2026 — G2C/G2D entregues na homologação3b788ec0
**Cinco ramos entregues:**P013–P015/P024–P025, sete tratamentos condicionais. `main` actualizado por fast-forward490527b9→3b788ec0, semforce, após consulta fresca do remoto e destino autenticado, preservando os fechos anteriores. Instalação/activação pelo webhook/instalador existente. Revisão efectivamente servida3b788ec0, manifesto/assets do novo catálogo e entrada do simuladorHTTP200 conferidos; sem novas execuções privadas sintéticas no activo. Controlos automáticos normais do instalador conservaram o processo de entrega; não se repetiram rondas manuais das provas QA aceites.
Backup/restauro real descritos abaixo:174tabelas/369ficheiros. Após instalação,174tabelas comparadas sob a mesma identidade/contextoPostgreSQL; diferenças em cache/sessions e um evento concorrente de consulta do Balcão (`virtual-desk`, `desk_cases`, `consulted`,12:47:35UTC). Conferido separadamente: os645eventos de auditoria anteriores mantêm contagem/checksum exactos; o novo evento foi preservado. Restantes dados de negócio/regras/resultados preservados.369ficheiros/configuração iguais;29fichas,28relações e408geometrias preservadas. Hash do único ficheiro funcional corresponde ao manifesto. Zero migrações/importações/alterações de acesso. Release490527b9 e backup verificado mantidos; patch de contenção compatível disponível, nenhuma reversão executada.
**Saldo:**133IDs=17entregues+115funcionaispendentes+P001documental;nenhumramoQAaguardaentreganesteconjunto. Os12anteriores mantêm o fecho490527b9;cinco novos em3b788ec0. L1aberto;P001não bloqueia independentes;estatísticas/IAadiadas. Recibo acrescentado no registo integrado existente, sem alterar objectos históricos;manifesto[l1-g2cd-delivery-20261024.json](../simulations/l1-g2cd-delivery-20261024.json). Evidência privada em `outputs/l1-g2cd-delivery-20261024/`.
## 24/10/2026 — G2C/G2D: entrega conjunta preparada
Cinco ramos P013–P015/P024–P025, sete tratamentos condicionais, sobre G2C122f4f04/d32ad1e0 e G2D8d127799/c28e290b. Consulta fresca de `origin/main` e destino SSH autenticado:490527b9, ancestralidade confirmada, sem avanço concorrente detectado, instalador inactivo. Único delta funcional: `iva-operations.ts`; sem schema, migrações, importações, permissões ou activação de regras fiscais no servidor. Provas QA aceites reutilizadas, sem nova ronda manual.
Backup novo `/var/backups/investmoz-l1-g2cd-delivery-20261024/backup`:174tabelas e369ficheiros/configuração verificados; dump SHA256 `c11ba51e60cb3ac1cad5411c2aeefcb0adaeadd6fd2c16cd42fd6b63b1449fff`. Restauro real isolado em `l1_g2cd_restore_20261024:55441`, rede desactivada,174contagens/checksums correspondentes; container próprio removido, zero escrita de teste na base activa. Patch de contenção existente continua compatível por `git apply --check`, não aplicado: conserva catálogo/leitores/snapshots/relatórios e suspende entradas L1. Release anterior e backup disponíveis; nenhuma reversão executada.
Activação pelo Git fast-forward/webhook/instalador existentes. Conferência posterior limitada à revisão, manifesto/assets do catálogo, entrada do simulador e preservação de dados/configuração; sem execuções sintéticas no activo. Até confirmação instalada,12entregues+5QA+115funcionais+P001=133;L1aberto. [Manifesto](../simulations/l1-g2cd-delivery-20261024.json). Estatísticas/IAadiadas.
## 24/10/2026 — G2D direitos de autor e publicações em QA
**Dois ramos P024/P025 demonstrados, candidata 8d127799cdb4f6e6bed7c6d42b434361e16bee2d; G2C preservado para entrega conjunta.** Incremento do G2 existente sobre122f4f04/registod32ad1e0. Homologação mantém490527b9;L1continuaaberto.
| Ramo / tratamento | Fonte e condição concreta | Resultado |
| --- | --- | --- |
| P024 / author_rights | CIVA9(9)(a): transmissão de direitos de autor ou autorização para utilização de obra intelectual, efectuada pelo próprio autor, seu herdeiro ou legatário; identificar operação e qualidade | Isenção sem direito à dedução nesta operação;07 |
| P025 / cultural_publications | CIVA9(9)(b): transmissão de jornais, revistas e livros de natureza cultural, educativa, técnica ou recreativa; identificar publicação/natureza, sem generalizar a todo material escolar ou serviço editorial | Isenção sem direito à dedução nesta operação;07 |
**Cotejo:** original aceite Lei13/2016/CIVA, PDF10/p.1426(268),9(9)(a–b); PDF15/p.1426(273),19(1). Lei22/2022 artigo1, PDF2/p.2252(26), mantém9(9) e suas alíneas. Reutilizado o cotejo posterior registado: Lei16/2020 afecta9(13), não9(9);Lei10/2025 não altera9/10 nem19(1). Sem divergência documental dependente deP001 neste recorte; não foi inventada lista de exclusões ou autorização ministerial para estas operações. Aplicação técnica Janeiro–Dezembro2026/MZN; outros períodos permanecem indeterminados.
**Reutilização:** mesmos campos de oportunidade/localização, período, moeda, valor e preço líquido/incluído; acrescentadas apenas as duas opções e condições específicas no catálogo. Natureza da operação, titularidade/natureza da publicação e fundamento/pressuposto são recolhidos pelos campos existentes. Sem schema,importação,migração,permissão,API ou fórmula nova. Uma condição desconhecida não é não aplicabilidade nem isenção presumida; deve ser completada ou revista a classificação.
**Provas:**2testesfrontend novos passam: duas operações,100,00MZNcada,base líquida/incluída,IVA0,00,campo07total200,00; ausência individual de cada condição,fundamento vazio,moeda/período fora da cobertura→indeterminado. Fixture congelada G2C conserva quatro livros anteriores, respectivas entradas/resultados/histórico e chaves actuais sem recálculo; relatório do contexto313 exclui tratamentos dos outros livros. API privadaPOST→GET na baseQAisolada `simulator_fiscal_delta_20261021_test:55441`,guardadedestino/transacçãorevertida,1teste/11asserções; snapshot integral recuperado. Interface real: titularidade sem confirmação→indeterminado;completada→revisão3 calculada/guardada; payload da interface enviado à API→recuperado→relatórioHTML real conferido com linhas/valores,2026-05,MZN,opportunity:313/Manica,fontes/versão. Tipos/compilação passaram. Os12ramosentregues e G2C não foram reensaiados nem recalculados. Renderizadores não alterados; Word/PDF/fraccões aceites reutilizados, sem afirmar nova prova de paginação.
**Saldo:**133IDs=12entregues+5QA(G2CP013–P015;G2DP024–P025)+115funcionaispendentes+P001documental. G2total32=8entregues+5QA+19pendentes. Motor32tratamentoscondicionados=10iniciais+22dosgrupos;duasopçõesindeterminadasmantidas. NenhumIDfundido/eliminado. P001isolado;estatísticas/IAadiadas.
**Próxima entrega conjunta:** G2C+G2D aguardam integraçãoGit autorizada com conferência fresca do destino/concorrência,backup/restauro e apenasdelta. Catálogo é único ficheiro funcional alterado neste incremento; activação comcomponenteexistente. Preservar catálogo/leitores/resultados numa contenção, suspendendo entradas por mudança explícita posterior em vez de eliminar regras usadas. Sem nova entrega ou reversão executada. Artefactos privados: `outputs/iva-l1-g2-publications-20261024/`.
## 24/10/2026 — G2C cultural/associativo executável em QA
**Três ramos P013–P015, cinco tratamentos condicionais, candidata 122f4f04b9e39d28e7b5922142c4ebc6889a68c1; L1 aberto.** Continuação do agrupamento G2 existente, sobre a entrega490527b9/recibo dacda11c. Os12ramos entregues permanecem encerrados; não foram recalculados nem repetidos os seus ensaios. A homologação não foi alterada.
| ID | Operação e condições específicas | Variantes / resultado |
| --- | --- | --- |
| P013 | Visitas guiadas ou não a museus, galerias, monumentos, parques, perímetros florestais, jardins botânicos/zoológicos e similares; pertença a entidade elegível; prestação pela própria entidade e próprios agentes; autorização do organismo sem finalidade lucrativa quando aplicável; bens apenas estreitamente conexos | Pública / sem finalidade lucrativa; campo07 |
| P014 | Cedência de pessoal por instituição religiosa **ou filosófica**, para actividade isenta no CIVA com fundamento identificado **ou assistência espiritual** | Pública / sem finalidade lucrativa; campo07 |
| P015 | Serviços no interesse colectivo dos associados; fins enumerados em9(2)(g); única contraprestação quota fixada nos estatutos | Sem finalidade lucrativa; campo07 |
**Fonte e período:** CIVA republicado pela Lei13/2016, PDF9, página1426(267), artigo9(2)(e–g); PDF15, página1426(273),19(1). Lei22/2022, artigo1, PDF1/p.2252(25), mantém estas alíneas; PDF2/p.2252(26),10(1–2), define entidade pública e as quatro condições cumulativas dos organismos sem finalidade lucrativa. Reutilizado o cotejo registado das alterações posteriores: Lei16/2020 altera9(13), não este recorte; Lei10/2025 não altera9/10 nem19(1). Aplicação técnica limitada a Janeiro–Dezembro2026/MZN, sem cálculo histórico presumido. Originais já existentes no arquivo de fontes; não se importou nem publicou um documento novo.
**Dados e execução:** reutilizam-se contexto da oportunidade, localização, moeda, montante, representação do preço e período; os campos existentes recolhem apenas natureza/entidade, condições específicas e documento ou pressuposto. Não foi reconstruído o simulador nem alterado schema, API, permissão ou regra fiscal de servidor. As quatro condições10(2) reutilizadas são cumulativas: lucros/gestão, escrituração, preços e não concorrência. Ausência de condição ou fundamento dá resultado indeterminado, nunca isenção presumida. Isenção sem direito à dedução nesta operação não constitui isenção geral da entidade nem dedução automática de compras.
**Provas dirigidas:** dois testesfrontend novos cobrem cinco variantes, preços líquidos/incluídos, ausência individual de cada condição, fundamento vazio, moeda/período fora da cobertura, soma500,00MZN no07 e isolamento do relatório. Fixture congelada da prova G2B preserva integralmente os três livros anteriores e respectivas chaves actuais, sem recalcular resultados aceites. API privada POST→GET passou na base QA isolada `simulator_fiscal_delta_20261021_test:55441`, com transacção revertida,1teste/14asserções e guarda do destino. Interface real emQA: retirar quota estatutária→indeterminado; repor→calcular/gravar revisão3; guardar payload real→API→recuperar→relatórioHTML real. O relatório confere cinco linhas,100,00MZN cada,IVA0,00,07=500,00,opportunity:312/Manica,2026-04,origem/artigos/versão. Tipos e compilação passaram. As provas Word/PDF aceites não foram regeneradas: este incremento não altera renderizadores nem representação de fracções; não se declara nova prova de paginação desses formatos.
**Saldo sem fusão de IDs:**133=12entregues+3demonstradosQA+117funcionaispendentes+P001documental. G2 tem32ramos:8entregues+3QA+21pendentes. No conjunto do motor há30tratamentos condicionais (dez iniciais+vinte dos grupos) e duas opções indeterminadas. P001 permanece documental; P016/festas de angariação e restantes grupos continuam nas respectivas dependências, sem bloquear G2C. Estatísticas/IA adiadas.
**Entrega futura:** delta funcional limitado ao catálogo `iva-operations.ts`, activado com o componente existente, sem migração/importação. Reversão deste incremento pelo Git pode retirar as cinco opções conservando leitores, snapshot e histórico; resultados já guardados exigem conservar o catálogo para continuar a ser lidos como actuais, pelo que contenção preferida é suspender entradas por alteração posterior explícita, não eliminar as regras usadas. Não se executou reversão nem nova disponibilização. Artefactos privados deQA em `outputs/iva-l1-g2-cultural-20261024/`.
## 24/10/2026 — entrega conjunta L1 instalada e delta conferido na homologação
**Fecho parcial utilizável instalado em `490527b9`**, candidata funcional `4a35d63c`. Conjunto: motor/classificação L1 inicial, fracções exactas e leitores, G1, G2A e G2B. A activação ocorreu pelo Git/webhook/instalador existentes, sem migrações, importações, publicação/activação de regras fiscais de servidor, alteração de permissões ou de consulta pública. Não equivale ao apuramento integral do IVA nem ao fecho de L1.
**Destino e concorrência:** a sessão SSH autenticada confirmou `installed.json`, symlink actual e revisão construída em1655f57e; instalador inactivo. `git fetch origin` fresco confirmou a mesma revisão remota, sem avanço concorrente; ancestralidade e hashes dos seis ficheiros funcionais conferidos. Publicada a branch do conjunto e actualizado `main` por fast-forward1655f57e→490527b9, sem force. Não se repôs o `main` local antigo nem se substituíram alterações concorrentes. A instalação activou a release490527b9-d41ae12f e conservou1655f57e-fe9d3b11 como release anterior.
**Backup/restauro antes da integração:** novo backup consistente, snapshot exportado da base `teste_investidor:5432`,174tabelas,369ficheiros persistentes/configuração verificados; dump SHA256 `6e9a2b0b350b0effe0812e7e5faa5c9c1886611a50c1be5f8b00515d7ef0c5ea`. Restauro real numa baseQA isolada `l1_joint_restore_20261024:55441`, container sem rede,174tabelas/contagens/checksums correspondentes; sem escrita na base activa. Originais privados e configuração ficaram no backup protegido `/var/backups/investmoz-l1-joint-delivery-20261024/backup`, sem expor valores de segredos. Mantém-se o patch de contenção compatível já ensaiado em QA: suspender edição/cálculo do painel L1, preservando leitores/resultados/relatórios/API/restantes formulários, pelo mesmo processo Git. O patch não está aplicado à release normal; não se executou reversão nem restauro da base activa.
**Instalador e delta:** activação concluída em24/10/2026 às12:30:02UTC; zero migrations/importações. Controlos automáticos normais do pipeline passaram (contrato isolado1teste/3106asserções;59unitários/317asserções;247frontend;compilação). Estes controlos pertencem ao processo de entrega existente; não foram reabertas rondas manuais dos casos aceites. Conferência posterior limitada ao delta instalado: revisão490527b9, hash do manifesto, quatro assets com11marcadores dos grupos/leitores/precisão, entrada actual do simuladorHTTP200 e disponibilidade fiscal existente. Não se criaram dossiers, pedidos ou cálculos sintéticos no activo.
**Preservação:** os seis ficheiros funcionais instalados correspondem aos hashes da candidata. Os369ficheiros persistentes/configuração correspondem ao backup. Comparadas as174tabelas por snapshot e leitura PostgreSQL com a mesma identidade/contexto antes e depois: diferenças apenas em `cache` e `sessions`; as restantes172tabelas, incluindo regras fiscais, drafts/resultados e dados de negócio, mantêm contagens/checksums. Não se declarou perda por visibilidade RLS nem se restauraram essas tabelas operacionais. Permanecem29fichas publicadas,28relações e408geometrias, sem reimportação.
**HTTP403 delimitado, sem mudar acesso:** duas leituras do mesmo URL `/build/revision.json`: cliente urllib padrão→403, `Server:cloudflare`, corpo `error code:1010`; cabeçalhos já usados no processo de entrega (`Mozilla/5.0 InvesteMoz-Delivery`)→200/revisão correcta. A [documentação oficial Cloudflare1010](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-1xxx-errors/error-1010/) identifica recusa pela assinatura do cliente. A evidência delimita a camada e a diferença de cliente; não se afirma inspecção da regra específica no painel Cloudflare. Não há evidência de falha de permissão da aplicação; não foram alterados Cloudflare, Nginx, autenticação, RLS ou âmbito público.
**Saldo:** os12ramos demonstrados passam a entregues na homologação: P003–P007, P009, P011–P012, P017–P018 e P029–P030, com prefixo `AUD-SIM-L1-`. São15tratamentos dos grupos, para12ramos; o motor inclui também os dez tratamentos iniciais já aceites,25tratamentos condicionados no conjunto. Permanecem **120ramos funcionais pendentes +P001documental**:133IDs=12entregues+120funcionais+1documental. P001 não bloqueia tratamentos independentes; os restantes lotes continuam no plano. S1–S3, aquisições08–10/totais condicionados14–18, estabilização276d833a e fechos anteriores preservados. Estatísticas/IA continuam adiadas.
Evidência privada/agregada em `outputs/l1-joint-delivery-20261024/`; manifesto actualizado em [l1-joint-delivery-20261024.json](../simulations/l1-joint-delivery-20261024.json); recibo acrescentado no registo integrado existente, sem alterar os recibos históricos. O commit documental do recibo é posterior à revisão efectivamente instalada, conforme o processo já utilizado.
## 24/10/2026 — G2B social em QA e entrega conjunta L1 preparada
**G2B executável/demonstrado em QA, candidata conjunta `4a35d63c`; entrega preparada, não instalada. L1 continua aberto.** Preservados G1 (`5030116e`/`89ab2883`), G2A (`675cf38f`/`0e644b55`), precisão racional (`689e7cbe`) e provas aceites. Não se repetiram os ensaios de G1/G2A nem se regeneraram os Word/PDF das fracções. O conjunto concluído não depende do fecho dos restantes ramos ou da correspondência de P001.
### G2B — três ramos, seis tratamentos por tipo de entidade
IDs com prefixo `AUD-SIM-L1-`:
| Ramo | Tratamento público | Tratamento sem finalidade lucrativa |
| --- | --- | --- |
| P009 — assistência social/bens estreitamente conexos | `social_assistance_public` | `social_assistance_nonprofit` |
| P011 — actividade habitual de equipamentos sociais e bens/serviços conexos | `social_care_public` | `social_care_nonprofit` |
| P012 — uso de instalações para prática artística/desportiva/recreativa/educação física | `activity_facilities_public` | `activity_facilities_nonprofit` |
**Fonte/período:** CIVA republicado Lei13/2016, art.9(2)(a),(c),(d), PDF9/p.1426(267); art.19(1), PDF15/p.1426(273). Lei22/2022 art.1, art.10(1–2), PDF2/p.2252(26): definição de entidade pública e quatro condições cumulativas do organismo sem finalidade lucrativa. Reutilizado o cotejo das alterações2017/2020/2022/2025 já documentado; não houve nova validação de credibilidade da fonte. Âmbito técnico2026/MZN, operações internas; campo07 condicionado, sem dedução automática de compras ou apuramento integral.
Entidade pública: órgão/instituição da Administração Pública com funções administrativas do Estado nos termos legais. Organismo sem finalidade lucrativa: cumulativamente, não disponibiliza lucros nem interesse dos gerentes nos resultados; escrituração de todas as actividades disponível aos serviços fiscais; preços homologados ou, quando não sujeitos a homologação, inferiores aos comerciais análogos; ausência de concorrência directa com sujeitos passivos. Os controlos de uma entidade pública não exigem as quatro condições próprias do outro tipo. É a definição do artigo10, não um novo aprovador ou requisito organizacional criado pelo Codex.
Acrescem as condições da operação: assistência social e bens estreitamente conexos com fins/objecto reconhecidos; equipamento social enumerado, pertencente à entidade, na actividade habitual, com reconhecimento quando exigido; instalação explorada pela própria entidade e serviço a quem pratica a actividade, sem isenção automática de bilhetes para espectadores, rendas ou revenda. A escolha não decorre apenas do sector ou da designação «associação». A falta de uma condição/fundamento produz indeterminação; não zero nem isenção presumida. Os dados específicos são pedidos nos controlos já existentes, reutilizando contexto, moeda original, período, preço/representação e documentação válida do dossier.
**Refinamento documental P010:** o texto de9(2)(b), na mesma página, diz «ligadas à segurança», prestadas por entidades públicas. A rotulagem anterior «segurança social» foi corrigida na matriz; não se presume que a alínea seja um regime de segurança social. P010 continua pendente, com o mesmo ID e sem cálculo novo. Este refinamento não condiciona as alíneas(a)/(c)/(d).
Provas novas: dois testes frontend para seis tratamentos, todas as condições ausentes individualmente, fundamento ausente, preço líquido/incluído, contexto e relatório; um teste API privada/15asserções com guarda `simulator_fiscal_delta_20261021_test:55441` e rollback. Componente real em QA18629: condições públicas e não lucrativas distintas; retirada a condição de preços do organismo não lucrativo→indeterminação; reposta→seis linhas de100MZN/campo07=600MZN/IVA0, oportunidade311/Manica/2026-03, revisão3. Interface→API→recuperação idêntica→relatório HTML existente. Os livros aceites309/G2A e310/G1 permanecem iguais e legíveis, sem recálculo. Tipos/compilação conferidos apenas para o delta.
**Saldo exacto:**133IDs=**12ramos demonstrados em QA +120funcionais pendentes +P001documental**. Ramos cobertos: P003–P007, P009, P011–P012, P017–P018, P029–P030. Pendentes funcionais: P002, P008, P010, P013–P016, P019–P028, P031–P133. G2 mantém32ramos:8cobertos/24pendentes. G1/G2A/G2B somam15tratamentos para12ramos; com os dez tratamentos iniciais já aceites fora deste saldo, o conjunto oferece25tratamentos determinados sob condições, mais duas opções explicitamente indeterminadas. Não se confundem ramos, tratamentos, grupos ou pendência documental.
### Entrega conjunta — cobertura e dependências concretas
Manifesto executável/reconciliável: [l1-joint-delivery-20261024.json](../simulations/l1-joint-delivery-20261024.json). Inclui o motor L1 inicial, precisão racional e leitores/relatórios necessários, G1, G2A e G2B. Não é possível transportar só as opções novas sem as dependências L1 que ainda não estão na referência remota. Nenhum outro imposto, regime não demonstrado, tratamento de P001, alteração de fontes publicadas, migração, seeder, importação ou mudança de permissões integra a entrega. As fontes/cálculos publicados no servidor não são activados por este pacote.
A referência `origin/main` foi actualizada por `git fetch origin`, terminando em `1655f57e698fef4099c2886069a79cd1c920f792`. O `main` local é anterior e não foi usado como base de reposição. A diferença funcional desde o destino Git limita-se a seis ficheiros JS/TS: painel mensal, componente de operações, fracções, aquisições, motor de operações e consolidação do dossier. Mantêm-se S1–S3, aquisições08–10/totais condicionados14–18, estabilização276d833a, complementos, âncoras/mapas e alterações concorrentes herdadas. A pré-visualização `git merge-tree --write-tree` passou: sem conflitos, árvore igual à candidata e fast-forward possível. O bundle `outputs/iva-l1-g2-social-20261024/l1-joint-4a35d63c.bundle` passou `git bundle verify` (166937bytes), com hash no manifesto; contém a candidata funcional e história desde a base, sendo o recibo final um commit documental posterior. Qualquer avanço remoto antes da publicação exige nova reconciliação do delta, nunca force-push ou substituição do trabalho concorrente.
**Activação preparada:** confirmar revisão servida e backup/restauro válidos do destino no processo existente; actualizar novamente `origin/main`; integrar a candidata/conjunto por fast-forward quando possível ou merge reconciliado; build normal por `npm ci`/`npm run build` e webhook existente. Excluir outputs, basesQA, dados sintéticos, `public/hot`, segredos e dependências locais do artefacto activo. Não há migration/seed/regra fiscal de servidor a executar nem novo sinalizador obrigatório. O painel passa a disponibilizar as opções compiladas no percurso já existente; a condição de cada operação continua explícita. Após instalação conferir só revisão servida/manifesto/asset do simulador e o delta de visibilidade/contexto/leitura, reutilizando os ensaios aceites. Não criar pedidos sintéticos no activo.
A leitura prévia de `https://teste-investidor.tempo.co.mz/build/revision.json` nesta passagem devolveu **HTTP403**. Portanto, não se afirma uma nova conferência da revisão efectivamente servida, de backup activo ou do instalador protegido. A referência1655f57e é a referência Git remota e a última entrega comunicada. O controlo autenticado já existente permite conferir o destino no momento da instalação; não é dependência fiscal nem bloqueio de P001. Nesta passagem não houve push para main, instalação ou escrita no activo.
**Reversão preparada e ensaiada em QA:** [patch de consulta L1](../simulations/l1-joint-readonly-rollback-20261024.patch), verificado por `git apply --check` e pelo componente real em QA. Mantém catálogo, leitores, snapshots/histórico, relatórios, API e restantes formulários; suspende apenas edição/cálculo no painel L1 através de um fieldset desactivado com explicação visível. A consulta dos detalhes e o resultado de600MZN continuam disponíveis. É uma contenção operacional da interface, não uma alteração das permissões da API nem uma regra de negócio. Não está aplicada à candidata normal.
Em incidente: criar correcção Git sobre a revisão instalada, aplicar o patch sem ignorar conflitos, compilar/disponibilizar pelo mesmo processo e verificar apenas suspensão L1+consulta/relatório+demais percursos preservados. Corrigida a causa, reverter apenas esse commit de contenção e disponibilizar novamente. Não restaurar a base nem apagar snapshots para uma reversão de código. Voltar integralmente à revisão1655f57e ocultaria os tratamentos/leitores L1 e não é a reversão preferencial; se exigido por emergência, identificar essa redução e conservar base/originais/histórico para recuperação compatível. O bundle Git preparado transporta a história do conjunto desde a base remota; o recibo fixa candidata, hashes e resultado da pré-visualização. Ainda não é entrega na homologação.
Estatísticas/IA e os restantes lotes permanecem no plano acordado. Não se reabre o concluído para exigir uma nova ronda genérica de aceitação.
## 24/10/2026 — reconciliação dos IDs L1 e incremento G2A de saúde
**Incremento executável em QA, candidata `675cf38f`; L1 aberto; homologação inalterada.** Preservados `5030116e`/registo `89ab2883`, G1 e a apresentação das fracções Word/PDF, aceites pela Tempo com base no relatório. Não se repetiram esses ensaios nem se regeneraram os respectivos ficheiros. As entregas podem reunir conjuntos coerentes/utilizáveis; o fecho de todos os ramos não é condição técnica ou organizacional para entregar um conjunto. Esta passagem prepara QA, sem realizar integração/disponibilização.
### Reconciliação: ramo, tratamento e pendência documental
Os **133 IDs** do inventário original incluem **132 ramos funcionais (`P002`–`P133`) e uma pendência documental (`P001`/D06)**. Todos os IDs desta secção têm prefixo `AUD-SIM-L1-`. Um ramo representa uma cobertura legal/operacional e pode conter vários produtos/variantes. Um tratamento é uma opção executável no motor. Um grupo agrega ramos por regras/dados comuns; agrupar não encerra os ramos nem cria uma aprovação por ID. Não houve eliminação, fusão ou renumeração de IDs.
| Momento | Ramos cobertos em QA | Ramos funcionais pendentes | Pendências documentais | Total de IDs |
| --- | ---: | ---: | ---: | ---: |
| Inventário inicial do saldo, excluindo os dez tratamentos anteriores já aceites | 0 | 132 | 1 | 133 |
| Após G1, candidata5030116e | 4 | 128 | 1 | 133 |
| Após este incremento G2A | 9 | 123 | 1 | 133 |
Portanto, **133−4=129IDs pendentes após G1:128funcionais+P001**. O resumo anterior «128restantes» referia apenas os funcionais e precisava desta distinção explícita. P001 não foi encerrado para produzir a diferença. Os nove ramos cobertos correspondem, nestes dois incrementos, a nove tratamentos; essa correspondência não é presumida para o restante inventário.
| ID | Grupo/incremento | Tratamento executável | Estado/referência |
| --- | --- | --- | --- |
| P017 | G1 | `financial_stamp` | Aceite em QA5030116e; preservado |
| P018 | G1 | `insurance_stamp` | Aceite em QA5030116e; preservado |
| P029 | G1 | `public_waste` | Aceite em QA5030116e; preservado |
| P030 | G1 | `public_funeral` | Aceite em QA5030116e; preservado |
| P003 | G2/G2A | `health_assistive` | Executável/demonstrado em QA neste incremento |
| P004 | G2/G2A | `human_materials` | Executável/demonstrado em QA neste incremento |
| P005 | G2/G2A | `patient_transport` | Executável/demonstrado em QA neste incremento |
| P006 | G2/G2A | `mosquito_nets` | Executável/demonstrado em QA neste incremento |
| P007 | G2/G2A | `medicines` | Executável/demonstrado em QA neste incremento |
| P001 | D06 | Nenhum: correspondência05/06 | Pendente: instrução da edição recebida ou correspondência administrativa expressa aplicável |
Os restantes **123IDs funcionais** são exactamente **P002, P008–P016, P019–P028 e P031–P133** (1+9+10+103). Permanecem na mesma matriz com grupo e dependência próprios; o recibo desta passagem enumera o conjunto exacto e verifica a partição disjunta dos133IDs. G2 mantém32ramos:5cobertos por G2A e27pendentes. Os onze grupos originais mantêm-se; G2A é um subincremento de G2, não um novo grupo nem o fecho integral de G2.
### G2A — fonte, condições e reutilização
**Fonte executada:** CIVA republicado pela Lei13/2016, PDF9, p.1426(267), art.9(1)(b–f); direito à dedução confrontado com19(1), PDF15, p.1426(273). A rectificação de08/06/2017, BR89 PDF1, altera6/14 e anexos, não estas alíneas. Lei22/2022 art.1, PDF1, p.2252(25), mantém9(1)(b–f) por remissão. Lei10/2025 art.1, BR248 PDF12–13, altera outros artigos e19(2), conservando19(1); as isenções destas cinco operações não são convertidas em taxa5% nem em dedução automática de compras. O artigo19(1)(b)(v) não enumera9(1)(b–f).
Conferência adicional de âmbito: [Lei16/2020, art.1, BR246 suplemento, PDF20, p.2414(20), exemplar oficial UFSA](https://www.ufsa.gov.mz/query/Baixar_documento.php?nome=LEI+DO+SISTAFAE+-+LEI+14%2F2020+DE+23+DE+DEZEMBRO) altera9(13), não9(1)(b–f). O nome do download menciona SISTAFE, mas o exemplar completo contém as Leis13–16/2020; identificada a página da Lei16, sem inferir conteúdo do nome. A fonte parlamentar `https://www.parlamento.mz/wp-content/uploads/2025/05/iva.pdf` foi localizada:8páginas sem texto extraível; não usada como lei aprovada nem como regra G2A. Continua por cotejar para a operação temporal correspondente, sem bloquear G2A.
| Tratamento | Informação específica necessária nos controlos existentes |
| --- | --- |
| Compensação da deficiência/próteses/braille | Bem na enumeração e destino conforme categoria: deficiência, membro/órgão, fractura, visão ou audição; não qualquer equipamento médico |
| Órgãos/sangue/leite | Origem humana e natureza da transmissão; não origem animal ou serviço autónomo |
| Transporte de doentes/feridos | Doente/ferido, ambulância ou veículo apropriado e organismo devidamente autorizado; não basta destino hospitalar |
| Redes mosquiteiras | Identificação como rede mosquiteira; não extensão automática a outros bens preventivos |
| Medicamentos/artigos elegíveis | Produto farmacêutico exclusivamente terapêutico/profiláctico ou artigo enumerado da alínea com finalidade higiénica/medicinal/cirúrgica; não qualquer produto vendido por farmácia |
Condição comum: operação interna localizada em Moçambique, distinguindo importação/estrangeiro. Âmbito técnico2026/MZN. Reutilizados oportunidade, moeda original, localização, estabelecimento, período, valor/representação e fundamento já guardados. Acrescentam-se apenas a escolha do tratamento e a confirmação das condições específicas em falta, nos controlos existentes. Não há novos formulários, campos persistidos, schema ou permissões. Uma confirmação/documento pressuposto em QA não é certificação da operação real. A falta de natureza, destino, autorização ou fundamento gera indeterminação; não presume zero nem isenção pelo sector.
P008 não integra G2A: matérias-primas/componentes de medicamentos exigem integração do estabelecimento no Serviço Nacional de Saúde e correspondência com a posição aplicável do AnexoIII, incluindo rectificação2017/alteração2022. Não se acrescenta uma aprovação ou inscrição autónoma à condição legal. Essa verificação afecta P008, não as cinco alíneas independentes. Os outros27ramos de G2 conservam as dependências já registadas. O próximo subincremento pode usar perfis sociais/art.10 ou produtos/anexos após o cotejo específico, sem criar um bloqueio comum a G2.
### Prova dirigida e limites
Dois testes frontend novos cobrem os cinco tratamentos, cada condição ausente, fundamento ausente, preço líquido/IVA incluído isento e relatório/contexto recuperados. Um teste da API privada,13asserções, com guarda nominal `simulator_fiscal_delta_20261021_test:55441` e rollback. No componente real em QA18628, retirada a autorização do transporte: indeterminação; reposta: cinco operações de100MZN, campo07=500MZN, IVA0; snapshot da interface → gravação/API → recuperação idêntica → relatório HTML do exportador existente. O contexto de tratamento é309/Manica/2026-02/MZN; o livro G1 da oportunidade310 mantém-se exactamente igual ao snapshot aceite, sem novo cálculo/teste de G1.
O motor, gravação, recuperação e exportador foram reutilizados. As provas Word/PDF das fracções permanecem aceites e intactas; não são apresentadas como uma nova prova específica dos cinco textos G2A. Apenas o relatório/contexto novo foi conferido neste incremento. Não se declara apuramento integral, dedução automática, submissão à AT, fecho integral de G2/L1 ou entrega na homologação. Estatísticas e IA permanecem adiadas.
## 24/10/2026 — L1: incrementos por regras/dados comuns e primeiro grupo executável
**Continuação exclusivamente em QA, candidata `5030116e`, sobre `689e7cbe`/registo `8719e916`. L1 aberto; homologação inalterada.** Os 133 ramos foram distribuídos, sem duplicação, por onze incrementos funcionais e uma dependência documental. Não são 133 desenvolvimentos nem 133 aprovações. A correspondência individual está na mesma matriz, coluna «Grupo de execução», linhas `AUD-SIM-L1-P001`–`P133`; não foi criada outra matriz/backlog.
| Grupo | Ramos | Regra/dados comuns e próximo incremento |
| --- | ---: | --- |
| G1 — serviços isentos | 4 | Executável em QA: natureza do serviço, entidade, sujeição a Selo quando exigida, fundamento, preço e período. |
| G2 — outras isenções internas | 32 | Classificação de bens/serviços e entidades, anexos, afectação e renúncia apenas quando aplicáveis. Próximo núcleo de classificação. |
| G3 — benefícios temporários | 7 | Calendário, início/termo e alteração expressa. Texto integral Lei3/2025 para açúcar/óleo/sabões; solar com termo31/12/2025, sem presumir prorrogação. |
| G4 — exportações/assimiladas | 19 | Destino, transportador/adquirente, embarcação/aeronave e documentos; perfis partilhados de exportação, transporte e intermediação. |
| G5 — regimes especiais/ofertas | 7 | Regime, beneficiário, localização e finalidade; condições específicas do benefício, sem isenção inferida do mapa. |
| G6 — isenções na importação | 15 | Documento aduaneiro, código, origem, regime e destino. Classificação L1; dedução/documento L2 e direitos L13 conservam âmbito próprio. |
| G7 — bases especiais | 18 | Motor comum de composição: preço/margem/custo, descontos, encargos, comissão, moeda e datas; fórmula por alínea. |
| G8 — territorialidade material | 7 | Lugar dos bens/execução/imóvel, partes/estabelecimento e trajecto; consolidar alterações apenas nas cláusulas afectadas. |
| G9 — transfronteiriços/digitais | 11 | Natureza, residência/estabelecimento, destinatário/utilização e responsável pela liquidação; consolidar Lei10/2025 por operação. |
| G10 — assimiladas/especiais | 9 | Perfis de comissão, stocks, uso próprio, gratuitidade e transmissão de negócio; histórico de dedução quando necessário. |
| G11 — exigibilidade/período | 3 | Calendário comum de entrega, execução, factura, pagamento e adiantamento; mês orçamental não determina sozinho o período fiscal. |
| D06 — correspondência do formulário | 1 | Falta a instrução da edição recebida que distinga05/06 ou correspondência administrativa expressa aplicável. Não bloqueia grupos independentes. |
Sequência proposta após G1: G2 e perfis documentados de G4; G8/G11 para localização e período; G7/G10; G5/G6/G9 conforme a dependência concreta. G3 avança nas operações cuja regra temporal esteja determinada. D06 mantém trilho documental próprio. Cada incremento percorre dados → condições → cálculo/não aplicação/indeterminação → gravação → recuperação → relatório. As linhas conservam as dependências específicas; a tabela não as substitui. A estimativa544–912h continua preliminar, a rever por reaproveitamento medido; não se multiplica por133. SISA/IPRA continuam inventariados, com esforço separado.
### G1 — quatro tratamentos, um incremento comum
Linhas `P017`, `P018`, `P029`, `P030`: operações bancárias/financeiras sujeitas a Selo; seguro/resseguro/mediação conexa sujeitos a Selo; remoção de lixo por entidade pública ou por ela contratada; serviços funerários/cremação e bens acessórios efectuados por entidade pública. Fonte: **Lei22/2022, art.1, CIVA art.9(4),9(6),9(12)(b)/(c), PDF2, p.2252(26)**; natureza de entidade pública definida em10(1), na mesma página; direito à dedução confrontado com CIVA19(1), republicação2016 PDF15, p.1426(273). Aplicação técnica delimitada a2026/MZN, sem alterar taxa/regra fiscal nem activar regra publicada no servidor.
Reutilizados oportunidade, moeda original, estabelecimento, período, preço/representação e documento/pressuposto. Os únicos dados específicos são a escolha do tratamento e a confirmação fundamentada das suas condições, nos controlos já existentes. A sujeição a Selo é condição nas duas operações que a exigem; o cálculo de Selo não integra G1 nem é dependência técnica deste enquadramento. Não se presume isenção de toda a entidade, nem de funerárias privadas ou qualquer serviço de limpeza. Dados insuficientes produzem indeterminação, não zero. Campo07 apenas nas operações enquadradas; sem dedução automática de compras.
Provas novas: dois testes frontend; um teste API/11asserções, transacção revertida em `simulator_fiscal_delta_20261021_test:55441`. No componente real em QA, retirada a condição de Selo: operação/totais indeterminados; reposta: quatro linhas de100MZN, campo07=400MZN e IVA0. O resultado de interface foi guardado/recuperado pela API privada, sem diferença no snapshot, e usado nos exportadores reais. Os dez tratamentos aceites não foram reensaiados.
Preservação: a chave de actualidade passa a depender das regras efectivamente usadas, aceitando também a chave do catálogo anterior. Adicionar regras independentes não invalida o snapshot racional aceite. Teste dirigido confirma que permanece actual e byte a byte inalterado, sem recálculo; alterações das entradas/contexto continuam a invalidar a correspondência.
### Formatos finais — conferência e limite
Conferência dos DOCX produzidos pelo exportador existente e dos PDFs nativos do percurso de impressão, usando o snapshot racional já aceite e o novo resultado G1 recuperado. A suspeita inicial de corte/sobreposição foi afastada pela renderização ampliada: os originais estão legíveis. A alteração experimental de paginação foi retirada, sem mudança nos exportadores. Não se declara uma regressão nem uma correcção inexistente.
Os resultados exactos `20/21`, `1/21`, total base `10102/105` e IVA `5051/1050`, os decimais de apresentação `0.047619`/`4.810476`, MZN, oportunidade Manica, período, fonte e versão permanecem nos ficheiros finais. Prova concluída: DOCX efectivamente renderizados em LibreOffice25.8.3.1 (seis páginas racional, duas G1), com todas as páginas inspeccionadas; PDF nativo Edge (sete páginas racional, três G1). Não se afirma renderização pelo Microsoft Word: a automação local desse programa não terminou; o renderizador alternativo abriu os DOCX reais. O auxiliar bundled falhou inicialmente por falta de pdf2image; usaram-se conversão LibreOffice e renderização PyMuPDF. O registo identifica ficheiros e hashes.
**Saldo:** G1 com quatro ramos executáveis em QA;128ramos funcionais nos outros dez grupos e uma pendência D06. Agrupamento não equivale a implementação dos restantes. Não se declara L1 concluído nem disponibilizado na homologação. Fechos anteriores preservados; IRPC/IRPS e restantes lotes mantêm o plano acordado.
## 24/10/2026 — delta L1: precisão racional, cotejo do campo06 e inventário por operação
**Incremento em QA, candidata `689e7cbe`, sem integração/homologação.** Preservados candidata `544068e8`, registo `d89912e5` e as provas dos dez tratamentos. A Tempo apreciou o relatório comunicado; não lhe é atribuída conferência do manual ou da demonstração. L1 continua aberto. As referências abaixo actualizam os limites correntes, conservando o histórico anterior.
### IVA incluído a5% — pendência de cálculo resolvida, apresentação distinta da declaração
O bloqueio de um decimal periódico era uma escolha técnica inadequada, não uma restrição fiscal da Tempo. Retirado. Para preço brutoG, conserva-se exactamente base=G×20/21 e IVA=G/21, isto é, a identidade aritmética decorrente de contraprestação+5%IVA (CIVA arts.15(10)/17-A, Lei22/2022 art.1/2, PDF3–4, pp.2252(27)–(28)). Não se altera a taxa nem se cria um novo regime. O art.34 na redacção Lei10/2025 (PDF14, p.2180(14)) contém o divisor116: não é usado como fórmula para a taxa5%.
- **Cálculo/persistência:** fracções reduzidas com numerador/denominador inteiros em unidadesMZN, sem ponto flutuante. Exemplo1MZN→base20/21 e IVA1/21. Guardam-se nas linhas e nos totais por período. As parcelas condicionadas14–18 transportam as fracções, sem somar aproximações das linhas.
- **Apresentação:** seis casas, metade para cima, identificadas como apresentação técnica. Mostram-se também as fracções exactas. Exemplo1/21→0.047619; não se perde o resto no valor calculado.21linhas de1MZN produzem IVA total1MZN, não0.999999. A resolução decimal não é precisão limite do cálculo.
- **Regra declarativa:** não determinada por escolher seis casas de apresentação. Esta implementação não afirma como a AT arredonda o campo declarativo a5%, nem bloqueia por isso a simulação. Cálculo, recuperação e relatório estão disponíveis; preenchimento/submissão oficial requerem a regra específica, no recorte declarativo próprio.
- **Preservação:** nova versão `iva-operations-l1/2`; resultados/entradas v1 permanecem guardados e legíveis. Não há recálculo automático dos dez tratamentos aceites. Outra oportunidade conserva a sua versão original, sem alteração. Origem alterada/incompleta não conserva indevidamente uma fracção apresentada como resultado actual.
### Campo06 — cotejo concluído no acervo acessível; correspondência executável ainda pendente
1. **Exemplares recebidos:** DOCX SHA62c198e9/63d45fa8 e `VAT Return.pdf` SHA9c0b99a8, p.1/quadro8:05 «Vendas isentas com direito a dedução»;06 remete para18(1)(b);07 isentas sem direito;08–10 dedução de compras. As instruções/rodapés existentes nos exemplares não discriminam os conjuntos05/06. Originais inalterados; não se repetiu a prova dos restantes campos.
2. **Lei:** CIVA republicado2016 PDF14, p.1426(272),18(1)(b)=imposto devido na importação. PDF15, p.1426(273),19(1)(b)(i–v)=operações que permitem o exercício do direito, com múltiplos ramos; operações no estrangeiro são apenas o subponto(ii). Lei10/2025 PDF13 mantém a estrutura de19(1) e altera19(2). Não se deduz daqui uma regra «todo o estrangeiro vai para06», nem se coloca IVA de importação numa base de vendas.
3. **Formulário antigo da AT:** [e-declaração, Modelo A](https://edeclaracao.at.gov.mz/formularios/iva/view/formulario_iva_ma.aspx), conteúdo oficial indexado consultado24/10:03 contém a remissão18(1)(b),04 isentas sem direito,05 imobilizado,06 existências,07 outros bens/serviços; taxa17%/remissão16. Portanto, a instrução antiga para «campo06» não corresponde ao campo06 da edição recebida. A consulta directa da página terminou em timeout; a leitura é identificada como conteúdo indexado, não sessão preenchida/submetida.
4. **Publicação localizada:** BR72 de15/04/2019, despacho/art.1(a), identificado no índice primário com aprovação do Modelo A e exemplar a17%. O ficheiro integral em `archive.gazettes.africa` respondeu **HTTP403**; não se declara leitura integral nem se usa o índice como instrução inexistente de05/06 da edição recebida. Não se contornou a restrição.
**Conclusão delimitada:** os números pertencem a layouts distintos e a remissão recebida não coincide com o texto legal consultado. A associação do antigo03 ao actual06 por simples deslocamento numérico continua insuficiente, porque existe também05 na edição recebida. Falta a instrução dessa edição que distinga os conjuntos05/06 ou uma correspondência administrativa expressa aplicável. Essa é a dependência de `AUD-SIM-L1-P001`. **Não se declara campo06 resolvido/activado.** A interface explica o cotejo; a localização da operação estrangeira é analisada independentemente desse número. O cálculo das linhas já delimitadas continua disponível; totais que dependem de uma classificação não determinada permanecem indeterminados.
Fontes locais verificáveis: [CIVA2016](../simulations/source-archive/Lei-13-2016-CIVA-BR-156-10-suplemento.pdf), [Lei22/2022](../simulations/source-archive/Lei-22-2022-IVA-republicada-BR-250-2-suplemento.pdf), [Lei10/2025 no BR248](../simulations/source-archive/BR-248-I-Suplemento-1-2025.pdf). A fonte oficial é aceite; a pendência é a correspondência concreta/edição, não nova validação da sua credibilidade nem aprovação jurídica genérica.
### Restante cobertura — operações individualizadas na mesma matriz
A linha-mãeAUD-SIM-INT02 conserva os fechos e passa a remeter para **133 linhas de cobertura `AUD-SIM-L1-P001`–`AUD-SIM-L1-P133` na matriz CSV existente**, sem outro backlog. São ramos legais/operacionais do saldo anteriormente agregado, não133 novos impostos ou lotes. Cada linha identifica operação, artigo/fonte, dependência exacta, dados/condições em falta, próximo incremento e critério de percurso completo; nenhum desses ramos é declarado implementado por este inventário.
Sequência dos incrementos do saldo: **R1** incidência/territorialidade e momento; **R2** isenções internas por natureza/entidade e listas; **R2T** limites temporais/cessação; **R3E** exportações/assimiladas; **R3Z** regimes/benefícios especiais; **R4** bases e composição da contraprestação. Os serviços transfronteiriços/digitais e operações assimiladas constam individualmente emR1D/R1S, não numa linha «outros». **R3I** delimita isenções na importação, conservando os cálculos/documentos/dedução deL2 e os direitos deL13 nos lotes próprios. A dependência06 éD06; o arredondamento declarativo está separado do cálculo racional disponível e do futuro fecho declarativoL3.
As linhas discriminam as alíneas ainda não implementadas dos arts.9,12,13,14,15 e as operações/localizações específicas dos arts.3/4/6/7/8. Produtos abrangidos por anexos exigem posição identificada; açúcar/óleo/sabões e solar têm dependência temporal concreta, sem prorrogação presumida para2026. Fontes antigas com regimes/benefícios especiais têm a alteração aplicável indicada como dependência antes de activar esse ramo. SISA/IPRA permanecemL15/L16 por analisar, esforço separado; não foram implementados nem somados à estimativa preliminar.
### Provas deste delta e estado da entrega
**Seis testes frontend novos aprovados**, exclusivamente no delta: fracções periódicas, total antes da apresentação, gravação/recuperação e preservação do snapshot aceite da primeira oportunidade, totais14–18/relatório, informação insuficiente/origem alterada e não associação automática ao campo06. Não executada novamente a suite dos dez tratamentos aceites.
**API real QA:1teste/10asserções**, base nominal isolada `simulator_fiscal_delta_20261021_test:55441`, guarda de identidade e transacções revertidas. Preenchimento/calculadora real com três preços periódicos1/100/0.02MZN, na segunda oportunidade310→gravação privada→recuperação exacta das fracções/resultados e snapshot309 original→relatório HTML/CSV sem recálculo. Interface distingue fracções e decimais, incluindo total04=5051/1050MZN, apresentado4.810476. Prova visual dirigida apenas ao delta. Sem novo PDF exigido ou regeneração dos PDFs aceites.
TypeScript/build conferidos; código frontend e representação racional reutilizam a API/rascunho e exportador existentes. Nenhum motor/parametrização fiscal publicado, alteração de schema/permissões/dados activos ou entrega na homologação. O recibo integrado `iva_l1_followup_qa_20261024` regista a candidata, artefactos e dependência documental06 ainda aberta. As544–912h continuam preliminares; este refinamento não é medição de esforço nem orçamento adicional aprovado.
## 24/10/2026 — L1 executável em QA: operações de IVA, cobertura e saldo explícitos
**Estado: incremento executado em QA, não entregue na homologação; não é fecho integral de L1 nem do IVA.** Base `e8c39a1b`, descendente da entrega `1655f57e`. Ramo `codex/iva-l1-20261024`; candidata executavel `544068e8`. Preservados os fechos S1–S3, aquisições08–10/totais14–18 e referência `276d833a`. Mantém-se o plano único abaixo; o inventário admite omissões e recebe SISA/IPRA para análise antes do futuro Imobiliário. Nenhum imposto/regra publicado ou activado no destino, schema/configuração/permissões/dados activos alterados.
### Operações efectivamente executáveis
Período técnico deste incremento: Janeiro–Dezembro2026, MZN explícito; não é declaração de expiração legal das fontes. Cada linha mostra artigo, fonte, condições e fundamento/pressuposto; a escolha do sector ou da localização não selecciona automaticamente isenção/taxa.
| Operação incluída | Tratamento/campo | Fonte exacta e condições recolhidas |
| --- | --- | --- |
| Operação interna geral | 16%;01/02; preço líquido ou IVA incluído | CIVA arts.1,6,15(1),17(1–2); Lei22/2022 art.1, PDF3, p.2252(27); Lei10/2025 art.1, art.34, PDF14, p.2180(14). Confirmar localização tributável/regime normal e contraprestação completa sem base especial/isenção/taxa reduzida. |
| Serviços médicos/sanitários privados e estreitamente conexos | 5%;03/04 | CIVA arts.15(10),17-A(a), Lei22/2022 arts.1/2, PDF3–4, pp.2252(27)–(28). Prestador hospitalar privado/clínica/dispensário/similar e natureza do serviço confirmados. |
| Ensino privado reconhecido e operações conexas pelo estabelecimento | 5%;03/04 | CIVA arts.15(10),17-A(b), mesma fonte. Integração no Sistema Nacional de Ensino e reconhecimento ministerial; não aplicar a toda venda autónoma de material escolar. |
| Formação profissional privada e fornecimentos conexos | 5%;03/04 | CIVA arts.15(10),17-A(c), mesma fonte. Confirmar formação/conexão e prestador privado. |
| Lições ministradas a título pessoal | 5%;03/04 | CIVA arts.15(10),17-A(d), mesma fonte. Confirmar título pessoal e matérias do ensino escolar/superior. |
| Exportação de bens pelo vendedor/terceiro por sua conta | Isenção com direito nas condições legais;05 | CIVA art.13(1)(a), republicação2016, PDF12, p.1426(270); art.19(1)(b)(i), PDF15, p.1426(273). Saída efectiva documentada ou pressuposto expresso da projecção; cliente estrangeiro por si só não basta. Não é dedução automática de compras nem classificação genérica «taxa zero». |
| Locação de imóvel para habitação | Isenção sem direito;07 | CIVA art.9(5), Lei22/2022 art.1, PDF2, p.2252(26); condições do art.19(1), republicação2016 PDF15. Não aplicar a hospedagem nem locação comercial/industrial. |
| Serviços médicos/sanitários públicos e estreitamente conexos | Isenção sem direito;07 | CIVA arts.9(1)(a),10(1), Lei22/2022 art.1, PDF1–2, pp.2252(25)–(26), conjugados com art.19(1). Confirmar serviço e natureza pública do prestador. |
| Ensino público reconhecido e operações conexas pelo estabelecimento | Isenção sem direito;07 | CIVA arts.9(3)(a),10(1), mesma fonte. Confirmar integração/reconhecimento, natureza pública e operação efectivamente conexa. |
| Formação profissional pública e fornecimentos conexos | Isenção sem direito;07 | CIVA arts.9(3)(b),10(1), mesma fonte. Confirmar formação/conexão e prestador público. |
Originais legais: [CIVA republicado2016](../simulations/source-archive/Lei-13-2016-CIVA-BR-156-10-suplemento.pdf), [Lei22/2022](../simulations/source-archive/Lei-22-2022-IVA-republicada-BR-250-2-suplemento.pdf), [BR248, Leis7–12/2025](../simulations/source-archive/BR-248-I-Suplemento-1-2025.pdf). As páginas PDF são contadas a partir de1; as páginas impressas estão indicadas separadamente. A leitura identificou que o art.17-A está na **página PDF4**, não3; a referência do novo catálogo foi corrigida antes do registo da candidata. Fontes aceites, sem nova validação genérica de credibilidade.
**Preço incluído:** geral — art.34 na redacção Lei10/2025: base=preço×100/116, arredondada à unidade mais próxima; IVA=preço−base. Escolha técnica explícita no empate: metade para cima. Exemplo QA1161MZN→base1001/IVA160/bruto1161. Reduzido — inversão aritmética dos arts.15(10)/17-A quando exacta até6casas:105MZN→base100/IVA5/bruto105. Não aplicar o divisor116 à taxa5%. Quando a inversão a5% exige arredondamento não delimitado, a linha permanece indeterminada; pode ser usada uma base líquida documentada, sem a inventar. Valores líquidos usam precisão técnica6casas/metade para cima, declarada no relatório, sem afirmar arredondamento final da AT.
### Dados reutilizados e únicos complementos pedidos
- Reutilizados: oportunidade em tratamento, moeda original, localização e rótulos, vendas e meses do plano/tesouraria, representação do preço quando já declarada e fonte do pressuposto. Reutilização não apaga edições deliberadas nem converte moeda.
- Informação adicional por operação, só quando em falta: descrição discriminante, estabelecimento (não inferido do local do projecto), tratamento, condições específicas e documento/pressuposto. Período, valor e preço líquido/incluído são herdados; só são preenchidos quando inexistentes ou divergentes. Nos valores reutilizados, a fonte existente preenche o pressuposto, evitando reescrita.
- Repartição explícita de vendas agregadas conserva total/período/moeda/representação da origem; parcelas devem reconciliar com esse total. Divergência, origem alterada, período fora de cobertura, preço desconhecido ou ausência de condição não gera zero. Uma lista vazia só constitui ausência após confirmação de cobertura do mês.
- Mantidos o rascunho privado, API, idempotência, permissões, relatório/CSV e o armazenamento já existentes: extensão `salesOperations` por oportunidade dentro de `modelo_a_snapshot`, sem novo formulário obrigatório nem schema. Cada recálculo guarda a versão anterior. A execução mensal geral existente continua conservada como execução separada e não é somada novamente às linhas L1.
### Divergências delimitadas e saldo de L1
1. **Campo06:** o exemplar remete para art.18(1)(b), que na republicação2016 PDF14 é imposto devido na importação, enquanto o direito relativo a operações no estrangeiro surge no art.19(1)(b)(ii), PDF15. Não se troca silenciosamente a remissão nem se atribui esse campo a qualquer operação estrangeira. Entrada própria conserva os dados como indeterminados. A pendência não impede calcular as outras linhas; totais que possam depender dela continuam indeterminados.
2. **Preço incluído5% com inversão não exacta:** falta delimitar o método de arredondamento dessa situação, não a existência da taxa ou o cálculo de uma base líquida conhecida. Apenas esse ramo permanece sem resultado.
3. **Outras coberturas ainda por implementar em L1:** restantes isenções dos arts.9/12–14, bases especiais do art.15(2), territorialidade/autoliquidação/serviços digitais e outras operações não enumeradas nesta tabela; não presumir cobertura por seleccionar «Outra operação». O registo da venda é conservado, com informação insuficiente e próximo passo. As remissões temporárias do art.9(13)/(16) não são prorrogadas automaticamente. Importações/deduções parciais/regularizações mantêm os lotes próprios do plano.
4. **Compras afectas a operações reduzidas/isentas/outras:** não reutilizar automaticamente a dedução exclusiva geral do lote08–10 em contexto novo misto. CIVA art.19(2), Lei10/2025 art.1, PDF13, p.2180(13), menciona as operações17-A. Neste incremento, essas parcelas exigem afectação específica em L2; resultados antigos são conservados, não convertidos em dedução universal. Quando a classificação L1 está actual, os seus campos01–07 alimentam o apuramento parcial existente; classificação alterada/incompleta não é substituída pela antiga execução geral nem por declarações de ausência.
### Referências exactas das incompatibilidades legislativas referidas no levantamento
- **IRPC:** Lei12/2025, arts.3/4/6, BR248 suplemento1 **PDF20, p.2180(20)**: revogação dos arts.39,47,75(2),76; transição dos regimes simplificados para contabilidade organizada; entrada01/01/2026. Daqui decorre a incompatibilidade da recomendação corrente dos coeficientes art.47 em2026. Não se presume prazo de transição adicional nem se elimina a possibilidade de regra histórica do respectivo período.
- **IRPS:** Lei11/2025, arts.3/4/6, mesmo BR **PDF18, p.2180(18)**: revogações discriminadas e transição dos sujeitos da segunda categoria dos regimes simplificados; entrada01/01/2026. Não é regra de cálculo mensal derivada dos escalões anuais.
- **IVA:** Lei10/2025, arts.2/3/5, mesmo BR **PDF15, p.2180(15)**: art.53 transitório, revogação das SubsecçõesI/II da SecçãoIV e do art.21(8), entrada01/01/2026. São estes trechos que impedem escolher automaticamente antigos limiares de isenção/simplificado do resumo. Não demonstram a extinção das isenções por operação do art.9, que continuam a ser analisadas separadamente.
- **Taxa geral e reduzida:** Lei22/2022 arts.1/2/6, **PDF3–4, pp.2252(27)–(28)**, arts.17(1)/17-A e início01/01/2023. As condições operacionais não são substituídas pelo exemplo de uma empresa mista do documento descritivo.
### Provas dirigidas e limitações da demonstração
**15 testes frontend aprovados:** sete novos L1 e oito da ligação às aquisições directamente alterada; sem repetir suites S1–S3, mapas, projectos âncora ou outros fechos sem delta. Abrangem cada tratamento enumerado, preço incluído geral e reduzido exacto, preço desconhecido, condições em falta, zero explícito, divergência de moeda/período/origem, repartição, histórico, segunda oportunidade sem alterar a primeira, ligação aos totais e recusa de dedução universal.
**API real:1 teste/13 asserções aprovado**, executado sobre payload calculado na interface, base nominal isolada `simulator_fiscal_delta_20261021_test:55441`, identidade conferida e transacções revertidas. Gravação→mesmoID na repetição idempotente→recuperação exacta; outra conta recusada; fingerprint das regras inalterado. Não é teste de motor servidor L1: os valores projectados são calculados pelo componente frontend e conservados no rascunho privado existente, como no recorte de aquisições; nenhuma nova regra publicada/admitida no consumidor fiscal do servidor.
**Interface:** componente real num ensaio sintético isolado, com12 entradas (dez tratamentos e dois casos indeterminados). Retirar fundamento da linha geral→calcular→IVA indeterminado; repor fundamento→calcular→IVA160; linha privada105 com IVA incluído→base100/IVA5. Guardar estado da interface→API real QA→recuperação→relatório HTML/CSV, sem recálculo na exportação, com montantes, oportunidade309/Manica, estabelecimento, Janeiro2026, artigos/fontes e revisão preservados. Histórico da versão insuficiente permanece guardado. Não se confunde o armazenamento local do ecrã de ensaio com a prova API.
HTML/CSV novos em `outputs/iva-l1-qa-20261024/`, com modelo e payloads sintéticos. Relatório visualmente conferido no browser. Não foi produzido/conferido novo PDF nativo nesta passagem, nem se regeneraram os PDFs aceites. TypeScript e build do incremento conferidos; ficheiros de prova, limitações e estado exacto no recibo integrado `iva_l1_qa_20261024`.
**Esforço:** houve reaproveitamento efectivo do simulador, rascunho/API, permissões e exportador. Não se declara um novo motor ou implementação do orçamento completo40–64h; esse intervalo era preliminar para o âmbito mais amplo de L1. Não existe medição fiável de horas desta passagem. Reestimar o saldo por cobertura remanescente, sem transformar544–912h em prazo contratado nem acrescentar SISA/IPRA ao total sem análise.
## 24/10/2026 — inventário fiscal reconciliado e proposta de fecho antes do Imobiliário
**Estado: análise concluída; lotes abaixo propostos, não implementados nem activados nesta passagem.** Decisão expressa da Tempo: concluir o inventário fiscal acordado antes do Imobiliário. Estatísticas e IA continuam posteriores. A tabela abaixo é a referência única do plano, dentro do manual e da matriz existentes (AUD-SIM-INT02); não constitui uma segunda matriz. As secções anteriores que colocavam todo o IRPC/IRPS em desenvolvimento posterior ao Imobiliário ficam ultrapassadas por esta sequência, mantendo os respectivos factos históricos e fechos.
### O que foi efectivamente conferido
Inventário das pastas autorizadas `Modelos` e `portal do investidor/Notas`, distinguindo originais de temporários de edição; leitura integral do texto de `Impostos e seu tratamento.docx`, do documento IRPC, dos escalões IRPS, da estrutura/células/fórmulas dos dois XLSX e das três páginas do M/22 PDF. O cotejo Modelo A/VAT Return já aceite foi reutilizado. Inventário, hashes e extracções privadas em `outputs/fiscal-inventory-plan-20261024/`; sem importar, publicar, alterar ou recalcular os originais. Os dados preenchidos de terceiros nos exemplares Excel não são pressupostos do investidor e não são reproduzidos neste manual.
- `Impostos e seu tratamento.docx`: SHA256 `aade59537c6c19eb56b017cfc317407d5c6ae758c8a15a390508cd5f6e9ae3ed`. O documento intitulado `O IRPC (Imposto sobre o Rendimento das Pessoas Coletivas) .docx` tem bytes/hash distintos (`4a4668c116c1abae26a334d55e3c9fe508c1ab31aa2a19fe7b88e374c4b34d16`), mas texto extraído integralmente igual: não são duas confirmações independentes.
- `Escalões e Taxas do IRPS.docx`: SHA256 `ea9fdfaf8a8682645e0e3dad3e2e165520783e9f72e8d23acdf684d8359d690e`; contém escalões anuais, não uma tabela mensal de retenção por trabalhador.
- `IRPC_IRPS.xlsx`: guias M/39 IRPC e M/19 IRPS, sem fórmulas. A remissão CIRPS na guia intitulada IRPC exige correspondência própria; um formulário não demonstra um motor de cálculo.
- `Cópia de IRPS-IMOP.xlsx`: sete folhas, uma oculta; 102 fórmulas, 15 referências directas `#REF!` e 18 erros em valores guardados. Inclui M/22, M/20 e anexos. Não serve de oráculo numérico sem reparar e cotejar cada correspondência; os erros não equivalem a zero.
- M/22 PDF versus XLSX: quadro de cálculo 12 versus 10; campo 302 «colecta» e 309 «IRPC liquidado» no PDF aparecem com designações trocadas no XLSX; referências PEC art.71 versus art.66 e base da colecta também diferem. A edição/período e a semântica de cada campo precedem a ligação executável. O modelo antigo não prova que um regime continua disponível em 2026.
Código reconciliado na revisão corrente, descendente da entrega `1655f57e`: consumidor público de regra fiscal limitado ao IVA demonstrado; `custom_planning` é planeamento por pressupostos do utilizador. Cadastro de fontes, parâmetros, expressões, governação e campos de entrada IRPC/IRPS/ISPC/INSS/retenções/aduaneiro-ICE são reutilizáveis, mas não equivalem a consumidores fiscais completos. Não se declara ausência de regras no cadastro protegido a partir desta leitura de código. Não houve novas consultas protegidas, ensaios de aceitação ou alterações ao destino.
### Divergências concretas e efeito delimitado
1. **IRPC simplificado:** o texto recomenda coeficientes 20%/30% do art.47 como solução corrente. A Lei12/2025 revoga esse artigo e determina transição para contabilidade organizada, com entrada em vigor em 01/01/2026. Não implementar esses coeficientes como opção corrente de 2026. Eventual cálculo histórico exige a regra do respectivo período; não se inventa prazo de transição. A Lei11/2025 também altera o enquadramento simplificado da segunda categoria IRPS.
2. **IVA:** o documento alterna limiares de 250.000 e 750.000 e recomenda isenção automática. A Lei10/2025 altera/revoga os antigos regimes e contém transição. Esses números não seleccionam automaticamente o regime em 2026. Operação a 5%, isenção com/sem direito à dedução e taxa zero são situações distintas; saúde/ensino não tornam todos os materiais ou vendas da entidade sujeitos a 5%.
3. **ISPC:** o resumo 3%/4% é incompleto perante a Lei9/2025: há diferentes actividades, escalões, exclusões, opções e tratamentos, incluindo taxas de 5%, 12%, 15% e excesso de volume. Não transformar a descrição em taxa única nem presumir tributação marginal. A elegibilidade é anterior à comparação ISPC/IRPC/IVA.
4. **Retenções e créditos:** nem todo serviço implica retenção uniforme de 20%; natureza do rendimento, residência, sujeito que retém, período, excepções e eventual convenção determinam o cálculo. Distinguir IRPC autónomo de mais-valias do tratamento de despesas não documentadas. Guia M/39, crédito estimado, crédito declarado, reconhecimento, compensação e dinheiro recebido são estados diferentes. Afirmações genéricas sobre original físico carimbado, caducidade de cinco anos, compensação automática ou cruzamento bancário da AT não se tornam restrições do portal sem disposição/procedimento concretamente aplicável.
5. **Selo e encargos:** não foi demonstrada incidência universal de 0,4% sobre toda factura acrescida de IVA. Falta cotejar verba, base, isenções, interacção com IVA e período na tabela aplicável. Exemplos de juros «MIMO + margem», coimas e multas não fornecem parâmetros suficientes. A pendência afecta esses cálculos, não bloqueia os restantes impostos.
6. **Trabalho:** escalões anuais IRPS não são convertidos numa tabela mensal dividindo por 12. As taxas INSS 4% empregador/3% trabalhador têm confirmação operacional oficial para TCO, mas base contributiva, exclusões, período e regime TCO/TCP precisam de correspondência própria. O exemplo de salário líquido que só desconta INSS não é líquido final quando há IRPS.
Fontes oficiais aceites reutilizadas: BR248, suplemento1 de29/12/2025 (Leis7–12/2025), CIVA2016/rectificação2017, republicação2022 e acervo fiscal existente. A origem oficial não requer nova aprovação jurídica genérica: aplicam-se as decisões Tempo de08/10 e22/10. Conferir edição, artigo, período, parâmetros e transições é execução da fonte aceite. Os antigos pedidos genéricos de «Fiscalista» constantes de registos históricos não criam um aprovador adicional para estes lotes.
### Tabela única — situação, lacunas, reutilização, dependências e esforço
Âmbito-base proposto: investimento e obrigações de 2026, com saldos/factos de anos anteriores necessários ao apuramento e respectiva proveniência. A possibilidade técnica de escolher outro ano não demonstra cobertura histórica: recalcular integralmente todos os impostos de2000–2025 ou activar anos futuros não integra implicitamente esta estimativa. Cada lote explicita os períodos que consegue calcular.
As estimativas são **horas de trabalho técnico**, não calendário nem medição já executada. Incluem cotejo específico restante, implementação, persistência/recuperação, relatório, provas dirigidas em QA e preparação/conferência do delta Git. Assumem reutilização da infra-estrutura existente; não incluem espera pela entrega de documentos efectivamente em falta, decisão organizacional nova ou integração externa da AT. Não se contabiliza novamente o IVA fechado. A sequência L1–L14 é proposta; dependências abaixo são concretas, não uma obrigação de bloquear todos os lotes em série.
| Lote / âmbito | Já disponível | Falta implementar de ponta a ponta | Dados reutilizáveis | Dependências concretas | Esforço estimado |
| --- | --- | --- | --- | --- | --- |
| Encerrado — planeamento, S1–S3 e IVA entregue | Planeamento financeiro; moeda original; recuperação por ID; IVA mensal geral líquido MZN/2026; aquisições08–10 no âmbito demonstrado e totais14–18 condicionados | Nenhum saldo nos lotes aceites. Não extrapolar para IVA integral | Vendas, compras, orçamento, custos, tesouraria, dossier por oportunidade, gravação e exportações | Preservar `cd10cccb`/`355656b5`, `1655f57e`/`e8c39a1b` e referência `276d833a` | 0 h de reimplementação |
| L1 — IVA: operações e enquadramento | Vendas mensais e operação interna geral líquida | Classificar operações03–07 e outras situações aplicáveis; IVA incluído, isenções/direito à dedução, taxa reduzida e períodos por linha/estabelecimento | Produtos, vendas, entidade, localização e oportunidade | CIVA e alterações2025; incidência por operação, sem inferir regime de sector/forma jurídica | 40–64 h |
| L2 — IVA: dedução restante e regularizações | Compras08–10, líquido/IVA/bruto, documento, mês e afectação explícita no recorte aceite | Importações documentadas, dedução parcial/pro-rata, exclusões, activos e regularizações12–13; condições por parcela; via de dedução de bebidas13(2), identificada porG4D e ainda não apurada | Compras, activos, fornecedor, documento, calendário, parcela não dedutível | L1 quando determina direito; artigos de dedução e regularização. Importação pode usar documento aduaneiro existente, sem esperar pelo cálculo de direitos de L13 | 48–72 h |
| L3 — IVA: saldo e fecho do Modelo A | Totais14–18 quando todas as parcelas estão determinadas | Campos19–27 aplicáveis, transporte de crédito, rectificações/substituição, imposto a entregar e pedido de reembolso; estados documentados e relação com tesouraria; via de restituição de bebidas13(2), identificada porG4D e ainda não apurada, conforme procedimento próprio | Execuções mensais, parcelas L1/L2, documentos e histórico | L1/L2 para apuramento integral; saldo anterior identificado e procedimento de reembolso aplicável. Pedido não significa deferimento/recebimento | 48–80 h |
| L4 — ISPC: elegibilidade e apuramento | Campos de enquadramento e motor genérico | Regime/actividade/volume elegível, opções/exclusões, escalões/taxas aplicáveis, mínimo, trimestre e retenções específicas; comparação só entre regimes admissíveis | Vendas por actividade, custos, NUIT, natureza jurídica e residência confirmada | Lei9/2025 e regulamentação/período; distinguir receita anual, trimestre e excesso | 40–64 h |
| L5 — retenções IRPC e guias | Documentos de compras/vendas e guia M/39 como exemplar | Rendimento pago/recebido, entidade que retém, residente/não residente/EP, evento temporal, excepções e casos digitais/e-money; guia e comprovativo ligados à operação | Contrapartes, facturas, pagamentos, período, moeda, oportunidade | Artigos aplicáveis por rendimento, taxa/convenção se invocada; corrigir remissões do exemplar. Sem submissão electrónica AT presumida | 32–56 h |
| L6 — IRPC anual: regime normal | Projecções, resultados financeiros, activos e custos | Ponte resultado contabilístico→matéria colectável, custos admitidos/não admitidos, amortizações, perdas fiscais e colecta; correspondência M/20/M/22 | Plano financeiro e dados comuns; L5 para retenções sofridas | Código IRPC e Lei12/2025; exercício fiscal, residência/EP, saldos/perdas com ano e prova; resolver diferenças PDF/XLSX | 48–80 h |
| L7 — IRPC: tratamentos específicos | Contexto sectorial/territorial e fontes cadastradas | Casos identificados: tributação autónoma de despesas e mais-valias, taxas reduzidas/cooperativas, isenções/benefícios e operações especiais com condições rastreadas | Base L6, despesas, activos, relação territorial documentada | Disposição e período por tratamento; localização por si só não concede benefício. Lista de tratamentos aplicáveis explicitada no lote | 48–80 h |
| L8 — IRPC: liquidação e pagamentos | Parcelas L5–L7 e formulários originais | PPC/PEC, deduções/créditos, dupla tributação quando aplicável, saldo anual a pagar/recuperar; calendário e reconciliação com pagamentos | Retenções, colecta, saldos anteriores, pagamentos/comprovativos | Base anterior para PPC/PEC, regras de limitação/transporte; não usar cinco anos ou compensação automática sem cotejo específico | 32–56 h |
| L9 — INSS: contribuição social | Massa salarial agregada e referência TCO3%+4% | Trabalhadores, remuneração/base contributiva, exclusões, empregador/trabalhador, TCO/TCP, declaração e encargos por período | Equipa/custos, entidade e calendário; cadastro de pessoa partilhado com L10 | Regulamento e alterações aplicáveis, natureza do vínculo; confirmar base antes da taxa. Contribuição social, distinta dos impostos | 24–40 h |
| L10 — IRPS: retenção mensal e líquido | Entrada IRPS, custos salariais e escalões anuais documentais | Tabela mensal própria, remunerações/benefícios, situação pessoal relevante, retenção, salário líquido e contribuição ligada a L9 | Mesmo trabalhador/folha salarial, pagamentos e retenções | Tabela mensal do período, residência e condições familiares necessárias; não dividir escalões anuais por12 | 40–64 h |
| L11 — IRPS: apuramento anual e outras categorias | Escalões anuais e exemplares M/19/M/20/anexos | Categorias aplicáveis aos rendimentos documentados, actividade independente, capitais/prediais/mais-valias, englobamento/tratamento autónomo, deduções, retenções e saldo | Dados pessoais autorizados, rendimentos/despesas, activos e L10 | Código IRPS/Lei11/2025, âmbito/categoria/período e deduções pessoais; diferenças de edição dos anexos. Não copiar regras IRPC | 48–80 h |
| L12 — Imposto do Selo | Factos/contratos/documentos financeiros do projecto | Incidências por verba aplicável às operações documentadas, base, taxa/valor fixo, sujeito, isenção e obrigação; explicar não aplicação | Contratos, financiamento, garantias, recibos e contexto do negócio | Código/tabela e alterações da verba/período; resolver exemplo genérico0,4% sem o aplicar a todas as facturas | 24–48 h |
| L13 — direitos aduaneiros | Entrada aduaneira/ICE e fontes no inventário anterior | Classificação pautal, origem, valor aduaneiro, despesas de composição, câmbio explícito e direitos/benefícios aplicáveis | Equipamentos/compras, transporte, seguro, documentos de importação e localização | Pauta/Lei8/2025, código/origem e data. Não inferir código pela descrição livre nem autorização de benefício pela localização | 40–72 h |
| L14 — ICE | Componente de entrada e fonte Lei7/2025 inventariada | Produtos/operações abrangidos, tributação específica/ad valorem/mista quando prevista, base/unidade e período; ligação à importação ou produção interna | Quantidades, produtos, preços, origem e L13 quando importado | Código/tabelas ICE e alterações; ligação à base de IVA somente quando aplicável, sem bloquear produção interna por ausência de cálculo aduaneiro | 32–56 h |
| L15 — SISA e delimitação territorial | Operações/localização do investimento; ainda sem consumidor fiscal específico | Analisar transmissão onerosa/direitos sobre imóveis, âmbito autárquico ou nacional, incidência/isenções/base/período e percurso completo | Imóvel, preço/documento, partes e localização; não equiparar DUAT a propriedade da terra | Cotejo do Código Tributário Autárquico/legislação nacional e alterações; fonte municipal confirma família, não taxa nacional uniforme | Por estimar após análise; não incluído em544–912h |
| L16 — Imposto Predial Autárquico e encargos imobiliários aplicáveis | Localização e orçamento; sem cálculo específico demonstrado | Analisar posse/uso/valor patrimonial, município, exercício e isenções; discriminar taxas administrativas de impostos | Imóvel, uso, entidade e valores documentados | Base legal e tabela da autarquia/período; não converter preço de compra em valor patrimonial | Por estimar após análise; não incluído em544–912h |
**Total preliminar original L1–L14 (L15/L16 ainda por analisar): 544–912 h (68–114 dias-pessoa de8h).** Não é promessa de prazo nem autorização automática de publicação. Rever a estimativa ao fechar o cotejo específico de cada lote, identificando exactamente a alteração. Não há um lote invisível adicional para relatórios ou persistência: fazem parte de cada linha.
Origem do âmbito: IVA, IRPC, ISPC, Selo e INSS constam de `Impostos e seu tratamento`; IRPS consta do documento de escalões e dos modelos. Direitos aduaneiros e ICE já constam do inventário fiscal/entrada existente e do BR248: são mantidos explicitamente na proposta, não atribuídos ao novo texto. Retenções, PPC/PEC, créditos, juros e obrigações são tratamentos das famílias respectivas, não impostos novos. Juros/encargos só são calculados no lote respectivo com facto, base, vencimento e parâmetro legal determinados; caso contrário ficam expressamente não calculados. Reclamações judiciais, minutas avulsas, execução bancária e ligação técnica de submissão à AT não se presumem requisitos de cálculo por aparecerem numa conversa do documento. Outros tributos não identificados neste acervo não são acrescentados silenciosamente ao significado de «terminar».
**Revisão para o futuro Imobiliário:** o inventário anterior era incompleto: faltavam SISA e IPRA explicitados. Acrescentados L15/L16 como recortes por analisar, mantendo a mesma tabela. A informação municipal oficial identifica [SISA imobiliária](https://cmcpemba.gov.mz/impostos-e-taxas/iasisa) e [IPRA](https://cmcpemba.gov.mz/impostos-e-taxas); serve aqui para confirmar a omissão, não para activar taxas. Há inconsistências concretas no índice municipal (descrição de veículos repetida em SISA), pelo que não se transportam essas descrições nem taxas para uma regra nacional. A delimitação legal/autárquica e temporal permanece por cotejar no ramo respectivo. IVA de locação habitacional está em L1; vendas sujeitas a SISA (art.9(12)(d)) e arrendamentos não habitacionais exigem enquadramento próprio; rendas/retenções e mais-valias permanecem L5–L8/L10–L11, contratos/financiamento em L12. Nenhuma destas ligações presume venda de terra ou transmissibilidade do DUAT. Outros encargos municipais efectivamente necessários serão inventariados com fonte e operação, sem acrescentar indiscriminadamente todos os tributos nacionais.
### Critério comum de fecho, aplicado separadamente a cada imposto/lote
1. **Dados:** entrada geral ou ficha herda a oportunidade em tratamento; reutiliza informação válida de perfil/organização/dossier/fontes, conservando autoria e edições. Projecto/localização não substitui residência fiscal. Pergunta apenas o que falta/diverge; valores sem moeda/origem não são convertidos ou reinterpretados silenciosamente.
2. **Enquadramento:** cada ramo tem condição, artigo/fonte, edição e período; distingue aplicável, não aplicável com explicação e informação insuficiente com próxima acção concreta. Cobertura não implementada é pendência do produto, nunca «não aplicável» ao investidor. Uma divergência documental suspende apenas o ramo dependente.
3. **Cálculo:** parcelas e total, arredondamento, limites, zero real e desconhecido são distintos. Caso normal e excepções delimitadas têm exemplos verificáveis, incluindo fronteiras de escalão/período. Crédito não é recebimento e compra não gera automaticamente dedução.
4. **Gravação/recuperação:** mesma execução, ID, oportunidade, pressupostos, parcelas, fonte e versão; permissões conservadas e recuperação independente da admissão de novos cálculos. Alteração posterior cria versão/explica divergência sem reescrever resultado aceite.
5. **Relatório:** ecrã, ficheiro final e recuperação apresentam os mesmos montantes/moeda/período/contexto/versão/fontes e pendências, incluindo paginação dos blocos novos. Dois investimentos: alterar apenas o segundo mantém o primeiro intacto. Provas anteriores sem delta são reutilizadas.
6. **Entrega:** demonstrar o lote em QA isolada, integrar pelo Git preservando alterações concorrentes, conferir revisão servida e apenas o delta/dependências. Sem activar cálculos por importar/publicar fontes e sem simular reconhecimento/submissão da AT. Operações em dados activos mantêm backup/restauro e acção autenticada aplicável.
O fecho integral exige cobertura executável e demonstrada das linhas acordadas, com operações/regimes/períodos discriminados. A ausência de dados de um investidor pode gerar resultado indeterminado correctamente explicado; a ausência de uma regra necessária ou de implementação permanece saldo do lote. As seis associações e os dois originais documentais anteriores não bloqueiam globalmente este plano: só afectam uma regra quando a dependência efectiva for identificada.
**Saldo histórico do levantamento anterior, actualizado pelo incremento L1 acima:** fontes e implementação reconciliadas, divergências e proposta finita registadas; zero alterações funcionais, zero impostos activados e zero novas provas exigidas à Tempo. S1–S3, aquisições08–10/totais14–18 e demais fechos permanecem encerrados. L1 tem agora incremento executável em QA com saldo discriminado acima; L2–L16 não estão implementados por esta passagem.
## 24/10/2026 — aquisições Modelo A entregues na homologação, revisão1655f57e
Lote08–10/14–18 integrado pelo Git existente e instalado em `1655f57e`, candidata `d18ff0f0`. Saldo deste lote zero. Revisão servida, manifesto, quatro assets/nove marcadores, entrada do simulador e disponibilidade existente conferidos apenas no delta. Sem novos pedidos/cálculos privados na homologação ou repetição dos ensaios aceites. S1–S3 `cd10cccb`/`355656b5`, PDF aceite e referência `276d833a` preservados; schema/configuração/regras publicadas sem alteração. Recibo integrado `modelo_a_acquisitions_homologation_20261024`; cotejo, âmbito e condições em `../simulations/modelo-a-reconciliacao-20261021.md`. Não é apuramento integral do IVA; IRPC/IRPS posteriores, estatísticas/IA adiadas. As secções de espera abaixo são histórico.
## 24/10/2026 — lote de aquisições Modelo A concluído em QA, candidata d18ff0f0
S1–S3 mantidos na homologação em `cd10cccb`/`355656b5`. Cotejo do `VAT Return.pdf` concluído:08–10 e14–18 correspondem aos DOCX; selecções/Maputo do PDF não são dados do investidor. Novo bloco no simulador: reutilizar compras/orçamentos explicitamente, completar documento/IVA/afectação/condições, confirmar cobertura por mês, calcular e guardar; a recuperação e o relatório usam a oportunidade escolhida. Ausência de condições/parcelas mantém resultado indeterminado. Mudanças conservam o resultado histórico e explicam a divergência. Regime e moeda não são inferidos da organização.
QA:11 testes frontend, dois testes de API/19 asserções, types/build e cadeia interface → API isolada → recuperação → relatório demonstrados. Segunda oportunidade17=128.0048, primeira144.0048 preservada. PDF novo de seis páginas revisto; provas S1–S3 reutilizadas. Detalhes e limites em `../simulations/modelo-a-reconciliacao-20261021.md`, recibo integrado `modelo_a_acquisitions_qa_20261024`, mesma linhaAUD-SIM-INT02. **Ainda não entregue na homologação.** IRPC/IRPS apenas inventário; estatísticas/IA adiadas.
## 24/10/2026 — próximo âmbito do Modelo A, apenas proposto
S1–S3 encerrados em `cd10cccb`, recibo `355656b5`. Reconciliação actualizada em `../simulations/modelo-a-reconciliacao-20261021.md`: campos01/02 suportados; restantes componentes discriminadas; proposta limitada a operações internas gerais, aquisições08–10 e totais condicionados14–18. Inventário completo das pastas Notas/Modelos no recibo integrado, incluindo IRPC/IRPS sem implementação. Sem novos impostos, regras activadas ou repetição de provas aceites. AUD-SIM-INT02 mantém o saldo de desenvolvimento do Modelo A distinto do lote S1–S3 encerrado.
## Simulador S1–S3 — entregue na homologação em `cd10cccb`, 24/10/2026
Por autorização expressa da Tempo após o fecho QA, integrado pelo Git existente, de `276d833a` para **`cd10cccbf45f53836d8bf7b2bd90794d99602cb9`**, que contém a correcção funcional `65b87819`. `git fetch` não encontrou alterações concorrentes em main; avanço normal, sem force. A referência `276d833a`/`reference/stabilization-20261024` permanece ancestral. Não houve edição da pasta servida nem migração/importação solicitada.
**Delta instalado conferido por leitura pública:** `/build/revision.json` identifica `cd10cccb`; SHA256 do manifesto servido coincide com o da revisão (`7957c776ab2c2eab516bcc6caedcdeb9943184645b4a21a89a4f709a4ba974f6`). Quatro assets do simulador/relatório responderam 200; os bundles contêm a guarda da moeda original, a confirmação explícita e a recuperação por mesmo ID. O asset comum da guarda de moeda coincide por bytes com o build QA. O simulador responde 200 e referencia a entrada app do manifesto instalado. O consumidor IVA mantém disponibilidade `enabled=true` e cobertura de 2026. Não se exige identidade dos bundles completos entre Windows QA e Linux; a conferência usa o manifesto do próprio build servido, os assets e o delta de código.
O diff de `app`, `database`, `config`, `routes` e `deploy` contra `276d833a` é vazio: sem alteração de motor, regras/fontes fiscais, schema, permissões, configuração ou processo de entrega. Cinco fontes frontend constituem o delta funcional de moeda/recuperação/relatório. Não foram criados dossiers, pedidos ou cálculos sintéticos na homologação, nem repetidos os ensaios aceites. Provas QA 12 frontend, 2 API/23 asserções, TypeScript/build e PDF de quatro páginas são reutilizadas, sem nova impressão. Não se apresenta esta leitura pública como auditoria autenticada nova dos dados protegidos.
**Saldo S1–S3: entregue, sem pendências deste lote.** Nos snapshots antigos sem moeda, a confirmação explícita da origem continua necessária, preservando os montantes; não se presume MZN nem se convertem valores. Este fecho abrange moeda da tesouraria, recuperação do IVA mensal e exportações; **não conclui todos os impostos**. Os modelos anexados delimitam o próximo lote fiscal, sem activação implícita. As pendências documentais anteriores mantêm-se no seu âmbito. Recibo integrado existente: chave `closure_homologation_20261024`; prova do delta em `outputs/simulator-delivery-20261024/installed-delta.json`. Os estados QA/pendentes abaixo são histórico superado por esta entrega.
## Simulador S1/S2/S3 — candidata QA `65b87819`, 24/10/2026
**Actualização de fecho S3:** a Tempo pediu expressamente voltar a gerar o ficheiro. O PDF foi gravado directamente em `outputs/simulator-closure-qa-20261024/monthly-final.pdf` pelo motor de impressão do Microsoft Edge em modo headless, com perfil isolado, a partir da mesma saída HTML final; não foi gravação manual pelo diálogo de impressão. Ficheiro de 111 910 bytes, SHA256 `7719a05136f6dba668b621f551626060d10db5fcbb84815cdad112a1eab9079b`. As **quatro páginas A4** foram extraídas, renderizadas e inspeccionadas visualmente: valores exactos, MZN, oportunidade `309`/Manica, Janeiro–Abril/2026, fonte sintética QA e versão 4 conservados; zero distinto de falta, cabeçalhos repetidos, linhas intactas, rodapés separados e numeração 1/4–4/4. CSV e Word previamente conferidos mantidos, sem recálculo fiscal. **S1, S2 e S3 concluídos em QA; candidata pronta para integração pelo Git.** Saldo QA deste lote: zero; integração, disponibilização e conferência do delta instalado ainda não executadas. Os estados de espera abaixo são histórico anterior a esta geração/conferência e não reabrem S3. Recibo integrado e mesmas oito linhas da matriz actualizados; referência `276d833a` e regras fiscais preservadas.
Execução autorizada pela Tempo após `be62783b`, preservando `276d833a` e a etiqueta `reference/stabilization-20261024`. Ramo `codex/simulator-closure-qa-20261024`; **não integrado em main nem entregue na homologação**. Cinco fontes frontend alteradas; sem alterações em motor/regras/fontes fiscais, schema, configuração, permissões, rotas ou dados activos. Sem impostos adicionais.
| Recorte | Correcção e resultado dirigido |
| --- | --- |
| **S1 — corrigido e demonstrado em QA** | Novos snapshots de tesouraria v2 conservam moeda de origem. Painel, CSV próprio e relatório usam essa moeda; o fallback de vendas para IVA recusa divergência. USD → MZN conserva `123 USD`, explica a diferença e permite restaurar USD no projecto por acção explícita. Os montantes não são convertidos nem reinterpretados. Snapshots v1 continuam legíveis; moeda sem origem recuperável exige confirmação única, conservando valores/modo/meses vazios. Não se presume MZN. A observação visual detectou um rótulo residual de saldo na moeda actual; corrigido para a moeda de origem. O rótulo do selector passou a «Moeda do projecto», distinguindo-o dos pressupostos guardados. |
| **S2 — corrigido e demonstrado em QA** | Recuperação mensal usa GET no mesmo ID, com credenciais e verificação do identificador devolvido; não depende da disponibilidade para novas admissões. Botão específico continua disponível com consumidor desligado. Resposta não substitui snapshot alterado entretanto ou componente desmontado. Interface isolada: consumidor indisponível, uma consulta GET, zero criações POST, mesma execução concluída. API real de QA: execução admitida → consumidor desligado só na configuração do teste → mesmo ID em fila/concluído; outra conta continua recusada e contagem de execuções não aumenta. Regras existentes reutilizadas, sem criar/publicar/suspender regra; fingerprint integral das versões igual. |
| **S3 — CSV/Word e fonte de impressão conferidos; PDF nativo ainda pendente** | Mesmo bloco mensal sintético congelado, sem recalcular: Janeiro `160.0048`, Fevereiro `320.0096`, Março zero, Abril sem informação; MZN, oportunidade `309`/Manica, período Janeiro–Abril/2026, fonte identificada como sintética QA e versão 4. CSV e Word finais lidos e comparados, incluindo ausência da primeira oportunidade/Sofala. A fonte HTML conserva os mesmos dados. O relatório está aberto no Edge e a Tempo indicou que guardará o PDF em `outputs/simulator-closure-qa-20261024/monthly-final.pdf`; falta ler e renderizar esse ficheiro para conferir apenas a paginação do bloco. HTML não substitui essa prova. |
Provas: quatro testes novos em `simulator-closure-scope.test.mjs`, mais oito casos das dependências directamente afectadas, **12/12 aprovados**; `SimulatorClosureRecoveryTest`, **2 casos/23 asserções**, transacções revertidas no clone nominal `simulator_fiscal_delta_20261021_test:55441`. TypeScript e build aprovados. As suites de aceitação não afectadas, ZIP, cálculos fiscais, PDFs/rodapé anteriores e contextos por oportunidade são reutilizados; não se exigiu à Tempo repetir essas provas. O ensaio visual usa componentes reais com transporte simulado explicitamente identificado, complementado pelo teste API de permissões; não é apresentado como servidor real ou processo na homologação.
Artefactos novos: `outputs/simulator-closure-qa-20261024/` — CSV/Word/HTML finais, snapshot congelado, inspecção/hash dos ficheiros, captura de recuperação e resultados dos testes. O estado executado fica no recibo integrado existente, chave `closure_qa_20261024`, e nas mesmas oito linhas da matriz. **Limite corrente:** S1/S2 em QA; S3 aguarda somente o PDF nativo guardado. A candidata não é declarada pronta para integração enquanto faltar essa conferência. Os seis pares legados e os dois originais incompletos não têm dependência efectiva neste lote.
## Simulador — âmbito de fecho reconciliado e lote proposto, 24/10/2026
Pedido expresso da Tempo após a referência `276d833a`/`reference/stabilization-20261024`, confirmada segundo o relatório, sem lhe atribuir leitura do recibo local. Esta passagem é **análise e proposta**, sem correcção funcional, integração, nova publicação/activação fiscal ou alteração de dados. A ordem de referência mantém-se. Não se acrescentam impostos nem se reabre o lote de estabilização.
### O que já existe e permanece aceite
| Frente | Implementação e provas reutilizadas |
| --- | --- |
| Planeamento financeiro | Plano empresarial por produto/mês, tesouraria, pressupostos editáveis, moeda e cenários de planeamento; controlos independentes anteriores de saldos positivo/negativo/nulo/incompleto, crédito e projecções. `business-financial-plan`, `monthly-cashflow` e recibos integrados de 20–22/10. Exemplos demonstrativos e imposto manual continuam identificados como planeamento, sem serem taxas legais ou valores do investidor. |
| IVA implementado | Consumidor publicado, selecção e versão congeladas no servidor, avaliador existente; vendas mensais do plano ou receita constante já guardada, indicação explícita de base líquida, zero distinto de falta e IVA separado da caixa. `SimulationPublishedFiscalTest`, quatro casos de `monthly-iva.test.mjs` e ensaio Edge mensal anteriores reutilizados. `3f5430c3` e `0b0cf761` pertencem à referência instalada; as notas históricas «só QA» não significam hoje ausência deste código. A disponibilidade pública consultada nesta passagem devolveu `enabled=true`, cobertura 2026. Isso não é uma nova auditoria dos parâmetros protegidos; o cadastro/publicação real v1 mantém o recibo de `d3fe8a02`. |
| Continuidade | Dois dossiers/nova sessão, isolamento, recuperação, erro e nova tentativa, históricos e hashes já provados. A escolha da oportunidade e o PDF correspondente estão entregues em `8036b9b0`/`cdf8fcfb`; não repetir. Inputs, rascunho e snapshots usam os mecanismos existentes, sem voltar a preencher vendas no IVA. |
| Resultados/exportações | Resumo/detalhe, CSV/Word, erro e nova tentativa de exportação, ZIP e rodapé do PDF nativo têm provas aceites. O rodapé nativo de tesouraria foi corrigido e conferido em 21/10; o PDF guardado por oportunidade foi conferido em 23/10. O bloco mensal usa o mesmo snapshot fiscal e não recalcula imposto ao exportar. A prova específica restante desse bloco consta de S3 abaixo; não reabrir os restantes exportadores ou PDFs. |
| Indisponibilidade | Fora da cobertura demonstrada de 2026, moeda diferente de MZN, preços com IVA incluído/base desconhecida, enquadramento não declarado e vendas em falta permanecem explícitos ou indeterminados, sem substituir por zero. Deduções, créditos, reembolsos, regimes especiais, apuramento final/Modelo A completo e outros impostos não são implementados por este lote. Cobertura técnica não é uma data legal de revogação. |
Reutilizados os recibos versionados `integrated-review-continuation-20261020-receipt.json`, `treatment-scope-installation-receipt-20261023.json` e os fechos posteriores do manual. Alguns caminhos históricos `outputs/` não existem nesta cópia do workspace: essa ausência não revoga provas aceites nem autoriza regenerá-las. Nenhuma suite de aceitação anterior foi reexecutada nesta análise.
### Saldo concreto — duas lacunas de código e uma prova específica
| ID / situação | Ecrã, causa e efeito delimitado | Lote proposto e critério de fecho |
| --- | --- | --- |
| **S1 — lacuna de código confirmada por diagnóstico isolado novo** | **Tesouraria → vendas reutilizadas pelo IVA → relatório.** `CashflowDraftSnapshot` v1 guarda montantes/modo, mas não a moeda de origem. O painel e o relatório usam a moeda actual do projecto; o fallback `monthlySalesFromDraft` não tem moeda guardada para comparar. Serializar receita `123` enquanto o projecto está em USD e depois mudar o projecto para MZN produz uma entrada IVA `123 MZN` e relatório MZN, sem conservar USD. O plano empresarial já tem protecção própria de moeda; a lacuna é a tesouraria guardada, não todos os planeadores. | Versionar a moeda dos pressupostos de tesouraria e partilhar a guarda entre painel, IVA e relatório. Divergência exige reconciliação explícita, sem conversão/reclassificação silenciosa nem perda dos montantes. Snapshots v1 continuam legíveis e intactos; moeda sem origem recuperável fica por confirmar, nunca presumida como MZN. Prova nova só deste delta: USD → MZN, gravação/recuperação, ecrã/IVA/exportação coerentes; valores e edições conservados. Diagnóstico sem DB/rede em `outputs/simulator-scope-20261024/currency-gap.json`. |
| **S2 — lacuna identificada no código; prova de interface dirigida a fazer com a correcção** | **IVA mensal, execução já admitida ainda em fila/processamento.** Em `SimulationMonthlyIva`, o efeito regressa por `!available` antes de consultar o ID pendente e o botão também fica desactivado. A suspensão do consumidor, que deve impedir novas admissões, bloqueia assim a recuperação pela componente mensal. O servidor já preserva a versão admitida e permite consultar o histórico; não há falha de cálculo ou perda da execução demonstrada. | Separar nova admissão de consulta/retoma por ID. Execução admitida deve ser recuperável com consumidor suspenso, respeitando autenticação/dono, sem novo POST nem nova regra. Prova dirigida em QA: mesma execução pendente → indisponibilidade para novas admissões → conclusão/recuperação por mesmo ID → rascunho/relatório com o snapshot correcto e sem duplicação. Não repetir os testes aceites do avaliador ou publicar/suspender a regra real de homologação. |
| **S3 — ainda sem prova específica, não defeito presumido** | **Bloco mensal de IVA nos ficheiros finais.** Há prova de reutilização das vendas, snapshots mensais no servidor e composição do relatório, e provas aceites dos exportadores gerais. Não há neste inventário uma conferência explícita de ficheiros finais com o bloco mensal completo — valores exactos, estado actual/histórico, oportunidade, fonte e versão — incluindo a paginação desse bloco. Os PDFs anteriores cobriam outros deltas. | Conferir um cenário mensal representativo por ecrã e CSV/Word, e apenas a paginação do bloco mensal no PDF nativo final. Reutilizar execução/snapshot sintético aceite, se recuperável, sem recalcular para testar exportação. Comparar montantes exactos, zero/falta, contexto, fonte, versão e aviso de ausência de apuramento final. ZIP e restante paginação/rodapé reutilizam as provas aceites. Corrigir apenas divergência efectivamente observada; não presumir falha de exportador. |
**Proposta de execução:** fechar S1 e S2 juntos, pelos consumidores de pressupostos/snapshots; verificar apenas os seus deltas e executar S3 sobre a candidata resultante. Integrar e disponibilizar somente depois dessas provas, pelo Git existente e preservando alterações concorrentes; conferir a revisão e o delta instalado. Não migrar dados activos nem publicar outra regra por esta proposta. As guardas, mensagens e compatibilidade de snapshots devem ser tratadas no mesmo lote, sem criar motor, formulários ou aprovações novos.
**Dependências reais:** nenhuma identificada entre S1–S3 e as seis associações legadas ou os dois originais incompletos. As fontes da regra IVA já cadastrada e os recibos fiscais existentes são reutilizados. Declaração Modelo A completa, outros impostos, elegibilidade/incentivos novos e extensão temporal não entram neste fecho. O resultado esperado é o ciclo **dados → cálculo disponível → gravação → recuperação → relatório** coerente neste âmbito, não a certificação de um simulador fiscal integral. A proposta está registada nas linhas existentes `AUD-SIM-01` e `AUD-SIM-INT02`–`08`; as notas e estimativas históricas ficam subordinadas a este saldo de três itens, sem outro backlog.
## Fecho do lote de estabilização e sequência de referência — 24/10/2026
**Ordem expressa da Tempo:** (1) correcções e estabilização; (2) simulador fiscal com âmbito definido; (3) Imobiliário; (4) Bens de consumo e franquias; (5) Estatística e painéis; (6) IA. A preservação técnica é responsabilidade do Codex e dos programadores. A Tempo avalia utilidade, clareza e apresentação; não tem de redescobrir regressões para comprovar preservação.
@@ -1,4 +1,4 @@
Exemplar/caminho,Bytes,SHA256,Tipo,Nota de leitura,Disponibilidade,Uso em cálculo,Situação jurídica/documental,Edição/versão identificada,Disponibilidade conferida 12/10/2026,Caminho atual/alias,SHA256 atual,Correspondência binária,Observação da reconciliação
Exemplar/caminho,Bytes,SHA256,Tipo,Nota de leitura,Disponibilidade,Uso em cálculo,Situação jurídica/documental,Edição/versão identificada,Disponibilidade conferida 12/10/2026,Caminho atual/alias,SHA256 atual,Correspondência binária,Observação da reconciliação
C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\~WRL2550.tmp,451286,0ae1dc970cc219a57791483bf22f134b2fab1ff5a6d3cd98eba98a5737f23010,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,,Exemplar acessível,C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\~WRL2550.tmp,0ae1dc970cc219a57791483bf22f134b2fab1ff5a6d3cd98eba98a5737f23010,Idêntico ao hash histórico,Hash original preservado; alteração de nome/caminho não cria outro documento/requisito.
C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\diagramas.docx,6005783,ece2c2edee8df625e712ff9f285df5c787378fa3477e466303b5a46ee0971c09,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,,Exemplar acessível,C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\diagramas.docx,ece2c2edee8df625e712ff9f285df5c787378fa3477e466303b5a46ee0971c09,Idêntico ao hash histórico,Hash original preservado; alteração de nome/caminho não cria outro documento/requisito.
C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\diagramas.docx#word/media/image1.png,1208097,1495ef144a048018723db1c0e11217fa14b4d7b14d8e65e32a3adeea23d08c4c,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,,Anexo embebido inventariado,C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\diagramas.docx,,Não aplicável/sem bytes disponíveis,Hash original preservado; alteração de nome/caminho não cria outro documento/requisito.
@@ -606,3 +606,5 @@ C:\laragon\www\portal-investidor\docs\investmoz\v2\auditoria-portal\legado-sitem
\\mac\home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\novos\segmentar processos v1.docx,104147,bf26caeee0437a8d292bf29be59247e2862c14e79b5ae465c00322747af72af5,.docx,Original integral907parágrafos/14tabelas; relações externas/notas/alterações verificadas; hash e cópia privada preservados. Identidade binária com v1(3).docx confirmada pelo responsável em 11/10/2026; v1.docx é o nome local do mesmo exemplar.,PrivadoQA/biblioteca recurso29,Nenhum cálculo ativado.,Documento de programação; não estender aceitação oficial. Original/histórico preservados.,"v1; propriedadeOOXMLrevision15; modificado11/10/2026 12:29UTC; mesmo exemplar de v1(3).docx, confirmado pelo responsável em 11/10/2026.",Exemplar acessível,\\mac\home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\novos\segmentar processos v1.docx,bf26caeee0437a8d292bf29be59247e2862c14e79b5ae465c00322747af72af5,Idêntico ao hash histórico,Hash original preservado; alteração de nome/caminho não cria outro documento/requisito.
\\mac\home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\novos\~$gmentar processos v1.docx,162,dd30703646feabe737708b9072861ce24e7ebd953e25847edcb23143383d5ae2,.docx,Inventariado integralmente no mesmo diretório antes da seleção; conteúdo não promovido a implementação. Not a valid DOCX ZIP; inventoried without discarding.,Origem acessível; divulgação não inferida.,Nenhum cálculo ativado.,Documento de programação; não estender aceitação oficial. Original/histórico preservados.,Nome/hash do exemplar; versão substantiva não inferida.,Original indisponível,\\mac\home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\novos\~$gmentar processos v1.docx,,Não aplicável/sem bytes disponíveis,"Ficheiro temporário Word indisponível; referência histórica preservada, não omitir do inventário."
\\mac\home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\novos\~WRL2698.tmp,20868,fb8a11801469536438e9e85cacc3468d33253d22e94bb366f249d109ba9ab827,.tmp,Inventariado integralmente no mesmo diretório antes da seleção; conteúdo não promovido a implementação. ,Origem acessível; divulgação não inferida.,Nenhum cálculo ativado.,Documento de programação; não estender aceitação oficial. Original/histórico preservados.,Nome/hash do exemplar; versão substantiva não inferida.,Original indisponível,\\mac\home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\novos\~WRL2698.tmp,,Não aplicável/sem bytes disponíveis,"Ficheiro temporário Word indisponível; referência histórica preservada, não omitir do inventário."
https://archive.gazettes.africa/archive/mz/2025/mz-government-gazette-series-i-supplement-dated-2025-05-21-no-95.pdf,329070,e0e682e2c027c3cd9c1d46a73a3f48bc5f6bdbf05667fd97314d7a3f6a456358,original oficial PDF,"BR95,I Série,Suplemento,21/05/2025;Lei3/2025 arts.1/2 eAnexoII;2páginas conferidas",Exemplar privado disponível para consulta;sem publicação automática,"Aplicado emG3cessação2026/P038–P043,emcódigoQA;semprorrogação presumida,benefíciohistórico ou activaçãoemservidor.",Origem oficial identificada;9(13) com termo31/12/2025;sem prorrogação presumida,Lei3/2025 de21/05/2025,Conferido em24/10/2026,C:\laragon\www\portal-investidor\docs\investmoz\simulations\source-archive\BR-95-I-Suplemento-2025-05-21.pdf,e0e682e2c027c3cd9c1d46a73a3f48bc5f6bdbf05667fd97314d7a3f6a456358,Original preservado porbytes/hash,G3 candidatoac948bd8b7ff34d661dd4cb7cbe88221093dfd83:termo31/12/2025 executável no percurso2026;P038–P043 comcode/APIaprovados evisualpendente. Original/proveniência/publicação preservados;zero importação/publicação embaseactiva. Histórico: Aquisição documental apenas;zero importação/publicação em base activa. Fonte aceite conforme decisãoTempo08/10;P038–P043 permanecem funcionais pendentes.
https://portaldogoverno.gov.mz/governo-introduz-alteracoes-nos-regulamentos-fiscais-para-reforcar-eficiencia-tributaria/,,,"Notícia oficial online,sem original porbytes preservado",Governo30/09/2026:aprovação dealterações regulamentaresIVA/IRPC/IRPS,Consulta online livre;sem importação/publicação peloportal,Não usada paraactivar cálculo;inventariada paracotejo dodiploma,"Comunicado não substitui decreto,publicação ou períodoaplicável","RegulamentoCIVA/Decreto7/2008:artigos mencionados3,7,8,15,16-A,18,21,23,28,36,37",Consultado24/10/2026,URLonline;semficheirooriginallocal,,Proveniência oficial dapágina;semafirmar vigência dodiploma,Cotejar publicação/texto/período eafectarapenas regrasdependentes;sem bloqueio genéricoG4A
1 Exemplar/caminho Bytes SHA256 Tipo Nota de leitura Disponibilidade Uso em cálculo Situação jurídica/documental Edição/versão identificada Disponibilidade conferida 12/10/2026 Caminho atual/alias SHA256 atual Correspondência binária Observação da reconciliação
2 C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\~WRL2550.tmp 451286 0ae1dc970cc219a57791483bf22f134b2fab1ff5a6d3cd98eba98a5737f23010 original Acervo inventariado; consulta/publicação individual não inferida Nenhum cálculo ativado pela auditoria Situação documental não determinada por inventário Exemplar acessível C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\~WRL2550.tmp 0ae1dc970cc219a57791483bf22f134b2fab1ff5a6d3cd98eba98a5737f23010 Idêntico ao hash histórico Hash original preservado; alteração de nome/caminho não cria outro documento/requisito.
3 C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\diagramas.docx 6005783 ece2c2edee8df625e712ff9f285df5c787378fa3477e466303b5a46ee0971c09 original Acervo inventariado; consulta/publicação individual não inferida Nenhum cálculo ativado pela auditoria Situação documental não determinada por inventário Exemplar acessível C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\diagramas.docx ece2c2edee8df625e712ff9f285df5c787378fa3477e466303b5a46ee0971c09 Idêntico ao hash histórico Hash original preservado; alteração de nome/caminho não cria outro documento/requisito.
4 C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\diagramas.docx#word/media/image1.png 1208097 1495ef144a048018723db1c0e11217fa14b4d7b14d8e65e32a3adeea23d08c4c anexo embebido Acervo inventariado; consulta/publicação individual não inferida Nenhum cálculo ativado pela auditoria Situação documental não determinada por inventário Anexo embebido inventariado C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\diagramas.docx Não aplicável/sem bytes disponíveis Hash original preservado; alteração de nome/caminho não cria outro documento/requisito.
606 https://archive.gazettes.africa/archive/mz/2025/mz-government-gazette-series-i-supplement-dated-2025-05-21-no-95.pdf 329070 e0e682e2c027c3cd9c1d46a73a3f48bc5f6bdbf05667fd97314d7a3f6a456358 original oficial PDF BR95,I Série,Suplemento,21/05/2025;Lei3/2025 arts.1/2 eAnexoII;2páginas conferidas Exemplar privado disponível para consulta;sem publicação automática Aplicado emG3cessação2026/P038–P043,emcódigoQA;semprorrogação presumida,benefíciohistórico ou activaçãoemservidor. Origem oficial identificada;9(13) com termo31/12/2025;sem prorrogação presumida Lei3/2025 de21/05/2025 Conferido em24/10/2026 C:\laragon\www\portal-investidor\docs\investmoz\simulations\source-archive\BR-95-I-Suplemento-2025-05-21.pdf e0e682e2c027c3cd9c1d46a73a3f48bc5f6bdbf05667fd97314d7a3f6a456358 Original preservado porbytes/hash G3 candidatoac948bd8b7ff34d661dd4cb7cbe88221093dfd83:termo31/12/2025 executável no percurso2026;P038–P043 comcode/APIaprovados evisualpendente. Original/proveniência/publicação preservados;zero importação/publicação embaseactiva. Histórico: Aquisição documental apenas;zero importação/publicação em base activa. Fonte aceite conforme decisãoTempo08/10;P038–P043 permanecem funcionais pendentes.
607 https://portaldogoverno.gov.mz/governo-introduz-alteracoes-nos-regulamentos-fiscais-para-reforcar-eficiencia-tributaria/ Notícia oficial online,sem original porbytes preservado Governo30/09/2026:aprovação dealterações regulamentaresIVA/IRPC/IRPS Consulta online livre;sem importação/publicação peloportal Não usada paraactivar cálculo;inventariada paracotejo dodiploma Comunicado não substitui decreto,publicação ou períodoaplicável RegulamentoCIVA/Decreto7/2008:artigos mencionados3,7,8,15,16-A,18,21,23,28,36,37 Consultado24/10/2026 URLonline;semficheirooriginallocal Proveniência oficial dapágina;semafirmar vigência dodiploma Cotejar publicação/texto/período eafectarapenas regrasdependentes;sem bloqueio genéricoG4A
608
609
610
File diff suppressed because one or more lines are too long
@@ -0,0 +1,62 @@
import { useState } from 'react';
import { acquisitionBook, acquisitionCurrent, acquisitionExcludedFields, acquisitionPlanReferences, acquisitionReportRows, calculateAcquisitions, newAcquisition, reuseAcquisitions, saveAcquisitionBook, type Acquisition, type AcquisitionBook } from '@/lib/iva-acquisitions';
export function SimulationAcquisitions({draft,onChange}:{draft:Record<string,unknown>;onChange:(field:string,value:string)=>void}) {
const [error,setError]=useState('');
let book:AcquisitionBook;
try {book=acquisitionBook(draft);} catch(cause) {return <p role="alert">{String(cause)}</p>;}
const save=(next:AcquisitionBook)=>{try {onChange('modelo_a_snapshot',saveAcquisitionBook(draft,next));setError('');}catch(cause){setError(String(cause));}};
const change=(id:string,patch:Partial<Acquisition>)=>save({...book,rows:book.rows.map(row=>row.id===id?{...row,...patch}:row)});
const run=(action:()=>void)=>{try{action();setError('');}catch(cause){setError(cause instanceof Error?cause.message:String(cause));}};
let references:ReturnType<typeof acquisitionPlanReferences>=[];
try {references=acquisitionPlanReferences(draft);}catch { /* The action reports the concrete currency/source error without replacing saved values. */ }
const labels:Record<string,string>={'03':'Base à taxa reduzida','04':'IVA à taxa reduzida','05':'Isentas com direito à dedução','06':'Operações art.18(1)(b)','07':'Isentas sem direito','11':'Importações','12':'Regularizações a favor do sujeito passivo','13':'Regularizações a favor do Estado'};
const select=(row:Acquisition,key:keyof Acquisition,label:string,options:Array<[string,string]>)=><label className="block" key={key}>{label}<select className="block rounded border p-2" value={String(row[key]??'')} onChange={e=>change(row.id,{[key]:e.target.value})}><option value="">Por indicar</option>{options.map(([value,text])=><option key={value} value={value}>{text}</option>)}</select></label>;
const yesNo:Array<[string,string]>=[['yes','Sim'],['no','Não']];
return <section aria-label="Aquisições e apuramento parcial Modelo A" className="space-y-4 rounded border p-3">
<h4 className="font-semibold">Compras e apuramento parcial do Modelo A</h4>
<p>Oportunidade em tratamento: {String(draft.context_opportunity||'entrada geral')}. Moeda de origem: {book.currency||'por indicar'}. A compra registada não gera automaticamente IVA dedutível.</p>
{book.currency && draft.currency!==book.currency && <p role="alert">As compras conservam {book.currency}; o projecto está em {String(draft.currency||'moeda por indicar')}. Reveja a moeda no projecto. Os montantes e o resultado anterior não foram convertidos ou reinterpretados.</p>}
{!book.currency && !!draft.currency && <button type="button" className="underline" onClick={()=>save({...book,currency:String(draft.currency),rows:book.rows.map(row=>row.sourceCurrency?row:{...row,sourceCurrency:String(draft.currency)})})}>Confirmar explicitamente {String(draft.currency)} como moeda de origem dos valores sem moeda, conservando os montantes</button>}
<p>Primeiro âmbito: aquisições internas em MZN, afectação exclusiva a operações tributadas, sem exclusões ou dedução parcial, documento e dedução no mesmo período de 2026. Nas projecções, cada confirmação é um pressuposto, sem certificar documento ou declaração efectiva. Indique dois valores entre líquido, IVA e bruto; o terceiro é obtido por diferença ou soma, sem taxa de compra presumida.</p>
<label className="block">Adquirente sujeito passivo de IVA no regime normal (efectivo ou pressuposto da projecção)<select className="block rounded border p-2" value={book.taxpayerRegistered??''} onChange={e=>save({...book,taxpayerRegistered:e.target.value as AcquisitionBook['taxpayerRegistered']})}><option value="">Por confirmar</option><option value="yes">Sim</option><option value="no">Não / outro enquadramento — fora deste lote</option></select></label>
{error&&<p role="alert">{error}</p>}
<button type="button" className="underline" onClick={()=>run(()=>save(reuseAcquisitions(draft,book)))}>Reutilizar compras e períodos existentes</button>
<button type="button" className="ml-3 underline" disabled={!book.periods.length} onClick={()=>save({...book,rows:[...book.rows,newAcquisition(crypto.randomUUID(),book.periods[0]?.period??'',book.currency)]})}>Acrescentar aquisição em falta</button>
{book.rows.map(row=><details key={row.id} className="rounded border p-3"><summary>{row.description||'Aquisição adicional'} — {row.period} — campo{row.field}</summary>
<p>Origem: {row.sourceMonth===null?'Introdução directa':`Plano, mês ${row.sourceMonth} (${row.sourcePeriod??'por indicar'}): ${row.sourceAmount??'sem informação'} ${row.sourceCurrency}`}. O mês da encomenda/orçamento não determina a data do documento ou a dedução. Alterações não substituem o resultado anterior.</p>
<div className="grid gap-3 md:grid-cols-2">
<label>Descrição<input className="block rounded border p-2" value={row.description} onChange={e=>change(row.id,{description:e.target.value})}/></label>
{row.sourceMonth===null && <label>Reutilizar valor existente, sem presumir que o orçamento é uma factura<select className="block rounded border p-2" value="" onChange={e=>run(()=>{const ref=references.find(r=>r.key===e.target.value);if(ref)change(row.id,{sourceMonth:ref.month,sourcePeriod:ref.period,sourceField:ref.kind,sourceAmount:ref.amount,sourceCurrency:ref.currency,...(ref.kind==='asset'?{}:{period:ref.period})});})}><option value="">Escolher apenas se corresponde a esta aquisição</option>{references.filter(ref=>ref.kind===(row.field==='08'?'asset':row.field==='10'?'operating':'inventory')).map(ref=><option key={ref.key} value={ref.key}>{ref.label}: {ref.amount??'sem informação'} {ref.currency}</option>)}</select></label>}
{select(row,'field','Categoria',[['08','08 — Imobilizado'],['09','09 — Existências'],['10','10 — Outros bens e serviços']])}
{select(row,'origin','Natureza dos dados',[['projected','Projectados / pressupostos'],['effective','Efectivos declarados']])}
<label>Período de dedução<input className="block rounded border p-2" type="month" value={row.period} onChange={e=>change(row.id,{period:e.target.value})}/></label>
{row.sourceMonth!==null && <label>O valor de origem corresponde a<select className="block rounded border p-2" value={row.sourceBasis} onChange={e=>{const basis=e.target.value as Acquisition['sourceBasis'];change(row.id,{sourceBasis:basis,...(basis==='net'&&!row.net?{net:row.sourceAmount??''}:basis==='gross'&&!row.gross?{gross:row.sourceAmount??''}:{})});}}><option value="">Por classificar</option><option value="net">Valor sem IVA</option><option value="gross">Valor com IVA</option></select></label>}
{(['net','vat','gross'] as const).map((field,index)=><label key={field}>{['Valor líquido','IVA indicado','Valor bruto'][index]} ({row.sourceCurrency})<input className="block rounded border p-2" inputMode="decimal" value={row[field]} onChange={e=>change(row.id,{[field]:e.target.value})}/></label>)}
{select(row,'documentType','Tipo de documento',[['invoice','Factura'],['equivalent','Documento equivalente']])}
<label>Referência do documento / previsão<input className="block rounded border p-2" value={row.documentRef} onChange={e=>change(row.id,{documentRef:e.target.value})}/></label>
<label>Linha do documento, se discriminado em várias aquisições<input className="block rounded border p-2" value={row.documentLine} onChange={e=>change(row.id,{documentLine:e.target.value})}/></label>
<label>Data do documento / prevista<input className="block rounded border p-2" type="date" value={row.documentDate} onChange={e=>change(row.id,{documentDate:e.target.value})}/></label>
<label>Fornecedor / previsto<input className="block rounded border p-2" value={row.supplier} onChange={e=>change(row.id,{supplier:e.target.value})}/></label>
{select(row,'domestic','Aquisição interna',yesNo)}
{select(row,'supplierRegistered','Fornecedor inscrito no IVA',yesNo)}
{select(row,'legalDocument','Documento emitido em forma legal',yesNo)}
{select(row,'held','Documento na posse do adquirente / previsto na projecção',yesNo)}
{select(row,'allocation','Afectação',[['taxable_only','Exclusiva a operações tributadas'],['mixed','Mista / parcial — fora deste lote'],['no_right','Operações sem direito à dedução']])}
{select(row,'exclusion','Exclusões de dedução',[['none','Sem exclusões ou casos especiais dos arts.18–20'],['excluded','Despesa excluída'],['special','Veículos, combustível, viagens, alojamento, comunicações, luxo ou outra situação especial — por enquadrar']])}
{select(row,'integrity','Operação real / pressuposto regular, sem simulação, margem de segunda mão ou impedimentos do art.18(3–5)',yesNo)}
</div>
<p>Fundamento: CIVA arts.18–21, fontes e versão no resultado. Não se calcula dedução parcial, excepção de despesa ou dedução posterior neste lote.</p>
{row.sourceMonth===null && <button type="button" className="mr-3 underline" onClick={()=>save({...book,rows:book.rows.filter(r=>r.id!==row.id)})}>Remover esta aquisição introduzida directamente</button>}
{row.sourceMonth!==null && <button type="button" className="underline" onClick={()=>run(()=>{const ref=acquisitionPlanReferences(draft).find(r=>r.month===row.sourceMonth && r.kind===(row.sourceField??'inventory'));if(!ref)throw new Error('Origem não disponível; conserve o registo e reveja o plano.');if(draft.currency!==row.sourceCurrency)throw new Error('Moeda divergente; não adoptar montantes de outra moeda.');change(row.id,{sourceAmount:ref.amount,sourcePeriod:ref.period,...(row.sourceBasis==='net'?{net:ref.amount??'',gross:''}:row.sourceBasis==='gross'?{gross:ref.amount??'',net:''}:{})});})}>Adoptar explicitamente o valor actual do plano (conserva histórico)</button>}
</details>)}
{book.periods.map(period=><details key={period.period} className="rounded border p-3"><summary>{period.period} — cobertura das parcelas — {period.complete && period.absent.length===acquisitionExcludedFields.length?'confirmada':'por completar'}</summary>
<label className="block"><input type="checkbox" checked={period.complete} onChange={e=>save({...book,periods:book.periods.map(p=>p.period===period.period?{...p,complete:e.target.checked}:p)})}/> Incluí todas as aquisições08–10 deste período, incluindo as sem direito à dedução; uma lista vazia significa que não houve essas aquisições.</label>
<p>Campos fora deste lote: assinale apenas quando não existiram as respectivas operações. Uma parcela não assinalada permanece indeterminada.</p>
{acquisitionExcludedFields.map(field=><label className="block" key={field}><input type="checkbox" checked={period.absent.includes(field)} onChange={e=>save({...book,periods:book.periods.map(p=>p.period===period.period?{...p,absent:e.target.checked?[...p.absent,field]:p.absent.filter(f=>f!==field)}:p)})}/> Sem operações no campo{field} — {labels[field]}</label>)}
</details>)}
<button type="button" disabled={!book.periods.length} className="rounded bg-emerald-800 p-2 text-white disabled:opacity-50" onClick={()=>run(()=>save({...book,result:calculateAcquisitions(draft,book)}))}>Calcular e guardar versão do apuramento parcial</button>
<p>O preenchimento e o resultado seguem a gravação privada do simulador. Os campos19–27 e a submissão à AT permanecem fora deste lote; 17/18 são diferenças antes de créditos anteriores, sem ordem de pagamento ou promessa de reembolso.</p>
{book.result&&<><p role="status">{acquisitionCurrent(draft,book)?'Resultado correspondente às entradas guardadas.':'Entradas ou origem alteradas: resultado histórico preservado; actualizar o cálculo.'}</p><dl>{acquisitionReportRows(draft).map(([,label,value,origin],i)=><div key={i}><dt className="font-semibold">{label}</dt><dd>{value}<small className="block">{origin}</small></dd></div>)}</dl></>}
</section>;
}
@@ -5,6 +5,7 @@ import {
defaultCashflowDraftInputs,
restoreCashflowDraftSnapshot,
serializeCashflowDraftSnapshot,
cashflowCurrency,
type CashflowDraftSnapshot,
} from '@/lib/monthly-cashflow';
import {
@@ -24,6 +25,9 @@ export function SimulationCashflowPlanner({
onSnapshotChange?: (snapshot: string) => void;
}) {
const restored = restoreCashflowDraftSnapshot(snapshot);
const [confirmedCurrency, setConfirmedCurrency] = useState('');
const originCurrency = restored?.version === 2 ? restored.currency : null;
const calculationCurrency = snapshot ? originCurrency ?? '' : currency;
const [taxMode, setTaxMode] = useState<'fixed' | 'schedule'>(
restored?.taxMode ?? 'fixed',
);
@@ -41,7 +45,7 @@ export function SimulationCashflowPlanner({
) {
setInputs(next);
setTaxMode(mode);
onSnapshotChange?.(serializeCashflowDraftSnapshot(mode, next));
onSnapshotChange?.(serializeCashflowDraftSnapshot(mode, next, snapshot ? originCurrency ?? null : currency || null));
}
const set = (
key: Exclude<keyof typeof inputs, 'monthlyTaxSchedule'>,
@@ -63,7 +67,8 @@ export function SimulationCashflowPlanner({
throw new Error(
'Não foi possível recuperar os pressupostos guardados de tesouraria. Reveja os campos antes de voltar a guardar; nenhum resultado foi calculado com dados alternativos.',
);
projection = projectMonthlyCashflow({ ...cashflowInput, currency });
if (restored) cashflowCurrency(restored, currency);
projection = projectMonthlyCashflow({ ...cashflowInput, currency: calculationCurrency });
} catch (cause) {
error =
cause instanceof Error
@@ -76,7 +81,7 @@ export function SimulationCashflowPlanner({
aria-labelledby="cashflow-title"
>
<label className="block max-w-xs text-sm font-medium">
Moeda dos valores (código ISO)
Moeda do projecto (código ISO)
<input
list="cashflow-currency-options"
inputMode="text"
@@ -103,6 +108,16 @@ export function SimulationCashflowPlanner({
<h3 id="cashflow-title" className="text-lg font-semibold">
Projecção de tesouraria — 12 meses
</h3>
{restored && !originCurrency && <div className="space-y-2 rounded border border-amber-600 p-3">
<p>A moeda de origem dos montantes guardados não foi registada. Os valores foram conservados. Confirme apenas essa moeda; não é necessário preencher os montantes novamente.</p>
<label>Moeda de origem da tesouraria guardada<select className="ml-2 rounded border p-2" value={confirmedCurrency} onChange={event => setConfirmedCurrency(event.target.value)}><option value="">Por confirmar</option>{simulationCurrencyOptions.map(code => <option key={code} value={code}>{code}</option>)}</select></label>
<button type="button" className="block underline" disabled={!isSimulationCurrency(confirmedCurrency)} onClick={() => onSnapshotChange?.(serializeCashflowDraftSnapshot(taxMode, inputs, confirmedCurrency))}>Confirmar moeda de origem e conservar montantes</button>
</div>}
{originCurrency && originCurrency !== currency && <div role="alert" className="rounded border border-amber-600 p-3">
<p>{cashflowCurrency(restored!, currency).notice}</p>
<button type="button" className="underline" onClick={() => onCurrencyChange(originCurrency)}>Usar {originCurrency} no projecto e conservar montantes</button>
</div>}
{originCurrency && <p>Moeda de origem dos pressupostos: {originCurrency}.</p>}
<p className="text-sm text-slate-700">
Introduza pressupostos na mesma moeda. O imposto indicado é um
pressuposto do utilizador; esta ferramenta não calcula nem
@@ -257,12 +272,12 @@ export function SimulationCashflowPlanner({
{error}
</p>
)}
{projection && isSimulationCurrency(currency) && (
{projection && isSimulationCurrency(calculationCurrency) && (
<>
<p aria-live="polite" className="font-semibold">
{projection.endingCash === null
? `Caixa conhecida antes de imposto em falta, ao fim de 12 meses (${currency}):`
: `Saldo projectado ao fim de 12 meses (${currency}):`}{' '}
? `Caixa conhecida antes de imposto em falta, ao fim de 12 meses (${calculationCurrency}):`
: `Saldo projectado ao fim de 12 meses (${calculationCurrency}):`}{' '}
{projection.endingCash ??
projection.endingCashBeforeUnassessedTax}
</p>
@@ -274,7 +289,7 @@ export function SimulationCashflowPlanner({
[
exportMonthlyCashflowCsv({
...cashflowInput,
currency,
currency: calculationCurrency,
periods: 12,
}),
],
@@ -8,7 +8,7 @@ export function SimulationModeloA({draft}: {draft:Record<string,unknown>}) {
return <section aria-label="Correspondência com o Modelo A" className="space-y-3 rounded border p-3">
<h4 className="font-semibold">Modelo A — correspondência da simulação</h4>
<p>{modeloAReference.status}</p>
<p>Os campos 14–18 do apuramento permanecem indeterminados. O IVA das vendas não é imposto final a pagar. Os dados deste percurso são projecções, separados de facturas e declarações efectivas.</p>
<p>Esta correspondência descreve a componente de vendas01/02. Consulte o bloco de compras e apuramento parcial para os campos08–10 e14–18, que só são determinados com as parcelas necessárias completas. O IVA das vendas não é imposto final a pagar.</p>
<details><summary>Aquisições já projectadas — sem dedução presumida</summary>
<p>Reutilizam-se os valores das compras/encomendas para existências do plano. O mês da encomenda não prova a data da factura, recepção ou pagamento. Valores declarados ainda sem indicação de base líquida/IVA incluído não são tratados como base tributável. IVA suportado e IVA dedutível continuam por determinar; zero de compras não prova inexistência de outras aquisições.</p>
{error && <p role="alert">{error}</p>}
@@ -1,9 +1,11 @@
import { InvestmentContextAssessment } from './investment-context-assessment';
import { useEffect, useRef, useState } from 'react';
import { monthlyIvaInput, monthlyIvaKey, monthlySalesFromDraft, readMonthlyIvaRecord, readMonthlyIvaSettings, monthlyIvaCashTreatment, type MonthlyIvaInput, type MonthlyIvaSettings } from '@/lib/monthly-iva';
import { monthlyIvaInput, monthlyIvaKey, monthlySalesFromDraft, readMonthlyIvaRecord, readMonthlyIvaSettings, recoverMonthlyIvaRecord, monthlyIvaCashTreatment, type MonthlyIvaInput, type MonthlyIvaSettings } from '@/lib/monthly-iva';
import { fiscalQaRows } from '@/lib/fiscal-qa-preview';
import { isApiSimulationReadResponseV1, type ApiSimulationExecutionV1 } from '@/lib/simulation-contract';
import { type ApiSimulationExecutionV1 } from '@/lib/simulation-contract';
import { SimulationModeloA } from './simulation-modelo-a';
import { SimulationAcquisitions } from './simulation-acquisitions';
import { SimulationOperations } from './simulation-operations';
export function SimulationMonthlyIva({draft, busy, onCalculate, onChange}: {
draft: Record<string, unknown>; busy: boolean;
@@ -16,6 +18,9 @@ export function SimulationMonthlyIva({draft, busy, onCalculate, onChange}: {
const [error, setError] = useState('');
const [available, setAvailable] = useState<boolean | null>(null);
const attempt = useRef('');
const mounted = useRef(true);
const latestSnapshot = useRef(draft.monthly_iva_snapshot); latestSnapshot.current = draft.monthly_iva_snapshot;
useEffect(() => { mounted.current = true; return () => { mounted.current = false; }; }, []);
const callbacks = useRef({onCalculate, onChange}); callbacks.current = {onCalculate, onChange};
let input: MonthlyIvaInput | null = null; let inputError = ''; let source = '';
try { source = monthlySalesFromDraft(draft).source; input = monthlyIvaInput(draft, settings); }
@@ -23,6 +28,8 @@ export function SimulationMonthlyIva({draft, busy, onCalculate, onChange}: {
const key = input ? monthlyIvaKey(input) : '';
const current = !!(input && record && monthlyIvaKey(record.input) === key);
const completed = current && record?.execution.status === 'completed';
const pendingRecord = record && ['queued','running'].includes(record.execution.status) ? record : null;
const actionKey = pendingRecord ? `recover:${pendingRecord.execution.id}` : key;
const saveSettings = (patch: Partial<MonthlyIvaSettings>) => onChange('monthly_iva_settings', JSON.stringify({...settings, ...patch}));
useEffect(() => {
let active = true;
@@ -32,27 +39,26 @@ export function SimulationMonthlyIva({draft, busy, onCalculate, onChange}: {
return () => { active = false; };
}, [retry]);
useEffect(() => {
if (!settings.auto || !input || input.currency !== 'MZN' || busy || !available || completed || attempt.current === key) return;
const request = input;
const pending = current && record && ['queued','running'].includes(record.execution.status) ? record.execution.id : null;
if (!settings.auto || busy || attempt.current === actionKey) return;
if (!pendingRecord && (!input || input.currency !== 'MZN' || !available || completed)) return;
const request = pendingRecord?.input ?? input!;
const savedSnapshot = draft.monthly_iva_snapshot;
const timer = window.setTimeout(() => {
attempt.current = key; setError('');
attempt.current = actionKey; setError('');
void (async () => {
try {
let execution;
if (pending) {
const response = await fetch(`/api/v1/simulations/${pending}`, {credentials:'same-origin', headers:{Accept:'application/json'}});
const value: unknown = await response.json();
if (!response.ok || !isApiSimulationReadResponseV1(value)) throw new Error('Não foi possível recuperar a execução mensal guardada. Não foi criada uma execução alternativa.');
execution = value.data;
if (pendingRecord) {
execution = (await recoverMonthlyIvaRecord(pendingRecord)).execution;
} else execution = await callbacks.current.onCalculate(request);
if (!execution) throw new Error('O cálculo mensal não foi concluído. As vendas e a versão anterior foram preservadas; tente novamente.');
if (!mounted.current || (pendingRecord && latestSnapshot.current !== savedSnapshot)) return;
callbacks.current.onChange('monthly_iva_snapshot', JSON.stringify({input:request, execution}));
} catch (cause) {setError(cause instanceof Error ? cause.message : 'Não foi possível calcular o IVA mensal.');}
} catch (cause) {if (mounted.current) setError(cause instanceof Error ? cause.message : 'Não foi possível calcular o IVA mensal.');}
})();
}, 700);
return () => window.clearTimeout(timer);
}, [key, settings.auto, busy, available, completed, retry]);
}, [actionKey, key, settings.auto, busy, available, completed, retry]);
const snapshot = record?.execution.result_snapshot;
const projection = snapshot?.monthly_projection as {rows?: Array<{date:string; sales_declared:string|null; net_sales:string|null; rate:string|null; vat:string|null; gross_sales:string|null; status:string}>} | undefined;
@@ -73,11 +79,14 @@ export function SimulationMonthlyIva({draft, busy, onCalculate, onChange}: {
{settings.auto && !completed && current && <p role="status">Execução mensal guardada: {record?.execution.status === 'queued' ? 'em fila' : record?.execution.status === 'running' ? 'em processamento' : 'não concluída'}. Pode voltar a consultar sem duplicar.</p>}
{busy && <p role="status">A actualizar os resultados dependentes das vendas…</p>}
{error && <p role="alert">{error}</p>}
<button type="button" disabled={busy || !available || !input || input.currency !== 'MZN'} onClick={() => {attempt.current=''; setRetry((value) => value+1); saveSettings({auto:true});}} className="rounded bg-emerald-800 p-2 text-white disabled:opacity-50">Calcular / actualizar IVA mensal e guardar versão</button>
<button type="button" disabled={busy || (!pendingRecord && (!available || !input || input.currency !== 'MZN'))} onClick={() => {attempt.current=''; setRetry((value) => value+1); saveSettings({auto:true});}} className="rounded bg-emerald-800 p-2 text-white disabled:opacity-50">{pendingRecord ? 'Recuperar execução mensal admitida pelo mesmo ID' : 'Calcular / actualizar IVA mensal e guardar versão'}</button>
{pendingRecord && <p>Consulta da execução {pendingRecord.execution.id}. A suspensão de novos cálculos não impede esta recuperação; não é criado outro pedido.</p>}
{settings.auto && <button type="button" className="ml-3 underline" onClick={() => saveSettings({auto:false})}>Pausar actualização automática</button>}
{input && <p className="text-sm">{input.monthly_sales.length} meses; moeda {input.currency || 'por indicar'}. Campo vazio significa informação em falta; zero declarado permanece zero. Depois da primeira execução, alterações das vendas actualizam o cálculo enquanto a actualização automática estiver ligada.</p>}
{projection?.rows && <div className="overflow-x-auto" tabIndex={0}><table className="min-w-full text-sm"><caption>IVA mensal — {current ? 'versão correspondente às entradas' : 'versão histórica'}</caption><thead><tr>{['Mês','Vendas declaradas','Vendas tributáveis sem IVA','Taxa aplicada (%)','IVA calculado','Total com IVA','Estado'].map((label) => <th key={label} className="p-2 text-left">{label}</th>)}</tr></thead><tbody>{projection.rows.map((row) => <tr key={row.date}><th scope="row" className="p-2">{row.date.slice(0,7)}</th><td>{row.sales_declared ?? 'Sem informação'}</td><td>{row.net_sales ?? 'Indeterminado'}</td><td>{row.rate ?? 'Indeterminada'}</td><td>{row.vat ?? 'Indeterminado'}</td><td>{row.gross_sales ?? 'Indeterminado'}</td><td>{{calculated:'Calculado',missing_sales:'Sem informação de vendas',unsupported_basis:'Base líquida não determinada',indeterminate:'Enquadramento ou regra indeterminados'}[row.status] ?? 'Indeterminado'}</td></tr>)}</tbody></table></div>}
{snapshot && <details><summary>Ver fundamento e relatório da versão guardada</summary><dl>{fiscalQaRows(snapshot).map(([label,value], index) => <div key={index}><dt className="font-semibold">{label}</dt><dd>{value}</dd></div>)}</dl></details>}
<SimulationOperations draft={draft} onChange={onChange} />
<SimulationAcquisitions draft={draft} onChange={onChange} />
<SimulationModeloA draft={draft} />
</section>;
}
@@ -0,0 +1,99 @@
import { useState } from 'react';
import { fundraisingActivities } from '@/lib/iva-fundraising';
import { pharmaAnnexEntries, pharmaAnnexEntry, pharmaAnnexReference } from '@/lib/iva-pharma-annex';
import { annexIEntries, annexIEntry, annexIReference } from '@/lib/iva-annex-i';
import { temporaryBenefit, temporaryBenefitNotice } from '@/lib/iva-temporary-benefits';
import { isExportService } from '@/lib/iva-export-services';
import { isOnboardSupply, supplyCategories, onboardSupplyIssue, type SupplyCategory } from '@/lib/iva-onboard-supplies';
import { emptyProductionTaxOption, type ProductionTaxOption } from '@/lib/iva-production-option';
import { referenceExportOperation, continueTemporaryOperation, continueAnnexIOperation, modeloA06Correspondence, newSalesOperation, operationTreatments, recordSales, reuseSales, salesBook, salesCurrent, salesReportRows, saveSalesBook, splitSales, type SalesBook, type SalesOperation } from '@/lib/iva-operations';
export function SimulationOperations({draft,onChange}:{draft:Record<string,unknown>;onChange:(field:string,value:string)=>void}) {
const [error,setError]=useState('');
const [reuseOption,setReuseOption]=useState<{rowId:string;sourceId:string}|null>(null);
const [annexSearch,setAnnexSearch]=useState<Record<string,string>>({});
let book:SalesBook;
try{book=salesBook(draft);}catch(cause){return <p role="alert">{String(cause)}</p>;}
const run=(action:()=>void)=>{try{action();setError('');}catch(cause){setError(cause instanceof Error?cause.message:String(cause));}};
const save=(next:SalesBook)=>onChange('modelo_a_snapshot',saveSalesBook(draft,next));
const change=(id:string,patch:Partial<SalesOperation>)=>run(()=>save({...book,rows:book.rows.map(r=>r.id===id?{...r,...patch}:r)}));
const continueTemporary=(id:string,target:string)=>run(()=>save({...book,rows:book.rows.map(row=>row.id===id?continueTemporaryOperation(row,target):row)}));
return <section aria-label="Operações IVA por oportunidade" className="space-y-3 rounded border p-3">
<h4 className="font-semibold">Operações de IVA — enquadramento das vendas</h4>
<p>Oportunidade {String(draft.context_opportunity||'entrada geral')}; moeda original {book.currency||'por indicar'}. Cobertura2026/MZN. Reutilize as vendas e complete apenas o enquadramento. Este bloco classifica as operações; não substitui nem soma novamente a execução mensal geral acima.</p>
<p>Uma empresa pode ter operações com tratamentos diferentes. Os valores são projecções sob pressupostos declarados, sem certificar facturas, reconhecer créditos ou submeter uma declaração à AT.</p>
<details><summary>Correspondência do campo06 e limites do formulário</summary><p>{modeloA06Correspondence}</p></details>
{error&&<p role="alert">{error}</p>}
<button type="button" className="underline" onClick={()=>run(()=>save(reuseSales(draft,book)))}>Reutilizar vendas e períodos existentes</button>
<button type="button" className="ml-3 underline" disabled={!book.periods.length} onClick={()=>run(()=>save({...book,rows:[...book.rows,newSalesOperation(crypto.randomUUID(),book.periods[0].period,book.currency)]}))}>Acrescentar operação em falta</button>
{book.rows.map(row=>{const rule=operationTreatments.find(r=>r.id===row.treatment),annexI=annexIEntry(row.annexIItem);return <details className="rounded border p-3" key={row.id}><summary>{row.description||'Operação adicional'} — {row.period}</summary>
<p>Origem: {row.source}; {row.sourceAmount??'sem valor de origem'} {row.sourceCurrency}; {row.sourcePeriod}. O estabelecimento não é inferido da localização do projecto.</p>
<div className="grid gap-3 md:grid-cols-2">
<label>Descrição da operação<input className="block rounded border p-2" value={row.description} onChange={e=>change(row.id,{description:e.target.value})}/></label>
<label>Estabelecimento<input className="block rounded border p-2" value={row.establishment} onChange={e=>change(row.id,{establishment:e.target.value})}/></label>
<label>Período<input type="month" className="block rounded border p-2" min="2026-01" max="2026-12" value={row.period} onChange={e=>change(row.id,{period:e.target.value})}/></label>
<label>Valor declarado<input inputMode="decimal" className="block rounded border p-2" value={row.amount} onChange={e=>change(row.id,{amount:e.target.value})}/></label>
<label>Representação do preço<select className="block rounded border p-2" value={row.basis} onChange={e=>change(row.id,{basis:e.target.value as SalesOperation['basis']})}><option value="">Ainda desconhecida</option><option value="net">Sem IVA</option><option value="included">IVA incluído</option></select></label>
<label>Tratamento da operação<select className="block rounded border p-2" value={row.treatment} onChange={e=>temporaryBenefit(row.treatment)&&!temporaryBenefit(e.target.value)?continueTemporary(row.id,e.target.value):change(row.id,{treatment:e.target.value,confirmed:[]})}>{operationTreatments.map(t=><option value={t.id} key={t.id}>{t.label}</option>)}</select></label>
</div>
{isOnboardSupply(row.treatment)&&<fieldset className="space-y-2 rounded border p-2"><legend>Natureza do abastecimento a bordo</legend>
<label>Categoria do artigo13(3)<select value={row.supplyCategory??''} onChange={e=>change(row.id,{supplyCategory:e.target.value as SupplyCategory,confirmed:[]})}><option value="">Por identificar</option>{supplyCategories.map(([value,label])=><option key={value} value={value}>{label}</option>)}</select></label>
<p>A escolha conserva o preço, a moeda e o período; reveja as condições. Para fornecimento misto, discrimine as parcelas efectivas sem repetir o total em cada linha. Desconhecido não equivale a «sem bebidas».</p>
{onboardSupplyIssue(row.treatment,row.supplyCategory)&&<p role="status">{onboardSupplyIssue(row.treatment,row.supplyCategory)}</p>}
</fieldset>}
{isExportService(row.treatment)&&<fieldset className="space-y-2 rounded border p-2"><legend>Referência à operação relacionada</legend>
<p>Se a operação já consta desta oportunidade,pode referenciá-la sem preencher de novo a descrição. A escolha conserva o preço,moeda,período e fundamento deste serviço;limpa as confirmações para revisão. Não copia o valor dos bens para o preço do serviço nem comprova automaticamente a isenção. Para operação documentada fora deste livro,use o fundamento abaixo.</p>
<label>Operação já preenchida<select value={row.relatedExport?.id??''} onChange={e=>run(()=>{if(!e.target.value){save({...book,rows:book.rows.map(item=>item.id===row.id?{...item,relatedExport:undefined,confirmed:[]}:item)});return;}const related=book.rows.find(item=>item.id===e.target.value);if(!related)throw new Error('Operação relacionada já não disponível; dados conservados.');save({...book,rows:book.rows.map(item=>item.id===row.id?referenceExportOperation(item,related):item)});})}><option value="">Sem referência interna — identificar no fundamento</option>{book.rows.filter(item=>item.id!==row.id).map(item=><option key={item.id} value={item.id}>{item.description||item.id} — {item.period}</option>)}</select></label>
{row.relatedExport&&<><p>Referência guardada: {row.relatedExport.description}; ID {row.relatedExport.id}; {row.relatedExport.treatment}.</p>{book.rows.some(item=>item.id===row.relatedExport!.id)&&<button type="button" onClick={()=>run(()=>{const related=book.rows.find(item=>item.id===row.relatedExport!.id)!;save({...book,rows:book.rows.map(item=>item.id===row.id?referenceExportOperation(item,related):item)});})}>Actualizar referência escolhida e rever condições</button>}</>}
</fieldset>}
{temporaryBenefit(row.treatment)&&<fieldset className="space-y-2 rounded border p-2"><legend>Benefício temporário — prazo e continuidade</legend>
<p>{temporaryBenefitNotice(row.treatment,row.period)}</p>
<p>{temporaryBenefit(row.treatment)!.historicalScope}</p>
<p>Não precisa de preencher documentos de uma isenção já terminada para prosseguir em2026. Antes de escolher outro tratamento, confirme a natureza da operação: a escolha conserva valor,moeda,período,estabelecimento eorigem; limpa as confirmações para revisão e mantém o resultado anterior no histórico.</p>
<button type="button" onClick={()=>continueTemporary(row.id,'general')}>Escolher operação interna geral e rever condições</button>
{row.treatment==='temporary_sugar_cane'&&<button type="button" onClick={()=>continueTemporary(row.id,'production_agriculture')}>Analisar produção agrícola própria — artigo9(7)(a)</button>}
<p>Para outro enquadramento disponível,use a escolha «Tratamento da operação». Nenhum resultado é recalculado automaticamente.</p>
</fieldset>}
{temporaryBenefit(row.temporaryBenefitOrigin)&&!temporaryBenefit(row.treatment)&&<p>Origem conservada: {temporaryBenefit(row.temporaryBenefitOrigin)!.label},benefício com termo31/12/2025. Enquadramento actual escolhido expressamente;confirme as respectivas condições antes de calcular.</p>}
{row.treatment==='annexI_goods'&&<fieldset className="space-y-2 rounded border p-2"><legend>Bem do Anexo I — edição Lei22/2022</legend>
<p>Escolha código e designação e confira apenas os qualificadores dessa linha. A pesquisa conserva a escolha actual; mudar de posição exige rever as condições específicas. O anexo não dispensa o enquadramento de outras isenções aplicáveis ao mesmo bem.</p>
<label className="block">Pesquisar código ou designação no Anexo I<input value={annexSearch[`I:${row.id}`]??''} onChange={e=>setAnnexSearch({...annexSearch,[`I:${row.id}`]:e.target.value})}/></label>
<label className="block">Posição do Anexo I<select className="block max-w-full rounded border p-2" value={row.annexIItem??''} onChange={e=>change(row.id,{annexIItem:e.target.value,annexIOnly:undefined,confirmed:row.confirmed.filter(n=>n===0)})}><option value="">Ainda por determinar</option>{annexIEntries.filter(entry=>entry.id===row.annexIItem||`${entry.code} ${entry.context??''} ${entry.label}`.toLocaleLowerCase('pt').includes((annexSearch[`I:${row.id}`]??'').trim().toLocaleLowerCase('pt'))).map(entry=><option key={entry.id} value={entry.id}>{entry.code} — {entry.context?entry.context+' — ':''}{entry.label} (PDF{entry.pdfPage})</option>)}</select></label>
{row.annexIItem&&<p>{annexI?annexIReference(annexI):`Posição guardada não encontrada nesta edição: ${row.annexIItem}. Original conservado; escolha explicitamente a correspondência.`}</p>}
{!!annexI?.relatedTreatments?.length&&<div><p>Confira a natureza e o destino: há um tratamento existente que pode abranger este bem. Se for aplicável, use-o para conservar também o direito à dedução nas condições legais. Ao confirmar a passagem, conserva valores e origem e terá de rever as condições do tratamento escolhido; nenhum resultado anterior é substituído automaticamente.</p>
{annexI.relatedTreatments.map(id=>{const target=operationTreatments.find(t=>t.id===id);return target&&<button className="block underline" type="button" key={id} onClick={()=>run(()=>save({...book,rows:book.rows.map(r=>r.id===row.id?continueAnnexIOperation(r,id):r)}))}>Usar {target.label} e rever condições</button>;})}
{!annexI.relatedRequired&&<label className="block"><input type="checkbox" checked={row.annexIOnly===true} onChange={e=>change(row.id,{annexIOnly:e.target.checked})}/>Conferi a designação e o destino: esta operação não corresponde ao tratamento indicado acima; o fundamento explica a aplicação apenas do artigo9(12)(h).</label>}
</div>}
</fieldset>}
{row.treatment==='pharma_manufacturing_inputs'&&<fieldset className="space-y-2 rounded border p-2"><legend>Bem do Anexo III — edição Lei22/2022</legend>
<p>Escolha a linha pelo código e pela designação. O estabelecimento que transmite deve estar integrado no SNS; o destino hospitalar não substitui essa condição. A selecção não classifica automaticamente uma mercadoria nem confirma a sua utilização.</p>
<label className="block">Pesquisar código ou designação<input value={annexSearch[row.id]??''} onChange={e=>setAnnexSearch({...annexSearch,[row.id]:e.target.value})}/></label>
<label className="block">Linha do Anexo III<select className="block max-w-full rounded border p-2" value={row.pharmaAnnexItem??''} onChange={e=>change(row.id,{pharmaAnnexItem:e.target.value})}><option value="">Ainda por determinar</option>{pharmaAnnexEntries.filter(entry=>entry.id===row.pharmaAnnexItem||`${entry.code} ${entry.label}`.toLocaleLowerCase('pt').includes((annexSearch[row.id]??'').trim().toLocaleLowerCase('pt'))).map(entry=><option key={entry.id} value={entry.id}>{entry.code} — {entry.label} (PDF{entry.pdfPage})</option>)}</select></label>
{row.pharmaAnnexItem&&<p>{pharmaAnnexEntry(row.pharmaAnnexItem)?pharmaAnnexReference(pharmaAnnexEntry(row.pharmaAnnexItem)!):`Escolha guardada não encontrada nesta edição: ${row.pharmaAnnexItem}. Original conservado; seleccione explicitamente a correspondência.`}</p>}
<p>O exemplar repete2912.19.00 em duas linhas com designações diferentes e imprime2935. sem completar a posição. As linhas mantêm identidades próprias; não se inventam dígitos nem se estende a isenção apenas pelo código.</p>
</fieldset>}
{row.treatment.startsWith('fundraising_')&&<fieldset className="space-y-2 rounded border p-2"><legend>Manifestação ocasional — limite anual da entidade</legend><p>O total é declarado para a entidade em todo o ano, incluindo manifestações fora deste dossier. Várias vendas da mesma manifestação não são novas manifestações.</p>
{([['entityReference','Referência da entidade organizadora'],['annualEvents','Total anual de manifestações da entidade, incluindo esta'],['eventNumber','Número desta manifestação no ano']] as const).map(([field,label])=><label className="block" key={field}>{label}<input value={row.fundraiser?.[field]??''} onChange={e=>change(row.id,{fundraiser:{entityReference:'',annualEvents:'',eventNumber:'',activity:'',...row.fundraiser,[field]:e.target.value}})}/></label>)}
<label className="block">Actividade habitual isenta<select value={row.fundraiser?.activity??''} onChange={e=>change(row.id,{fundraiser:{entityReference:'',annualEvents:'',eventNumber:'',...row.fundraiser,activity:e.target.value}})}><option value="">Por identificar</option>{fundraisingActivities.filter(([id])=>row.treatment==='fundraising_nonprofit'?!id.endsWith('_public'):id!=='statutory_membership').map(([id,label])=><option key={id} value={id}>{label}</option>)}</select></label>
</fieldset>}
{row.treatment.startsWith('production_')&&row.treatment.endsWith('_opted')&&<fieldset className="space-y-2 rounded border p-2"><legend>Opção de tributação da produção — artigo11</legend>
<p>Complete apenas as datas em falta. A opção não cessa automaticamente ao fim de cinco anos. O prazo termina às 24 horas do dia correspondente; se faltar esse dia, no último dia do mesmo mês. O artigo11(3) exige declaração antes de expirar o prazo e fixa os efeitos em 1 de Janeiro seguinte, respeitando a permanência mínima.</p>
{book.rows.some(source=>source.id!==row.id&&source.taxOption)&&<label className="block">Reutilizar opção já preenchida neste dossier<select value={reuseOption?.rowId===row.id?reuseOption.sourceId:''} onChange={e=>setReuseOption(e.target.value?{rowId:row.id,sourceId:e.target.value}:null)}><option value="">Escolha a origem, se aplicável ao mesmo sujeito passivo</option>{book.rows.filter(source=>source.id!==row.id&&source.taxOption).map(source=><option key={source.id} value={source.id}>{source.description} — {source.establishment}</option>)}</select></label>}
{reuseOption?.rowId===row.id&&<div><p>Ao confirmar, substituirá o enquadramento e as datas da opção desta linha pelos da origem escolhida, conservando a data desta operação. Confirme que se aplicam ao mesmo sujeito passivo; o resultado anterior permanece no histórico.</p><button type="button" onClick={()=>run(()=>{const source=book.rows.find(r=>r.id===reuseOption.sourceId);if(!source?.taxOption)throw new Error('Origem da opção já não disponível; dados conservados.');change(row.id,{taxOption:{...structuredClone(source.taxOption),operationDate:row.taxOption?.operationDate??'',origin:{rowId:source.id,description:source.description,establishment:source.establishment}}});setReuseOption(null);})}>Confirmar reutilização da opção escolhida</button><button type="button" onClick={()=>setReuseOption(null)}>Conservar os dados desta linha</button></div>}
<label className="block">Tipo de declaração de opção<select value={row.taxOption?.mode??''} onChange={e=>change(row.id,{taxOption:{...emptyProductionTaxOption(),...row.taxOption,mode:e.target.value as ProductionTaxOption['mode']}})}><option value="">Por indicar</option><option value="annual">Opção com efeitos no ano seguinte</option><option value="startup">Opção na declaração de início da actividade</option></select></label>
<label className="block">Declaração de regresso à isenção<select value={row.taxOption?.returnStatus??''} onChange={e=>change(row.id,{taxOption:{...emptyProductionTaxOption(),...row.taxOption,returnStatus:e.target.value as ProductionTaxOption['returnStatus']}})}><option value="">Ainda desconhecido</option><option value="none">Não existe declaração de regresso</option><option value="declared">Existe declaração de regresso</option></select></label>
{([['declarationDate','Data da declaração de opção'],...(row.taxOption?.mode==='startup'?[['startupDate','Data de início da actividade']]:[]),['operationDate','Data da operação nesta linha'],...(row.taxOption?.returnStatus==='declared'||row.taxOption?.returnDeclarationDate?[['returnDeclarationDate','Data da declaração de regresso à isenção']]:[])] as Array<['declarationDate'|'startupDate'|'operationDate'|'returnDeclarationDate',string]>).map(([field,label])=><label className="block" key={field}>{label}<input type="date" value={row.taxOption?.[field]??''} onChange={e=>change(row.id,{taxOption:{...emptyProductionTaxOption(),...row.taxOption,[field]:e.target.value}})}/></label>)}
</fieldset>}
<p>{rule?.article}; {rule?.source}. Aplicação nesta versão: Janeiro–Dezembro2026, sujeita às condições seguintes.</p>
{rule?.conditions.map((condition,index)=><label className="block" key={index}><input type="checkbox" checked={row.confirmed.includes(index)} onChange={e=>change(row.id,{confirmed:e.target.checked?[...row.confirmed,index]:row.confirmed.filter(i=>i!==index)})}/> {condition}</label>)}
<label className="block">Documento ou pressuposto que sustenta estas condições<textarea className="block w-full rounded border p-2" value={row.evidence} onChange={e=>change(row.id,{evidence:e.target.value})}/></label>
<p>Se precisar de repartir uma venda agregada, conserve o valor de origem e prepare linhas discriminadas. Não altere silenciosamente a sua representação monetária.</p>
<button type="button" className="mr-3 underline" onClick={()=>run(()=>save(splitSales(book,row.id,crypto.randomUUID())))}>Repartir explicitamente esta venda, conservando o total de origem</button>
<button type="button" className="underline" onClick={()=>run(()=>save({...book,rows:book.rows.filter(r=>r.id!==row.id),periods:book.periods.map(p=>p.period===row.period?{...p,complete:false}:p)}))}>Remover esta linha do preenchimento (resultado anterior conservado)</button>
</details>;})}
{book.periods.map(p=><label className="block" key={p.period}><input type="checkbox" checked={p.complete} onChange={e=>run(()=>save({...book,periods:book.periods.map(v=>v.period===p.period?{...v,complete:e.target.checked}:v)}))}/> {p.period}: incluí todas as operações deste período; lista vazia significa ausência expressamente confirmada.</label>)}
<p>Limites: outras isenções/bases especiais e correspondência do campo06 permanecem por delimitar. IVA incluído a5% conserva a fracção exacta e apresenta um decimal a6casas; a aproximação de apresentação não constitui regra declarativa. O desconhecido nunca é assumido como zero.</p>
<button type="button" disabled={!book.periods.length} className="rounded bg-emerald-800 p-2 text-white disabled:opacity-50" onClick={()=>run(()=>save(recordSales(draft,book)))}>Calcular e guardar operações IVA</button>
{book.result&&<><p role="status">{salesCurrent(draft,book)?'Resultado correspondente às entradas.':'Resultado histórico conservado; reveja as alterações antes de recalcular.'}</p><dl>{salesReportRows(draft).map(([,label,value,origin],index)=><div className="break-inside-avoid border-t py-2" key={index}><dt className="font-semibold">{label}</dt><dd>{value}<small className="block">{origin}</small></dd></div>)}</dl></>}
</section>;
}
+22
View File
@@ -0,0 +1,22 @@
/** Exact amounts in currency units; decimal formatting is presentation, never a tax rule. */
export type FiscalFraction = { numerator:string; denominator:string };
function parts(value:FiscalFraction):[bigint,bigint] {
if(!/^-?\d{1,80}$/.test(value.numerator)||!/^\d{1,80}$/.test(value.denominator)||BigInt(value.denominator)===0n)throw new Error('Representação racional inválida; sem substituição por zero.');
return [BigInt(value.numerator),BigInt(value.denominator)];
}
export function fraction(n:bigint,d=1n):FiscalFraction {
if(d===0n)throw new Error('Denominador nulo.');if(d<0n){n=-n;d=-d;}
let a=n<0n?-n:n,b=d;while(b){const r=a%b;a=b;b=r;}return {numerator:String(n/(a||1n)),denominator:String(d/(a||1n))};
}
export function decimalFraction(raw:string):FiscalFraction {
if(!/^\d{1,18}(\.\d{1,6})?$/.test(raw))throw new Error('Montante decimal inválido.');const [a,b='']=raw.split('.');return fraction(BigInt(a+b),10n**BigInt(b.length));
}
export function addFractions(values:FiscalFraction[]):FiscalFraction {return values.reduce((a,b)=>{const [an,ad]=parts(a),[bn,bd]=parts(b);return fraction(an*bd+bn*ad,ad*bd);},fraction(0n));}
export function subtractFractions(a:FiscalFraction,b:FiscalFraction):FiscalFraction {const [an,ad]=parts(a),[bn,bd]=parts(b);return fraction(an*bd-bn*ad,ad*bd);}
export function positiveFraction(value:FiscalFraction):FiscalFraction {return parts(value)[0]>0n?value:fraction(0n);}
export function fractionPresentation(value:FiscalFraction):{decimal:string;approximate:boolean} {
const [raw,d]=parts(value),n=raw<0n?-raw:raw,scaled=n*1000000n;
const q=(scaled+d/2n)/d,dec=(q%1000000n).toString().padStart(6,'0').replace(/0+$/,'').padEnd(2,'0');
return {decimal:`${raw<0n?'-':''}${q/1000000n}.${dec}`,approximate:scaled%d!==0n};
}
export function fractionLabel(value:FiscalFraction):string {parts(value);return `${value.numerator}/${value.denominator}`;}
+208
View File
@@ -0,0 +1,208 @@
import { modeloAPurchaseReferences } from './iva-modelo-a.ts';
import { monthlyIvaInput, monthlyIvaKey, readMonthlyIvaRecord, readMonthlyIvaSettings } from './monthly-iva.ts';
import { restoreBusinessPlanSnapshot } from './business-financial-plan.ts';
import { salesBook, salesCurrent as salesOperationsCurrent } from './iva-operations.ts';
import { addFractions, decimalFraction, fractionLabel, fractionPresentation, positiveFraction, subtractFractions, type FiscalFraction } from './fiscal-rational.ts';
export const acquisitionVersion = 'modelo-a-internal-acquisitions/1';
export const acquisitionBasis = 'CIVA arts.18(1)(a),18(2) (Lei10/2025),18(3–5),19(1)(a),19(2),20 (Lei22/2022),21(1–3); âmbito interno, afectação exclusiva, mesmo período, sem exclusões ou dedução parcial.';
export const acquisitionSources = 'Modelo A DOCX 62c198e9 / v1 63d45fa8; VAT Return.pdf SHA256 9c0b99a810c7db53eb75d63c22ee22fb86a50ba57bd5509041ed80ee10f75741, p.1; CIVA republicado Lei13/2016, PDF14–16; Lei22/2022, art.20; Lei10/2025, arts.18/19, PDF13.';
type Choice = '' | 'yes' | 'no';
export type Acquisition = {
id: string; field: '08'|'09'|'10'; period: string; origin: 'projected'|'effective';
sourceMonth: number|null; sourcePeriod?:string; sourceField?:'inventory'|'asset'|'operating'; sourceAmount: string|null; sourceCurrency: string; sourceBasis: ''|'net'|'gross';
net: string; vat: string; gross: string; documentType: ''|'invoice'|'equivalent'; documentRef: string; documentDate: string; documentLine:string;
supplier: string; supplierRegistered: Choice; legalDocument: Choice; held: Choice; domestic: Choice;
allocation: ''|'taxable_only'|'mixed'|'no_right'; exclusion: ''|'none'|'excluded'|'special';
integrity: Choice; description: string;
};
export type AcquisitionResult = {id:string; net:string|null; vat:string|null; gross:string|null; deductible:string|null; reason:string};
type PeriodInput = {period:string; complete:boolean; absent:string[]};
export type AcquisitionBook = {currency:string; taxpayerRegistered?:Choice; rows:Acquisition[]; periods:PeriodInput[]; result?:AcquisitionCalculation};
export type AcquisitionCalculation = {version:string; revision:number; calculatedAt:string; opportunity:string; location:string; currency:string; sourceKey:string; basis:string; sources:string;
declarations?:{taxpayerRegistered:Choice;periods:PeriodInput[]}; rows:AcquisitionResult[]; inputs:Acquisition[]; periods:Array<{period:string; fields:Record<string,string|null>; exactFields?:Record<string,FiscalFraction|null>; reasons:string[]}>};
type Store = {version:1; books:Record<string,AcquisitionBook>};
const excluded = ['03','04','05','06','07','11','12','13'];
export const acquisitionExcludedFields = excluded;
export function acquisitionScope(draft:Record<string,unknown>):string {
if(!draft.context_opportunity) {
try {const context=JSON.parse(String(draft.context_applicability_snapshot??''));if(context.opportunity_choices?.length>1)throw new Error('Escolha a oportunidade em tratamento antes de preparar as compras.');}
catch(cause) {if(cause instanceof Error && cause.message.startsWith('Escolha'))throw cause;}
}
return String(draft.context_opportunity || 'general');
}
export function readAcquisitionStore(raw:unknown):Store {
if (!raw) return {version:1,books:{}};
const value=JSON.parse(String(raw));
if (value?.version!==1 || !value.books || typeof value.books!=='object' || Array.isArray(value.books)) throw new Error('Compras fiscais guardadas não recuperáveis; dados preservados.');
for(const book of Object.values(value.books) as AcquisitionBook[]) {
if(!book || !Array.isArray(book.rows) || !Array.isArray(book.periods) || typeof book.currency!=='string') throw new Error('Formato de compras não recuperável; sem substituição.');
const stringKeys=Object.keys(newAcquisition('','','')).filter(key=>!['sourceMonth','sourceAmount'].includes(key));
if(book.rows.some(row=>!row || stringKeys.some(key=>typeof row[key as keyof Acquisition]!=='string') || !(row.sourceMonth===null || Number.isInteger(row.sourceMonth)) || !(row.sourceAmount===null || typeof row.sourceAmount==='string')) || book.periods.some(p=>!p || typeof p.period!=='string' || typeof p.complete!=='boolean' || !Array.isArray(p.absent) || p.absent.some(f=>typeof f!=='string'))) throw new Error('Linhas ou períodos de compras não recuperáveis; os dados guardados foram preservados.');
}
return value;
}
export function acquisitionBook(draft:Record<string,unknown>):AcquisitionBook {
return readAcquisitionStore(draft.modelo_a_snapshot).books[acquisitionScope(draft)] ?? {currency:String(draft.currency ?? ''),rows:[],periods:[]};
}
export function saveAcquisitionBook(draft:Record<string,unknown>,book:AcquisitionBook):string {
const store=readAcquisitionStore(draft.modelo_a_snapshot);
return JSON.stringify({...store,books:{...store.books,[acquisitionScope(draft)]:book}});
}
export function newAcquisition(id:string,period:string,currency:string):Acquisition {
return {id,field:'09',period,origin:'projected',sourceMonth:null,sourceAmount:null,sourceCurrency:currency,sourceBasis:'',net:'',vat:'',gross:'',documentType:'',documentRef:'',documentDate:'',documentLine:'',supplier:'',supplierRegistered:'',legalDocument:'',held:'',domestic:'',allocation:'',exclusion:'',integrity:'',description:''};
}
function periods(draft:Record<string,unknown>):string[] {
try {return monthlyIvaInput(draft,readMonthlyIvaSettings(String(draft.monthly_iva_settings ?? ''))).monthly_sales.map(r=>r.date.slice(0,7));}
catch {return [];}
}
export function acquisitionPlanReferences(draft:Record<string,unknown>):Array<{key:string;kind:'inventory'|'asset'|'operating';month:number;period:string;amount:string|null;currency:string;label:string}> {
const dates=periods(draft),plan=restoreBusinessPlanSnapshot(String(draft.business_plan_snapshot??''));
if(!plan || !dates.length)return [];
if(plan.currency!==draft.currency)throw new Error('Moeda do plano divergente; não reutilizar como moeda do projecto.');
const inventory=modeloAPurchaseReferences(draft).map(r=>({key:`inventory:${r.month}`,kind:'inventory' as const,month:r.month,period:dates[r.month-1],amount:r.declared,currency:plan.currency,label:`Compras/encomendas — mês ${r.month}`}));
const asset={key:'asset:1',kind:'asset' as const,month:1,period:dates[0],amount:plan.assetInvestment?.trim()||null,currency:plan.currency,label:'Orçamento de investimento em activos — período a confirmar'};
const operating=dates.map((period,index)=>({key:`operating:${index+1}`,kind:'operating' as const,month:index+1,period,amount:(plan.monthlyOperatingExpensesByPeriod?plan.monthlyOperatingExpensesByPeriod[index]:plan.monthlyOperatingExpenses)?.trim()||null,currency:plan.currency,label:`Orçamento de despesas operacionais — mês ${index+1}`}));
return [...inventory,asset,...operating];
}
export function reuseAcquisitions(draft:Record<string,unknown>,book:AcquisitionBook):AcquisitionBook {
const dates=periods(draft); if(!dates.length) throw new Error('Defina o período mensal e resolva a moeda da projecção antes de reutilizar compras.');
const rows=[...book.rows];
for(const reference of modeloAPurchaseReferences(draft)) {
if(rows.some(r=>r.sourceMonth===reference.month)) continue;
rows.push({...newAcquisition(`plan-${reference.month}`,dates[reference.month-1],String(draft.currency ?? '')),sourceMonth:reference.month,sourcePeriod:dates[reference.month-1],sourceAmount:reference.declared,description:`Compras/encomendas do plano — mês ${reference.month}`});
}
return {...book,rows,periods:dates.map(period=>book.periods.find(p=>p.period===period) ?? {period,complete:false,absent:[]})};
}
// Decimal arithmetic for aggregation only. No binary rounding and no invented purchase tax rate.
function amount(raw:unknown):bigint|null {
if(typeof raw!=='string' || !/^\d{1,15}(\.\d{1,6})?$/.test(raw.trim())) return null;
const [a,b='']=raw.trim().split('.');return BigInt(a)*1000000n+BigInt(b.padEnd(6,'0'));
}
function money(value:bigint):string {const a=value/1000000n,b=(value%1000000n).toString().padStart(6,'0').replace(/0+$/,'').padEnd(2,'0');return `${a}.${b}`;}
function sum(values:Array<string|null>):string|null {const parsed=values.map(amount);return parsed.some(v=>v===null)?null:money((parsed as bigint[]).reduce((a,b)=>a+b,0n));}
function dateValid(raw:string):boolean {const date=new Date(`${raw}T00:00:00Z`);return /^\d{4}-\d{2}-\d{2}$/.test(raw) && Number.isFinite(date.getTime()) && date.toISOString().slice(0,10)===raw;}
export function evaluateAcquisition(row:Acquisition,currency:string,taxpayerRegistered:Choice=''):AcquisitionResult {
let n=amount(row.net),v=amount(row.vat),g=amount(row.gross);
if(n!==null && v!==null && g===null && !row.gross.trim()) g=n+v;
if(g!==null && v!==null && n===null && !row.net.trim() && g>=v) n=g-v;
if(n!==null && g!==null && v===null && !row.vat.trim() && g>=n) v=g-n;
const result:AcquisitionResult={id:row.id,net:n===null?null:money(n),vat:v===null?null:money(v),gross:g===null?null:money(g),deductible:null,reason:''};
const stop=(reason:string,deductible:string|null=null)=>({...result,reason,deductible});
if(currency!=='MZN' || row.sourceCurrency!==currency) return stop('Divergência ou moeda fora de MZN; sem conversão.');
if(!/^2026-(0[1-9]|1[0-2])$/.test(row.period)) return stop('Período fora do âmbito 2026 ou em falta.');
if(n===null || v===null || g===null || n+v!==g) return stop('Indique dois valores válidos; líquido + IVA deve corresponder ao bruto.');
if(row.sourceMonth!==null && (!row.sourceBasis || amount(row.sourceAmount)!==(row.sourceBasis==='net'?n:g))) return stop('Classifique ou resolva a divergência do valor de origem; não foi reinterpretado.');
if(v===0n) return stop('IVA explicitamente indicado como zero; não existe imposto a deduzir nesta aquisição.','0.00');
if(taxpayerRegistered!=='yes') return stop('Confirme o enquadramento do adquirente como sujeito passivo de IVA no regime normal; não é inferido da organização.');
if(row.allocation==='no_right' || row.exclusion==='excluded' || row.supplierRegistered==='no' || row.legalDocument==='no' || row.integrity==='no') return stop('Sem dedução no âmbito declarado: afectação, exclusão, fornecedor ou documento não elegível.','0.00');
if(row.domestic!=='yes') return stop('Aquisição interna por confirmar; importações fora deste lote.');
if(row.allocation!=='taxable_only' || row.exclusion!=='none') return stop('Confirme afectação exclusiva a operações tributadas e ausência de exclusões; casos mistos/especiais não calculados.');
if(!['invoice','equivalent'].includes(row.documentType) || !row.documentRef.trim() || !row.supplier.trim() || row.supplierRegistered!=='yes' || row.legalDocument!=='yes' || row.held!=='yes' || row.integrity!=='yes') return stop('Documento, fornecedor inscrito, posse e condições de dedução ainda incompletos.');
if(!dateValid(row.documentDate) || row.documentDate.slice(0,7)!==row.period) return stop('Data do documento e período de dedução devem coincidir neste lote; dedução posterior não presumida.');
return stop(row.origin==='projected'?'Dedução projectada sob pressupostos explícitos; não certifica factura ou declaração.':'Dedução segundo dados e condições declarados; sem submissão ou certificação pela AT.',money(v));
}
function sourceKey(draft:Record<string,unknown>,book:AcquisitionBook):string {
const raw=JSON.stringify([acquisitionScope(draft),draft.currency??'',draft.province_id??'',draft.district_id??'',draft.business_plan_snapshot,draft.monthly_iva_settings,draft.monthly_iva_snapshot,book.currency,book.taxpayerRegistered,book.rows,book.periods]);
// Change detection only, never an authorization or authenticity token.
let hash=14695981039346656037n;for(let i=0;i<raw.length;i++)hash=BigInt.asUintN(64,(hash^BigInt(raw.charCodeAt(i)))*1099511628211n);
const operations=(readAcquisitionStore(draft.modelo_a_snapshot) as Store & {salesOperations?:Record<string,unknown>}).salesOperations?.[acquisitionScope(draft)];
return `${raw.length}:${hash.toString(16)}${operations?`:${JSON.stringify(operations)}`:''}`;
}
function location(draft:Record<string,unknown>):string {
const labels=draft.selection_labels as Record<string,unknown>|undefined;
return ['province_id','district_id'].filter(key=>draft[key]).map(key=>String(draft[`${key}_label`]??labels?.[key]??draft[key])).join(' / ');
}
export function acquisitionCurrent(draft:Record<string,unknown>,book:AcquisitionBook):boolean {return !!book.result && book.result.version===acquisitionVersion && book.result.opportunity===acquisitionScope(draft) && book.result.sourceKey===sourceKey(draft,book);}
export function calculateAcquisitions(draft:Record<string,unknown>,book:AcquisitionBook,now=new Date().toISOString()):AcquisitionCalculation {
const scope=acquisitionScope(draft),dates=periods(draft);
if(book.currency!=='MZN' || draft.currency!==book.currency) throw new Error('Resolva a moeda de origem das compras; valores preservados sem conversão.');
if(!dates.length) throw new Error('Período de vendas por determinar.');
if(new Set(book.rows.map(r=>r.id)).size!==book.rows.length) throw new Error('Existem compras com identidade repetida.');
const documents=book.rows.filter(r=>r.documentRef.trim() && r.supplier.trim()).map(r=>JSON.stringify([r.origin,r.supplier.trim().toLowerCase(),r.documentRef.trim().toLowerCase(),r.documentDate,r.documentLine?.trim()??'']));
if(new Set(documents).size!==documents.length) throw new Error('Documento/linha repetido: discrimine linhas distintas ou remova a duplicação antes de deduzir.');
if(book.rows.some(r=>!['08','09','10'].includes(r.field) || !dates.includes(r.period))) throw new Error('Classifique cada aquisição num campo08–10 e num período da projecção.');
const references=acquisitionPlanReferences(draft);
for(const row of book.rows.filter(r=>r.sourceMonth!==null)) {
const current=references.find(p=>p.month===row.sourceMonth && p.kind===(row.sourceField??'inventory'));
if(!current || current.amount!==row.sourceAmount || (current.kind!=='asset' && row.sourcePeriod && current.period!==row.sourcePeriod)) throw new Error('As compras ou orçamentos do plano mudaram. Resolva a divergência de origem antes de calcular; histórico preservado.');
}
const rows=book.rows.map(row=>evaluateAcquisition(row,book.currency,book.taxpayerRegistered));
const record=readMonthlyIvaRecord(String(draft.monthly_iva_snapshot ?? ''));
let salesCurrent=false;
try {salesCurrent=!!record && record.execution.status==='completed' && monthlyIvaKey(record.input)===monthlyIvaKey(monthlyIvaInput(draft,readMonthlyIvaSettings(String(draft.monthly_iva_settings ?? ''))));} catch { /* Preserve history, never fabricate 01/02. */ }
const projection=record?.execution.result_snapshot?.monthly_projection as {rows?:Array<{date:string;net_sales:string|null;vat:string|null}>}|undefined;
const calculated=dates.map(period=>{
const input=book.periods.find(p=>p.period===period), reasons:string[]=[], fields:Record<string,string|null>={};
const declaredAmount=(key:string)=>{const value=amount(String(draft[key]??''));return value!==null && value>0n;};
if(input?.absent.includes('11') && (declaredAmount('imports') || book.rows.some(r=>r.period===period && r.domestic==='no'))) throw new Error('Existem importações declaradas. Não confirme ausência no campo11; enquadramento fora deste lote.');
if(input?.absent.includes('07') && declaredAmount('sales_exempt')) throw new Error('Existem vendas isentas declaradas. Resolva o período e a classificação antes de confirmar ausência no campo07.');
if(input?.absent.includes('05') && (declaredAmount('exports')||declaredAmount('sales_zero_rate'))) throw new Error('Existem exportações ou vendas de outro enquadramento. Não confirme ausência no campo05 sem resolver a classificação.');
const sales=salesCurrent?projection?.rows?.find(r=>r.date.slice(0,7)===period):null;
fields['01']=sales?.net_sales??null;fields['02']=sales?.vat??null;
if(!sales || sales.net_sales===null || sales.vat===null) reasons.push('01/02: vendas ou IVA mensal em falta, execução incompleta ou desactualizada.');
for(const field of excluded) fields[field]=input?.absent.includes(field)?'0.00':null;
const operations=salesBook(draft);
if(operations.rows.length || operations.result) {
const classified=salesOperationsCurrent(draft,operations)?operations.result?.periods.find(p=>p.period===period):null;
for(const field of ['01','02','03','04','05','06','07'])fields[field]=classified?.fields[field]??null;
if(!classified)reasons.push('Operações L1 alteradas ou sem resultado correspondente: recalcule a classificação; não usar01/02 antigos nem ausência presumida.');
else reasons.push(...classified.reasons);
}
for(const field of ['08','09','10']) {
const matching=book.rows.filter(r=>r.period===period && r.field===field);
fields[field]=input?.complete ? sum(matching.map(r=>rows.find(x=>x.id===r.id)!.deductible)) : null;
if((operations.rows.length || operations.result) && operations.rows.some(r=>r.period===period && !['general','export_goods'].includes(r.treatment)) && matching.some(r=>rows.find(x=>x.id===r.id)!.deductible!=='0.00')) {
fields[field]=null;
reasons.push(`Campo${field}: operações reduzidas/isentas/outras exigem afectar cada aquisição; não reutilizar dedução exclusiva geral como se fosse universal (L2).`);
}
}
if(!input?.complete) reasons.push('Aquisições08–10: confirme que todas as compras do período foram incluídas, mesmo quando não existam.');
for(const row of book.rows.filter(r=>r.period===period)) {const r=rows.find(x=>x.id===row.id)!;if(r.deductible===null) reasons.push(`${row.description||row.id}: ${r.reason}`);}
for(const field of excluded) if(fields[field]===null) reasons.push(`Campo${field}: fora deste lote, sem declaração expressa de inexistência de operações.`);
fields['14']=sum(['01','03','05','06','07'].map(f=>fields[f]));
fields['15']=sum(['08','09','10','11','12'].map(f=>fields[f]));
fields['16']=sum(['02','04','13'].map(f=>fields[f]));
const state=amount(fields['16']),taxpayer=amount(fields['15']);
fields['17']=state===null||taxpayer===null?null:money(state>taxpayer?state-taxpayer:0n);
fields['18']=state===null||taxpayer===null?null:money(taxpayer>state?taxpayer-state:0n);
const classified=salesOperationsCurrent(draft,operations)?operations.result?.periods.find(p=>p.period===period):null;
if(classified?.exactFields) {
const exactFields:Record<string,FiscalFraction|null>={};
for(const f of ['01','02','03','04','05','06','07','08','09','10','11','12','13'])exactFields[f]=classified.exactFields[f]??(fields[f]===null?null:decimalFraction(fields[f]!));
for(const [f,parts] of [['14',['01','03','05','06','07']],['15',['08','09','10','11','12']],['16',['02','04','13']]] as const)exactFields[f]=parts.some(k=>exactFields[k]===null)?null:addFractions(parts.map(k=>exactFields[k]!));
exactFields['17']=exactFields['16']&&exactFields['15']?positiveFraction(subtractFractions(exactFields['16'],exactFields['15'])):null;
exactFields['18']=exactFields['16']&&exactFields['15']?positiveFraction(subtractFractions(exactFields['15'],exactFields['16'])):null;
for(const f of Object.keys(exactFields))fields[f]=exactFields[f]?fractionPresentation(exactFields[f]!).decimal:null;
reasons.push('Totais derivados das fracções exactas, sem somar aproximações das linhas; decimais a6casas são apresentação técnica, não arredondamento declarativo.');
return {period,fields,exactFields,reasons};
}
return {period,fields,reasons};
});
return {version:acquisitionVersion,revision:(book.result?.revision??0)+1,calculatedAt:now,opportunity:scope,location:location(draft),currency:book.currency,sourceKey:sourceKey(draft,book),basis:acquisitionBasis,sources:acquisitionSources,declarations:{taxpayerRegistered:book.taxpayerRegistered??'',periods:structuredClone(book.periods)},rows,inputs:structuredClone(book.rows),periods:calculated};
}
export function acquisitionReportRows(draft:Record<string,unknown>):Array<[string,string,string,string]> {
if(!draft.modelo_a_snapshot) return [];
try {
const book=acquisitionBook(draft),result=book.result;
if(!result) return [['IVA mensal','Compras — Modelo A','Sem cálculo guardado para a oportunidade escolhida','Sem dedução presumida']];
const context=`${result.currency}; oportunidade ${result.opportunity}; localização ${result.location || 'não indicada'}; ${result.version}; revisão ${result.revision}; ${result.calculatedAt}`;
const out:Array<[string,string,string,string]>=[['IVA mensal','Apuramento parcial Modelo A',acquisitionCurrent(draft,book)?'Versão correspondente às entradas':'Histórico desactualizado; não aplicar à projecção actual',context],['IVA mensal','Fundamento das aquisições',result.basis,result.sources]];
for(const row of result.inputs) {
const r=result.rows.find(x=>x.id===row.id)!;
const source=row.sourceMonth===null?'Introduzido pelo utilizador':`Plano (${row.sourceField==='asset'?'orçamento de activos':row.sourceField==='operating'?'orçamento operacional':'compras/encomendas'}), mês ${row.sourceMonth}, ${row.sourcePeriod??'período de origem não indicado'}, ${row.sourceAmount??'valor em falta'} ${row.sourceCurrency}; ${row.sourceBasis==='net'?'sem IVA':row.sourceBasis==='gross'?'com IVA':'base por classificar'}`;
const allocation={taxable_only:'exclusiva a operações tributadas',mixed:'mista',no_right:'sem direito à dedução','':'por indicar'}[row.allocation];
out.push(['IVA mensal',`Aquisição ${row.id} — campo${row.field} — ${row.period}`,`${row.description}; líquido ${r.net??'Indeterminado'}; IVA ${r.vat??'Indeterminado'}; bruto ${r.gross??'Indeterminado'}; dedutível ${r.deductible??'Indeterminado'}`,`${context}; ${row.origin==='projected'?'Projecção':'Dados efectivos declarados'}; ${source}; ${row.documentType==='invoice'?'Factura':row.documentType==='equivalent'?'Documento equivalente':'Documento por indicar'} ${row.documentRef}, ${row.documentDate}, linha ${row.documentLine||'única'}; fornecedor ${row.supplier}; afectação ${allocation}; ${r.reason}`]);
}
for(const period of result.periods) {
const entries=Object.entries(period.fields).sort(([a],[b])=>Number(a)-Number(b));
const declaration=result.declarations?.periods.find(p=>p.period===period.period);
const declarationOrigin=declaration?`Aquisições08–10 ${declaration.complete?'declaradas completas':'por completar'}; ausência de operações expressamente declarada nos campos ${declaration.absent.join(', ')||'nenhum'}.`:'Declarações detalhadas não recuperáveis nesta versão histórica.';
out.push(['IVA mensal',`Modelo A — ${period.period} — parcelas01–13`,entries.filter(([field])=>Number(field)<=13).map(([field,value])=>`${field}: ${value??'Indeterminado'}`).join('; '),`${context}; ${declarationOrigin}`]);
out.push(['IVA mensal',`Modelo A — ${period.period} — totais14–18`,entries.filter(([field])=>Number(field)>=14).map(([field,value])=>`${field}: ${value??'Indeterminado'}`).join('; '),context]);
if(period.exactFields)out.push(['IVA mensal',`Modelo A — ${period.period} — precisão exacta`,Object.entries(period.exactFields).map(([f,v])=>`${f}: ${v?fractionLabel(v):'Indeterminado'}`).join('; '),'Fracções em MZN; apresentação decimal técnica, sem regra declarativa presumida.']);
if(period.reasons.length)out.push(['IVA mensal',`Modelo A — ${period.period} — pendências`,period.reasons.join(' '),result.sources]);
}
return out;
} catch {return [['IVA mensal','Compras — Modelo A','Não foi possível recuperar os dados guardados','Preservados, sem substituição por zero']];}
}
+181
View File
@@ -0,0 +1,181 @@
// Accepted official exemplar: preserve qualifiers and uncoded group headings, not tariff inference.
export const annexIVersion='annexI-lei22-2022/1';
export const annexISource='Lei22/2022, art.3(1), AnexoI, PDF5–11, p.2252(29)–(35); efeitos01/01/2023';
export const annexIPdfSha256='ea1b0dc6f5cf6e595f6d9a19e7042f398999e0087caef1785f6e8fac571b5f53';
export type AnnexIEntry={id:string;code:string;label:string;pdfPage:number;lastPdfPage:number;context?:string;relatedTreatments?:string[];relatedRequired?:boolean};
export const annexIEntries:AnnexIEntry[]=[
{"id":"annexI-2022-001","code":"0102.21.00","label":"-Bovinos domésticos - Reprodutores de raça pura","pdfPage":5,"lastPdfPage":5},
{"id":"annexI-2022-002","code":"0102.31.00","label":"-Búfalos - Reprodutores de raça pura","pdfPage":5,"lastPdfPage":5},
{"id":"annexI-2022-003","code":"0103.10.00","label":"Animais vivos da espécie suína - Reprodutores de raça pura","pdfPage":5,"lastPdfPage":5},
{"id":"annexI-2022-004","code":"0104.10.10","label":"- Ovinos - Reprodutores de raça pura","pdfPage":5,"lastPdfPage":5},
{"id":"annexI-2022-005","code":"0104.20.10","label":"- Caprinos - Reprodutores de raça pura","pdfPage":5,"lastPdfPage":5},
{"id":"annexI-2022-006","code":"0105.11.10","label":"- Galos e galinhas (De peso não superior a 185g) - Reprodutores certificados","pdfPage":5,"lastPdfPage":5},
{"id":"annexI-2022-007","code":"0105.12.10","label":"- Peruas e perus (De peso não superior a 185g) -Reprodutores certificados","pdfPage":5,"lastPdfPage":5},
{"id":"annexI-2022-008","code":"0105.13.10","label":"- Patos - Reprodutores certificados","pdfPage":5,"lastPdfPage":5},
{"id":"annexI-2022-009","code":"0105.14.10","label":"-Gansos - Reprodutores certificados","pdfPage":5,"lastPdfPage":5},
{"id":"annexI-2022-010","code":"0105.94.10","label":"-Galos e galinhas - Reprodutores certificados e poedeiras","pdfPage":5,"lastPdfPage":5},
{"id":"annexI-2022-011","code":"0301.99.10","label":"- Peixes reprodutores","pdfPage":5,"lastPdfPage":5},
{"id":"annexI-2022-012","code":"0306.36.10","label":"- Camarões - Larvas de camarão com comprimento não superior a 1 mm","pdfPage":5,"lastPdfPage":5},
{"id":"annexI-2022-013","code":"0402.21.10","label":"- Leite em pó, grânulos ou outras formas sólidas, concentrados sem adição de açúcar ou de outros edulcorantes, com um teor, em peso, de matérias gordas, superior a 1,5%, para uso na indústria acondicionado em embalagens de capacidade igual ou superior a 25Kg","pdfPage":5,"lastPdfPage":5,"relatedTreatments":["listed_infant_powdered_milk"],"relatedRequired":false},
{"id":"annexI-2022-014","code":"0404.90.10","label":"-Soro de leite para aleitamento de crias de animais","pdfPage":5,"lastPdfPage":5},
{"id":"annexI-2022-015","code":"0407.11.00","label":"Ovos de aves, com casca, frescos, conservados ou cozidos. - Ovos para incubação certificados","pdfPage":5,"lastPdfPage":5},
{"id":"annexI-2022-016","code":"0511.10.00","label":"- Sémen de bovino","pdfPage":5,"lastPdfPage":5},
{"id":"annexI-2022-017","code":"0511.10.10","label":"- Sémen de outras espécies","pdfPage":5,"lastPdfPage":5},
{"id":"annexI-2022-018","code":"0511.99.10","label":"- Embriões de bovino","pdfPage":5,"lastPdfPage":5},
{"id":"annexI-2022-019","code":"0511.99.20","label":"- Embriões de outras espécies","pdfPage":5,"lastPdfPage":5},
{"id":"annexI-2022-020","code":"0602.90.20","label":"-Mudas de plantas florestais e de fruteiras","pdfPage":5,"lastPdfPage":5},
{"id":"annexI-2022-021","code":"0701.10.00","label":"- Batata-semente","pdfPage":5,"lastPdfPage":5,"relatedTreatments":["listed_potato"],"relatedRequired":false},
{"id":"annexI-2022-022","code":"0701.90.00","label":"-Outras","pdfPage":5,"lastPdfPage":5,"relatedTreatments":["listed_potato"],"relatedRequired":false},
{"id":"annexI-2022-023","code":"0702.00.00","label":"Tomate, frescos ou refrigerados","pdfPage":5,"lastPdfPage":5,"relatedTreatments":["listed_fresh_chilled_tomato"],"relatedRequired":true},
{"id":"annexI-2022-024","code":"0703.10.11","label":"- Cebolas -De semente","pdfPage":5,"lastPdfPage":5,"relatedTreatments":["listed_onion"],"relatedRequired":false},
{"id":"annexI-2022-025","code":"0703.10.19","label":"-Outras","pdfPage":5,"lastPdfPage":5,"relatedTreatments":["listed_onion"],"relatedRequired":false},
{"id":"annexI-2022-026","code":"0713.32.10","label":"- Feijão Adzuki destinado à sementeira","pdfPage":5,"lastPdfPage":5},
{"id":"annexI-2022-027","code":"0713.33.10","label":"- Feijão comum -destinado à sementeira","pdfPage":6,"lastPdfPage":6},
{"id":"annexI-2022-028","code":"0713.39.10","label":"- Outros feijões -destinados à sementeira","pdfPage":6,"lastPdfPage":6},
{"id":"annexI-2022-029","code":"0801.19.10","label":"- Semente de coco híbrido","pdfPage":6,"lastPdfPage":6},
{"id":"annexI-2022-030","code":"0801.19.20","label":"- Semente de coco não híbrido","pdfPage":6,"lastPdfPage":6},
{"id":"annexI-2022-031","code":"1001.11.00","label":"-Trigo duro - para sementeira","pdfPage":6,"lastPdfPage":6,"relatedTreatments":["listed_wheat"],"relatedRequired":false},
{"id":"annexI-2022-032","code":"1001.91.00","label":"-Outros -Para sementeira","pdfPage":6,"lastPdfPage":6,"relatedTreatments":["listed_wheat"],"relatedRequired":false},
{"id":"annexI-2022-033","code":"1002.10.00","label":"-Centeio -Para sementeira","pdfPage":6,"lastPdfPage":6},
{"id":"annexI-2022-034","code":"1003.10.00","label":"-Cevada -Para sementeira","pdfPage":6,"lastPdfPage":6},
{"id":"annexI-2022-035","code":"1004.10.00","label":"-Aveia -Para sementeira","pdfPage":6,"lastPdfPage":6},
{"id":"annexI-2022-036","code":"1005.10.00","label":"- Milho - Para sementeira","pdfPage":6,"lastPdfPage":6,"relatedTreatments":["listed_maize"],"relatedRequired":false},
{"id":"annexI-2022-037","code":"1006.10.10","label":"- Arroz com casca -Destinado à sementeira","pdfPage":6,"lastPdfPage":6,"relatedTreatments":["listed_rice"],"relatedRequired":false},
{"id":"annexI-2022-038","code":"1007.10.00","label":"- Sorgo de grão -para sementeira","pdfPage":6,"lastPdfPage":6},
{"id":"annexI-2022-039","code":"1008.21.00","label":"-Painço -Para sementeira","pdfPage":6,"lastPdfPage":6},
{"id":"annexI-2022-040","code":"1008.90.21","label":"- Mexoeira -Para sementeira","pdfPage":6,"lastPdfPage":6},
{"id":"annexI-2022-041","code":"1008.90.91","label":"-Outros cereais -Para sementeira","pdfPage":6,"lastPdfPage":6},
{"id":"annexI-2022-042","code":"1101.00.00","label":"Farinhas de trigo ou mistura de trigo com centeio","pdfPage":6,"lastPdfPage":6,"relatedTreatments":["listed_wheat_flour"],"relatedRequired":false},
{"id":"annexI-2022-043","code":"1102.20.00","label":"- Farinha de milho","pdfPage":6,"lastPdfPage":6,"relatedTreatments":["listed_maize_flour"],"relatedRequired":true},
{"id":"annexI-2022-044","code":"1201.10.00","label":"Soja, mesmo triturada -Para sementeira","pdfPage":6,"lastPdfPage":6},
{"id":"annexI-2022-045","code":"1202.30.00","label":"Amendoins. -Para sementeira","pdfPage":6,"lastPdfPage":6},
{"id":"annexI-2022-046","code":"1204.00.10","label":"-Sementes de linho -Para sementeira","pdfPage":6,"lastPdfPage":6},
{"id":"annexI-2022-047","code":"1206.00.10","label":"Sementes de girassol -Para sementeira","pdfPage":6,"lastPdfPage":6},
{"id":"annexI-2022-048","code":"1207.21.00","label":"- Sementes de algodão -Para sementeira","pdfPage":6,"lastPdfPage":6},
{"id":"annexI-2022-049","code":"1207.30.00","label":"- Sementes de rícino","pdfPage":6,"lastPdfPage":6},
{"id":"annexI-2022-050","code":"1207.40.10","label":"- Sementes de gergelim -Para sementeira","pdfPage":6,"lastPdfPage":6},
{"id":"annexI-2022-051","code":"1207.50.00","label":"-Sementes de mostarda","pdfPage":6,"lastPdfPage":6},
{"id":"annexI-2022-052","code":"1207.60.00","label":"-Sementes de cártamo","pdfPage":6,"lastPdfPage":6},
{"id":"annexI-2022-053","code":"1207.70.00","label":"-Sementes de Melão","pdfPage":6,"lastPdfPage":6},
{"id":"annexI-2022-054","code":"1207.91.00","label":"-Sementes de dormideira ou papoula","pdfPage":6,"lastPdfPage":6},
{"id":"annexI-2022-055","code":"1207.99.10","label":"-Outras sementes para sementeira","pdfPage":6,"lastPdfPage":6},
{"id":"annexI-2022-056","code":"1209.10.00","label":"-Sementes de beterraba sacarina","pdfPage":6,"lastPdfPage":6},
{"id":"annexI-2022-057","code":"1209.21.00","label":"- Semente de alfafa (Luzerna)","pdfPage":6,"lastPdfPage":6},
{"id":"annexI-2022-058","code":"1209.22.00","label":"-Sementes de trevo (Tlurifolium spp)","pdfPage":7,"lastPdfPage":7},
{"id":"annexI-2022-059","code":"1209.23.00","label":"- Sementes de festuca","pdfPage":7,"lastPdfPage":7},
{"id":"annexI-2022-060","code":"1209.24.00","label":"- Sementes de pasto dos prados de Kentucky (Poa pratensis L.)","pdfPage":7,"lastPdfPage":7},
{"id":"annexI-2022-061","code":"1209.25.00","label":"-Sementes de azevém (Lolium multiflorum Lam, Lolium perente L.)","pdfPage":7,"lastPdfPage":7},
{"id":"annexI-2022-062","code":"1209.29.00","label":"-Outras (sementes)","pdfPage":7,"lastPdfPage":7},
{"id":"annexI-2022-063","code":"1209.30.00","label":"-Sementes de plantas herbáceas cultivadas especialmente pelas suas flores","pdfPage":7,"lastPdfPage":7},
{"id":"annexI-2022-064","code":"1209.91.00","label":"- Outras -Sementes de produtos hortícolas","pdfPage":7,"lastPdfPage":7},
{"id":"annexI-2022-065","code":"1209.99.00","label":"- Outras sementes","pdfPage":7,"lastPdfPage":7},
{"id":"annexI-2022-066","code":"1901.10.10","label":"- Preparações alimentícias à base de lacticínios, para lactentes e crianças de tenra idade, acondicionadas para venda à retalho","pdfPage":7,"lastPdfPage":7},
{"id":"annexI-2022-067","code":"1901.10.30","label":"- Preparações alimentares, terapêuticas à base de lacticínios ou de cereais","pdfPage":7,"lastPdfPage":7},
{"id":"annexI-2022-068","code":"2106.90.20","label":"- Produto composto para fortificação de alimentos destinados ao consumo humano, contendo alguns dos seguintes micronutrientes, vitaminas, iodo, zinco, ácido fólico e ferro (por exemplo, produtos denominados PREMIX)","pdfPage":7,"lastPdfPage":7},
{"id":"annexI-2022-069","code":"2309.90.10","label":"- Preparações, aditivos do tipo utilizado na aquacultura do camarão, na avicultura, na pecuária e pré-mistura de alta concentração.","pdfPage":7,"lastPdfPage":7},
{"id":"annexI-2022-070","code":"3101.00.00","label":"Adubos (fertilizantes) de origem animal ou vegetal, mesmo misturados entre si ou tratados quimicamente; adubos (fertilizantes) resultantes da mistura ou do tratamento químico de produtos de origem animal ou vegetal","pdfPage":7,"lastPdfPage":7},
{"id":"annexI-2022-071","code":"3102.10.00","label":"Adubos (fertilizantes) minerais ou químicos, azotados (nitrogenados): - Ureia, mesmo em solução aquosa","pdfPage":7,"lastPdfPage":7},
{"id":"annexI-2022-072","code":"3102.21.00","label":"Adubos (fertilizantes) minerais ou químicos, azotados (nitrogenados): - Sulfato de amónio","pdfPage":7,"lastPdfPage":7},
{"id":"annexI-2022-073","code":"3102.29.00","label":"-Outros adubos (fertilizantes) minerais ou químicos, azotados (nitrogenados)","pdfPage":7,"lastPdfPage":7},
{"id":"annexI-2022-074","code":"3102.30.00","label":"Adubos (fertilizantes) minerais ou químicos, azotados (nitrogenados): -Nitrato de amónio, mesmo em solução aquosa","pdfPage":7,"lastPdfPage":7},
{"id":"annexI-2022-075","code":"3102.40.00","label":"Adubos (fertilizantes) minerais ou químicos, azotados (nitrogenados): - Misturas de nitrato de amónio com carbonato de cálcio ou com outras matérias inorgânicas desprovidas de poder fertilizante","pdfPage":7,"lastPdfPage":7},
{"id":"annexI-2022-076","code":"3102.50.00","label":"Adubos (fertilizantes) minerais ou químicos, azotados (nitrogenados): - Nitrato de sódio","pdfPage":7,"lastPdfPage":7},
{"id":"annexI-2022-077","code":"3102.60.00","label":"Adubos (fertilizantes) minerais ou químicos, azotados (nitrogenados): - Sais duplos e misturas de nitrato de cálcio e nitrato de amónio","pdfPage":7,"lastPdfPage":7},
{"id":"annexI-2022-078","code":"3102.80.00","label":"Adubos (fertilizantes) minerais ou químicos, azotados (nitrogenados): - Misturas de ureia com nitrato de amónio em soluções aquosas ou amoniacais","pdfPage":7,"lastPdfPage":7},
{"id":"annexI-2022-079","code":"3102.90.00","label":"Adubos (fertilizantes) minerais ou químicos, azotados (nitrogenados): - Outros incluídas as misturas não mencionadas nas sub posições precedentes","pdfPage":7,"lastPdfPage":7},
{"id":"annexI-2022-080","code":"3103.11.00","label":"Adubos (fertilizantes) minerais ou químicos, fosfatados: - Superfosfatos Que contenham, em peso, 35% ou mais de pentóxido de difósforo","pdfPage":7,"lastPdfPage":7},
{"id":"annexI-2022-081","code":"3103.19.00","label":"Outros superfosfatos","pdfPage":7,"lastPdfPage":7},
{"id":"annexI-2022-082","code":"3103.90.00","label":"- Outros adubos (fertilizantes) minerais ou químicos, fosfatados","pdfPage":7,"lastPdfPage":7},
{"id":"annexI-2022-083","code":"3104.20.00","label":"Adubos (fertilizantes) minerais ou químicos, potássicos: - Cloreto de potássio","pdfPage":7,"lastPdfPage":7},
{"id":"annexI-2022-084","code":"3104.30.00","label":"Adubos (fertilizantes) minerais ou químicos, potássicos: - Sulfato de potássio","pdfPage":8,"lastPdfPage":8},
{"id":"annexI-2022-085","code":"3104.90.00","label":"- Outros adubos (fertilizantes) minerais ou químicos, potássicos","pdfPage":8,"lastPdfPage":8},
{"id":"annexI-2022-086","code":"3105.10.00","label":"Adubos (fertilizantes) minerais ou químicos, contendo dois ou três dos seguintes elementos fertilizantes: azoto (nitrogénio), fósforo e potássio; outros adubos (fertilizantes). -Produtos do presente capítulo apresentados em tabletes ou forma semelhantes, ou ainda em embalagens com peso bruto não superior a 10 kg","pdfPage":8,"lastPdfPage":8},
{"id":"annexI-2022-087","code":"3105.20.00","label":"- Adubos (fertilizantes) minerais ou químicos, contendo os três elementos fertilizantes: azoto (nitrogénio), fósforo e potássio","pdfPage":8,"lastPdfPage":8},
{"id":"annexI-2022-088","code":"3105.30.00","label":"- Adubos (fertilizantes) minerais ou químicos, Hidrogéno-ortofosfato de diamónio (fosfato diamónico ou dimoniacal)","pdfPage":8,"lastPdfPage":8},
{"id":"annexI-2022-089","code":"3105.40.00","label":"-Diidrogeno-ortofosfato de amónio (fosfato monoamónico ou monoamonical), mesmo misturado com hidrogeno-ortofosfato de diamónio (fosfato diamónico ou diamonical)","pdfPage":8,"lastPdfPage":8},
{"id":"annexI-2022-090","code":"3105.51.00","label":"- Outros adubos (fertilizantes) minerais ou químicos, contendo os dois elementos fertilizantes, azoto (nitrogénio) e fósforo: -que contenham nitratos e fosfatos","pdfPage":8,"lastPdfPage":8},
{"id":"annexI-2022-091","code":"3105.59.00","label":"- Outros adubos (fertilizantes) minerais ou químicos, contendo os dois elementos fertilizantes: azoto (nitrogénio) e fósforo","pdfPage":8,"lastPdfPage":8},
{"id":"annexI-2022-092","code":"3105.60.00","label":"- Adubos (fertilizantes) minerais ou químicos, contendo os dois elementos fertilizantes: fósforos e potássio","pdfPage":8,"lastPdfPage":8},
{"id":"annexI-2022-093","code":"3105.90.00","label":"- Outros adubos (fertilizantes) minerais ou químicos, contendo dois ou três dos seguintes elementos fertilizantes: azoto (nitrogénio), fósforo e potássio; outros adubos (fertilizantes), produtos do presente capítulo apresentados em tabletes ou forma semelhantes, ou ainda em embalagens com peso bruto não superior a 10 kg","pdfPage":8,"lastPdfPage":8},
{"id":"annexI-2022-094","code":"3808.91.00","label":"- Insecticidas","pdfPage":8,"lastPdfPage":8,"relatedTreatments":["listed_insecticides"],"relatedRequired":true},
{"id":"annexI-2022-095","code":"3808.92.00","label":"- Fungicidas","pdfPage":8,"lastPdfPage":8},
{"id":"annexI-2022-096","code":"3808.93.00","label":"- Herbicida, inibidores de germinação e reguladores de crescimento para plantas","pdfPage":8,"lastPdfPage":8},
{"id":"annexI-2022-097","code":"3808.94.00","label":"- Desinfectantes","pdfPage":8,"lastPdfPage":8},
{"id":"annexI-2022-098","code":"3808.99.00","label":"- Outros produtos semelhantes","pdfPage":8,"lastPdfPage":8},
{"id":"annexI-2022-099","code":"3821.00.00","label":"Meios de cultura preparados para o desenvolvimento de microrganismos e a manutenção de microrganismos (incluindo os vírus e os organismos similares) ou de células vegetais, humanas ou animais","pdfPage":8,"lastPdfPage":8},
{"id":"annexI-2022-100","code":"3822.00.00","label":"Reagentes de diagnóstico ou de laboratório em qualquer suporte e reagentes de diagnóstico ou de laboratório preparados, mesmos apresentados num suporte, excepto os das posições 30.02 ou 30.06; materiais de referência certificados","pdfPage":8,"lastPdfPage":8},
{"id":"annexI-2022-101","code":"3926.90.10","label":"- Flutuadores para a pesca","pdfPage":8,"lastPdfPage":8},
{"id":"annexI-2022-102","code":"3926.90.40","label":"- Brincos para identificação de animais","pdfPage":8,"lastPdfPage":8},
{"id":"annexI-2022-103","code":"5608.11.00","label":"-Redes confeccionadas para a pesca","pdfPage":8,"lastPdfPage":8},
{"id":"annexI-2022-104","code":"6304.20.00","label":"- Mosquiteiros para cama","pdfPage":8,"lastPdfPage":8},
{"id":"annexI-2022-105","code":"6305.10.00","label":"- Sacos de juta ou de outras fibras têxteis liberianas","pdfPage":8,"lastPdfPage":8},
{"id":"annexI-2022-106","code":"8201.10.00","label":"- Pás","pdfPage":8,"lastPdfPage":8},
{"id":"annexI-2022-107","code":"8201.30.00","label":"- Alviões, picaretas, enxadas, sachos, ancinhos e raspadeiras","pdfPage":8,"lastPdfPage":8},
{"id":"annexI-2022-108","code":"8201.40.00","label":"- Machados, padrões e ferramentas semelhantes de gume","pdfPage":8,"lastPdfPage":8},
{"id":"annexI-2022-109","code":"8201.50.00","label":"- Tesouras de podar (incluindo as tesouras para aves domésticas), manipuladas com uma das mãos","pdfPage":8,"lastPdfPage":9},
{"id":"annexI-2022-110","code":"8201.60.00","label":"- Tesouras para sebes, tesouras de podar e ferramentas semelhantes, manipuladas com as duas mãos","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-111","code":"8201.90.00","label":"- Outras ferramentas manuais para agricultura, horticultura e silvicultura","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-112","code":"8202.10.00","label":"- Serras manuais","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-113","code":"8202.20.00","label":"- Folhas para serras de fita","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-114","code":"8208.40.00","label":"- Correntes cortantes de serras","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-115","code":"8413.20.00","label":"Bombas para líquidos, mesmo com dispositivo medidor, elevadores de líquidos. -Bombas manuais, excepto das subposições 8413.11 e 8413.19","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-116","code":"8413.81.00","label":"- Outras Bombas","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-117","code":"8413.82.00","label":"- Elevadores de líquidos","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-118","code":"8419.31.00","label":"- Secadores - Para produtos agrícolas","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-119","code":"8421.11.00","label":"Centrifugadores, incluindo os secadores centrífugos; -Desnatadeiras","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-120","code":"8424.81.00","label":"- Aparelhos mecânicos (mesmo manuais) para projectar, dispersar ou pulverizar líquidos ou pós, para agricultura ou horticultura","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-121","code":"8424.90.00","label":"- Partes","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-122","code":"8425.31.00","label":"- Guinchos e cabrestantes de motor eléctrico","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-123","code":"8425.39.00","label":"- Outros guinchos e cabrestantes","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-124","code":"8432.10.00","label":"- Arados e charruas","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-125","code":"8432.21.00","label":"-Grades de discos","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-126","code":"8432.29.00","label":"- Outros: Grades, escarificadores, cultivadores, extirpadores, enxadas e sachadores","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-127","code":"8432.31.00","label":"- Semeadores, plantadores e transplantadores","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-128","code":"8432.41.00","label":"- Espalhadores de estrume e distribuidores de adubos (fertilizantes)","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-129","code":"8432.80.00","label":"- Outras máquinas e aparelhos de uso agrícola, hortícola ou florestal, para preparação ou trabalho do solo ou para cultura","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-130","code":"8432.90.00","label":"- Partes de máquinas e aparelhos de uso agrícola, hortícola ou florestal, para preparação ou trabalho do solo ou para cultura","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-131","code":"8433.11.00","label":"-Cortadores de relva motorizados, cujo dispositivo de corte gira num plano horizontal, para colheita ou debulha de produtos agrícolas","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-132","code":"8433.19.00","label":"-Outros cortadores de relva motorizados, para colheita ou debulha de produtos agrícolas","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-133","code":"8433.20.00","label":"- Ceifeiras, incluindo as barras de corte para montagem em tractores","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-134","code":"8433.30.00","label":"- Outras máquinas e aparelhos para colher e dispor o feno","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-135","code":"8433.40.00","label":"- Enfardadeiras de palha ou de forragem, incluindo as enfardadeiras- apanhadeiras","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-136","code":"8433.51.00","label":"-Ceifeiras-debulhadoras","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-137","code":"8433.52.00","label":"- Outras máquinas e aparelhos para debulha","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-138","code":"8433.53.00","label":"- Máquinas para colheita de raízes ou tubérculos","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-139","code":"8433.59.00","label":"- Outras máquinas e aparelhos para colheita e para debulha","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-140","code":"8433.60.00","label":"- Máquinas para limpar ou seleccionar ovos, frutas ou outros produtos agrícolas","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-141","code":"8433.90.00","label":"- Partes de máquina e aparelhos para colheita ou debulha de produtos agrícolas, incluindo as enfardadeiras de palha ou forragem; cortadores de relva e ceifeiras; máquinas para limpar e seleccionar ovos, frutas ou outros produtos agrícolas, excepto os da posição nº. 84.37.","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-142","code":"8434.10.00","label":"- Máquinas de ordenhar","pdfPage":9,"lastPdfPage":9},
{"id":"annexI-2022-143","code":"8434.20.00","label":"- Máquinas e aparelhos, para a indústria de lacticínios","pdfPage":10,"lastPdfPage":10},
{"id":"annexI-2022-144","code":"8434.90.00","label":"- Partes de máquinas e aparelhos de ordenhar e para a indústria de lacticínios","pdfPage":10,"lastPdfPage":10},
{"id":"annexI-2022-145","code":"8435.10.00","label":"Prensas, esmagadores, máquinas e aparelhos semelhantes, para fabricação de vinho, sidra, sumos de frutas ou bebidas semelhantes - Máquinas e aparelhos","pdfPage":10,"lastPdfPage":10},
{"id":"annexI-2022-146","code":"8435.90.00","label":"- Partes de prensas, esmagadores, máquinas e aparelhos semelhantes, para fabricação de vinho, sidra, sumos de frutas ou bebidas semelhantes","pdfPage":10,"lastPdfPage":10},
{"id":"annexI-2022-147","code":"8436.10.00","label":"- Máquinas e aparelhos, para preparação de alimentos e rações para animais","pdfPage":10,"lastPdfPage":10},
{"id":"annexI-2022-148","code":"8436.21.00","label":"- Chocadeiras e criadeiras para avicultura","pdfPage":10,"lastPdfPage":10},
{"id":"annexI-2022-149","code":"8436.29.00","label":"- Outras máquinas e aparelhos, para agricultura, horticultura, silvicultura, avicultura ou apicultura, incluindo os germinadores equipados com dispositivos mecânicos ou térmicos","pdfPage":10,"lastPdfPage":10},
{"id":"annexI-2022-150","code":"8436.80.00","label":"- Outras máquinas e aparelhos","pdfPage":10,"lastPdfPage":10},
{"id":"annexI-2022-151","code":"8436.91.00","label":"-Partes de máquinas e aparelhos, para agricultura, horticultura, silvicultura, avicultura ou apicultura, incluindo os germinadores equipados com dispositivos mecânicos ou térmicos e as chocadeiras e criadeiras para silvicultura","pdfPage":10,"lastPdfPage":10},
{"id":"annexI-2022-152","code":"8436.99.00","label":"- Partes de outras máquinas e aparelhos","pdfPage":10,"lastPdfPage":10},
{"id":"annexI-2022-153","code":"8437.10.00","label":"- Máquinas para limpeza, selecção ou peneiração de grão ou de produtos agrícolas secos","pdfPage":10,"lastPdfPage":10},
{"id":"annexI-2022-154","code":"8437.80.00","label":"- Outras máquinas e aparelhos para a indústria de moagem ou tratamento de cereais ou de produtos hortícolas secos, excepto dos tipos utilizados em fazendas","pdfPage":10,"lastPdfPage":10},
{"id":"annexI-2022-155","code":"8437.90.00","label":"- Partes de máquinas para limpeza, selecção ou peneiração de grãos ou de produtos hortícolas secos; máquinas e aparelhos para a indústria de moagem ou tratamento de cereais ou de produtos hortícolas secos, excepto dos tipos utilizados em fazendas","pdfPage":10,"lastPdfPage":10},
{"id":"annexI-2022-156","code":"8438.30.00","label":"Máquinas e aparelhos não especificados nem compreendidos noutras posições do presente capítulo… - Máquinas e aparelhos para indústria do açúcar","pdfPage":10,"lastPdfPage":10},
{"id":"annexI-2022-157","code":"8438.60.00","label":"- Máquinas e aparelhos para preparação de frutas ou de produtos hortícolas","pdfPage":10,"lastPdfPage":10},
{"id":"annexI-2022-158","code":"8501.61.00","label":"-Geradores de corrente alternada (alternadores) -De potência não superior a 75 KVA","pdfPage":10,"lastPdfPage":10},
{"id":"annexI-2022-159","code":"8502.11.00","label":"- Grupos electrogéneos de motor de pistão de ignição por compressão (motores diesel ou semi-diesel) -De potência não superior a 75 KVA","pdfPage":10,"lastPdfPage":10},
{"id":"annexI-2022-160","code":"8502.20.00","label":"- Grupos electrogéneos de motor de pistão de ignição por faísca (motor de explosão)","pdfPage":10,"lastPdfPage":10},
{"id":"annexI-2022-161","code":"8701.10.00","label":"- Tractores de um eixo","pdfPage":10,"lastPdfPage":10},
{"id":"annexI-2022-162","code":"8701.20.00","label":"- Tractores rodoviários para semi-reboques","pdfPage":10,"lastPdfPage":10},
{"id":"annexI-2022-163","code":"8701.30.00","label":"- Tractores de lagartas","pdfPage":10,"lastPdfPage":10},
{"id":"annexI-2022-164","code":"8701.91.00","label":"Nã superior a 18KW","pdfPage":10,"lastPdfPage":10,"context":"Outros tractores"},
{"id":"annexI-2022-165","code":"8701.92.00","label":"Superior a 18KW, mas não superior a 37KW","pdfPage":10,"lastPdfPage":10,"context":"Outros tractores"},
{"id":"annexI-2022-166","code":"8701.93.00","label":"Superior a 37KW, mas não superior a 75KW","pdfPage":10,"lastPdfPage":10,"context":"Outros tractores"},
{"id":"annexI-2022-167","code":"8701.94.00","label":"Superior a 75KW, mas não superior a 130KW","pdfPage":10,"lastPdfPage":10,"context":"Outros tractores"},
{"id":"annexI-2022-168","code":"8701.95.00","label":"Superior a 130KW","pdfPage":11,"lastPdfPage":11,"context":"Outros tractores"},
{"id":"annexI-2022-169","code":"8704.21.90","label":"- Outros veículos automóveis para transporte de mercadorias, com motor de pistão de ignição por compressão (diesel ou semi-diesel), de peso bruto não superior a 5 toneladas","pdfPage":11,"lastPdfPage":11},
{"id":"annexI-2022-170","code":"8716.80.00","label":"- Outros veículos não auto propulsionados (carroças de tracção animal)","pdfPage":11,"lastPdfPage":11},
{"id":"annexI-2022-171","code":"9507.20.00","label":"- Anzóis, mesmo montados em terminais (sedelas)","pdfPage":11,"lastPdfPage":11},
{"id":"annexI-2022-172","code":"9507.90.00","label":"- Outros artigos para a pesca à linha","pdfPage":11,"lastPdfPage":11}
];
export function annexIEntry(id:unknown):AnnexIEntry|undefined {return typeof id==='string'?annexIEntries.find(entry=>entry.id===id):undefined;}
export function annexIReference(entry:AnnexIEntry):string {return `AnexoI/2022: ${entry.id}; código ${entry.code}; ${entry.context?entry.context+' — ':''}${entry.label}; PDF${entry.pdfPage}${entry.lastPdfPage===entry.pdfPage?'':`–${entry.lastPdfPage}`}; ${annexIVersion}`;}
+29
View File
@@ -0,0 +1,29 @@
import type { OperationTreatment } from './iva-operations.ts';
const source = 'CIVA republicado pela Lei13/2016, BR156/10.º suplemento, art.13(1)(o/p/q/r/t), PDF12/p.1426(270); art.19(1)(b)(i), PDF15/p.1426(273). Lei22/2022 art.1, PDF3/p.2252(27), mantém19(1)(b)(i); Lei10/2025 art.1, PDF12–13/p.2180(12)–(13), não altera13 e mantém19(1)(b)(i). Âmbito técnico2026/MZN; classificação de vendas, sem dedução automática de compras ou declaraçãoAT.';
const scope = 'Operação abrangida pelo CIVA em Moçambique, com territorialidade identificada; não inferida apenas da residência do cliente ou do sector';
const make = (id:string,label:string,letter:string,conditions:string[]):OperationTreatment => ({id,label,field:'05',rate:0,article:`CIVA arts.13(1)(${letter}),19(1)(b)(i)`,source,logicVersion:'export-direct-operations/1',conditions:[scope,...conditions]});
export const directExportTreatments:OperationTreatment[] = [
make('export_railway_cfm','Operação ferroviária dos CFM com companhia estrangeira','o',[
'Transmissão de bens ou prestação de serviços efectuada pelos Caminhos de Ferro de Moçambique a companhia ferroviária estrangeira identificada; não basta ser qualquer operador ferroviário',
'Operação no quadro da exploração de ferrovias ou dos seus equipamentos, com ligação identificada; não isenção de qualquer venda a companhia estrangeira',
]),
make('export_international_passengers','Transporte de passageiros proveniente do ou com destino ao estrangeiro','p',[
'Serviço identificado como transporte de passageiros; não transporte de mercadorias nem serviço autónomo de alojamento ou agência',
'Percurso proveniente do estrangeiro ou com destino ao estrangeiro, com origem e destino identificados no documento ou pressuposto; nacionalidade do passageiro não comprova o percurso',
]),
make('export_work_on_movables','Trabalhos em bens móveis para reexpedição ao estrangeiro','q',[
'Prestação de serviços que consiste em trabalhos sobre bens móveis identificados, adquiridos ou importados para esses trabalhos em território nacional',
'Os bens trabalhados são expedidos ou transportados de seguida para o estrangeiro, com correspondência entre entrada, trabalhos e saída identificada',
'Expedição efectuada pelo prestador, pelo destinatário não estabelecido no território nacional ou por terceiro em nome e por conta de qualquer deles; interveniente e relação identificados',
]),
make('export_gold_bom','Ouro não trabalhado transmitido ao Banco de Moçambique','r',[
'Bem identificado como ouro em barra ou noutra forma não trabalhada; não jóia nem artigo de ouro trabalhado',
'Adquirente identificado como Banco de Moçambique; não qualquer banco ou comprador estrangeiro',
]),
make('export_packaging','Taras e embalagens para mercadorias a exportar','t',[
'Transmissão de taras ou embalagens identificadas que servem de invólucro de mercadorias; não serviço autónomo de transporte ou armazenagem',
'Mercadorias a exportar identificadas e afectação das taras/embalagens a essas mercadorias documentada ou expressamente pressuposta; não inferida só da actividade exportadora do comprador',
]),
];
+20
View File
@@ -0,0 +1,20 @@
import type { OperationTreatment } from './iva-operations.ts';
const source='CIVA republicado Lei13/2016,13(1)(m/n/s),PDF12/p.1426(270);remissões12(1)(c),PDF11/p.1426(269),14,PDF13/p.1426(271),19(1)(b)(i),PDF15/p.1426(273). Lei22/2022art.1 eLei10/2025art.1 mantêm13 e19(1)(b)(i);Lei10/2025PDF12–13/p.2180(12)–(13). Âmbito2026/MZN;classificação do serviço,sem certificar regime/documentos ou deduzir compras automaticamente.';
const scope='O próprio serviço está localizado e abrangido pelo CIVA em Moçambique, com territorialidade identificada; cliente estrangeiro ou operação subjacente no estrangeiro não determinam, por si, a localização deste serviço';
const make=(id:string,label:string,letter:string,conditions:string[]):OperationTreatment=>({id,label,field:'05',rate:0,article:`CIVA arts.13(1)(${letter}),19(1)(b)(i)`,source,logicVersion:'export-linked-services/1',conditions:[scope,...conditions]});
export const exportServiceTreatments:OperationTreatment[]=[
make('export_customs_related_services','Serviços ligados a bens nos regimes indicados no artigo13(1)(m)','m',[
'Serviço directamente relacionado com trânsito, exportação ou importação dos bens identificados, com ligação concreta descrita',
'Os bens estão isentos por admissão temporária, draubaque ou trânsito nos termos de12(1)(c), ou entraram em depósitos de regime aduaneiro ou livre de outras áreas do14; regime e documento/pressuposto identificados, não apenas localização do projecto numa zona',
'O serviço não está entre os serviços referidos no artigo9; a exclusão foi analisada para esta operação concreta, não presumida por o cliente exportar',
]),
make('export_dispatch_services','Serviços ligados à expedição de bens para o estrangeiro','n',[
'Serviço identificado e relacionado com expedição de bens destinados ao estrangeiro; bens, destino e ligação concreta do serviço identificados no documento ou pressuposto',
'O serviço não está entre os serviços referidos no artigo9; não basta uma venda a cliente estrangeiro nem um serviço genérico ao exportador',
]),
make('export_disclosed_intermediation','Intermediação em nome e por conta de outrem — artigo13(1)(s)','s',[
'Prestação de intermediação em nome e por conta de outrem, com mandante e mandato/pressuposto identificados; não actuação em nome próprio',
'O intermediário intervém numa operação descrita no artigo13 ou realizada fora do território nacional, com operação e fundamento/localização identificados; a referência a outra linha não comprova automaticamente esses factos',
]),
];
export function isExportService(id:string):boolean{return exportServiceTreatments.some(item=>item.id===id);}
+8
View File
@@ -0,0 +1,8 @@
export type FundraisingContext={entityReference:string;annualEvents:string;eventNumber:string;activity:string};
export const fundraisingActivities=[['health_public','Saúde pública — 9(1)(a)'],['social_assistance','Assistência social — 9(2)(a)'],['security_public','Segurança pública — 9(2)(b)'],['social_care','Equipamentos sociais — 9(2)(c)'],['activity_facilities','Prática artística/desportiva/recreativa — 9(2)(d)'],['cultural_visits','Visitas culturais — 9(2)(e)'],['statutory_membership','Serviços colectivos por quota — 9(2)(g)'],['education_public','Ensino público — 9(3)(a)'],['training_public','Formação pública — 9(3)(b)']];
export function fundraisingError(value:FundraisingContext|undefined,nonprofit:boolean):string|undefined {
if(!value||typeof value.entityReference!=='string'||!value.entityReference.trim())return 'Identifique a entidade organizadora; o limite anual não é por oportunidade.';
if(typeof value.annualEvents!=='string'||typeof value.eventNumber!=='string'||!/^[1-8]$/.test(value.annualEvents)||!/^[1-8]$/.test(value.eventNumber)||Number(value.eventNumber)>Number(value.annualEvents))return 'Indique o total anual da entidade (incluindo esta manifestação) e o número desta manifestação: de1a8, sem exceder o total. Desconhecido não significa zero.';
const activities=fundraisingActivities.map(([id])=>id).filter(id=>nonprofit?!id.endsWith('_public'):id!=='statutory_membership');
if(!activities.includes(value.activity))return 'Escolha uma actividade habitual isenta abrangida por9(2)(h) e compatível com a entidade; não basta ser uma angariação de fundos.';
}
@@ -0,0 +1,30 @@
import type { OperationTreatment } from './iva-operations.ts';
const source = 'CIVA republicado Lei13/2016, BR156/10.º suplemento, art.13(1)(c/d/f/g/i), PDF12/p.1426(270); art.19(1)(b)(i), PDF15/p.1426(273). Lei22/2022 art.1, PDF3/p.2252(27), e Lei10/2025 art.1, PDF12–13/p.2180(12)–(13), mantêm19(1)(b)(i), sem alterar13. Âmbito2026/MZN; sem dedução automática de compras ou submissãoAT.';
const scope = 'Operação abrangida pelo CIVA em Moçambique, com territorialidade identificada; não basta o sector, a localização do investimento ou a residência estrangeira do cliente';
const ship = 'Embarcação identificada, afecta a navegação marítima em alto mar com transporte remunerado de passageiros ou actividade comercial, industrial ou de pesca; ou a salvamento, assistência marítima ou pesca costeira, nos termos de13(1)(c/d). A natureza e utilização constam do documento ou pressuposto; não qualquer barco de recreio';
const aircraft = 'Avião identificado e utilizado por companhia de navegação aérea que se dedica principalmente ao tráfego internacional; companhia e utilização identificadas, não bastando um voo internacional isolado';
const make=(id:string,label:string,letter:string,conditions:string[]):OperationTreatment=>({id,label,field:'05',rate:0,article:`CIVA arts.13(1)(${letter}),19(1)(b)(i)`,source,logicVersion:'international-assets/1',conditions:[scope,...conditions]});
export const internationalAssetTreatments:OperationTreatment[] = [
make('international_ship_operations','Operações sobre embarcação elegível e objectos da sua exploração','f',[
ship,
'Operação identificada: transmissão, transformação, reparação, manutenção, frete ou aluguer da embarcação; ou transmissão, aluguer, reparação ou conservação de objectos incorporados ou utilizados na sua exploração, incluindo equipamento de pesca',
'A operação e o objecto estão ligados à embarcação elegível identificada; não qualquer venda ou serviço a uma empresa marítima',
]),
make('international_aircraft_operations','Operações sobre avião de companhia principalmente internacional','g',[
aircraft,
'Operação identificada: transmissão, transformação, reparação, manutenção, frete ou aluguer do avião; ou transmissão, reparação ou manutenção de objectos nele incorporados ou utilizados na sua exploração. Não estender o aluguer do avião ao aluguer autónomo de objectos não enumerado nesta alínea',
'A operação e o objecto estão ligados ao avião elegível identificado; não qualquer fornecimento à companhia aérea',
]),
make('international_ship_direct_services','Serviços para necessidades directas de embarcação elegível ou sua carga','i',[
ship,
'Prestação de serviços identificada e efectuada para necessidades directas da embarcação elegível ou da respectiva carga, com ligação concreta descrita; não qualquer serviço ao armador',
'Serviço distinto dos já mencionados em13(1)(f/g); confirme a natureza específica, sem duplicar o enquadramento das operações sobre embarcação ou avião',
]),
make('international_aircraft_direct_services','Serviços para necessidades directas de avião elegível ou sua carga','i',[
aircraft,
'Prestação de serviços identificada e efectuada para necessidades directas do avião elegível ou da respectiva carga, com ligação concreta descrita; não qualquer serviço à companhia aérea',
'Serviço distinto dos já mencionados em13(1)(f/g); confirme a natureza específica, sem duplicar o enquadramento das operações sobre embarcação ou avião',
]),
];
+1 -1
View File
@@ -45,7 +45,7 @@ export function modeloAComponentRows(snapshot: Record<string, unknown>): Array<[
return [
['Correspondência Modelo A',modeloAReference.status],
['Campos01/02', 'Base líquida e IVA mensal da versão publicada. Os restantes campos não foram presumidos iguais a zero.'],
['Apuramento do período — campos14–18', 'Indeterminado: faltam componentes e enquadramentos do Modelo A. IVA das vendas não é imposto final a pagar.'],
['Apuramento nesta execução de vendas — campos14–18', 'Indeterminado nesta execução isolada de01/02. Consulte o bloco separado de aquisições e apuramento parcial, quando preenchido. IVA das vendas não é imposto final a pagar.'],
['Origem dos dados','Projecção do negócio; não são operações efectivas nem declaração fiscal.'],
['Exemplar de referência',`${modeloAReference.file}; SHA256 ${modeloAReference.sha256}. ${modeloAReference.edition}`],
];
+37
View File
@@ -0,0 +1,37 @@
import type { OperationTreatment } from './iva-operations.ts';
export type SupplyCategory = '' | 'provisions' | 'beverages' | 'fuel' | 'cargo_products';
export const supplyCategories: Array<[Exclude<SupplyCategory, ''>, string]> = [
['provisions', 'Provisões de bordo, excepto bebidas — consumo exclusivo da tripulação e passageiros'],
['beverages', 'Bebidas como provisões de bordo — consumo exclusivo da tripulação e passageiros'],
['fuel', 'Combustíveis, carburantes, lubrificantes ou outros produtos para propulsão ou aparelhos de uso técnico a bordo'],
['cargo_products', 'Produtos acessórios para preparação, tratamento ou conservação das mercadorias transportadas a bordo'],
];
const source = 'CIVA republicado Lei 13/2016, BR156/10.º suplemento, art.13(1)(c/d/e/h),13(2–3), PDF12/p.1426(270);19(1)(b)(i), PDF15/p.1426(273). Lei22/2022 art.1, PDF3/p.2252(27), e Lei10/2025 art.1, PDF12–13/p.2180(12)–(13), não alteram13 e mantêm19(1)(b)(i). Âmbito2026/MZN; bebidas em c/d/h não têm isenção directa automática:13(2) prevê dedução ou restituição, sem aplicar20(1)(d) para esse efeito.';
const make = (id:string,label:string,letter:string,conditions:string[]):OperationTreatment => ({id,label,field:'05',rate:0,article:`CIVA arts.13(1)(${letter}),13(2–3),19(1)(b)(i)`,source,logicVersion:'onboard-supplies/1',conditions:[
'Transmissão de bens localizada em Moçambique, com territorialidade identificada; não importação nem serviço autónomo',
'Bens efectivamente postos a bordo do meio identificado; natureza e destino correspondem à categoria escolhida do artigo13(3), sustentados pelo documento ou pressuposto expresso da projecção',
...conditions,
]});
export const onboardSupplyTreatments:OperationTreatment[] = [
make('onboard_seagoing_ship','Abastecimento de embarcação de navegação marítima em alto mar','c',[
'Embarcação identificada que efectua navegação marítima em alto mar e assegura transporte remunerado de passageiros ou actividade comercial, industrial ou de pesca; utilização identificada, não qualquer barco de recreio',
]),
make('onboard_rescue_coastal_ship','Abastecimento de embarcação de salvamento, assistência marítima ou pesca costeira','d',[
'Embarcação identificada de salvamento, assistência marítima ou pesca costeira; actividade identificada, não presumida pelo nome do operador',
]),
make('onboard_departing_warship','Abastecimento de embarcação de guerra com destino estrangeiro','e',[
'Embarcação de guerra identificada que deixa o país com destino a porto ou ancoradouro situado no estrangeiro; saída e destino identificados, não simples utilização militar',
]),
make('onboard_international_aircraft','Abastecimento de avião de companhia principalmente internacional','h',[
'Avião identificado utilizado por companhia de navegação aérea que se dedica principalmente ao tráfego internacional nos termos de13(1)(g); companhia e utilização identificadas, não apenas um voo internacional isolado',
]),
];
export function isOnboardSupply(id:string):boolean { return onboardSupplyTreatments.some(rule=>rule.id===id); }
export function onboardSupplyIssue(id:string,category:unknown):string|null {
if(!isOnboardSupply(id))return null;
if(!supplyCategories.some(([value])=>value===category))return 'Identifique a natureza do abastecimento segundo o artigo13(3). Informação em falta não significa ausência de bebidas ou provisões; nenhum montante fiscal foi presumido.';
if(id==='onboard_rescue_coastal_ship'&&(category==='provisions'||category==='beverages'))return 'As provisões de bordo estão excluídas da isenção de13(1)(d), incluindo bebidas, nas embarcações de salvamento, assistência marítima e pesca costeira. Esta isenção não se aplica; o tratamento fiscal alternativo deve ser identificado, sem presumir taxa ou zero.';
if(category==='beverages'&&id!=='onboard_departing_warship')return 'Bebidas em13(1)(c/h):13(2) prevê isenção por dedução ou restituição, não isenção directa deste fornecimento; para esse efeito não se aplica20(1)(d). O montante liquidado e o procedimento aplicável não são determinados neste incremento: sem crédito, restituição, taxa ou zero automáticos. Conserve o preço e identifique o tratamento antes do apuramento.';
return null;
}
+269
View File
@@ -0,0 +1,269 @@
import { acquisitionScope, readAcquisitionStore } from './iva-acquisitions.ts';
import { fundraisingError, type FundraisingContext } from './iva-fundraising.ts';
import { pharmaAnnexEntry, pharmaAnnexReference, pharmaAnnexSource, pharmaAnnexVersion } from './iva-pharma-annex.ts';
import { annexIEntry, annexIReference, annexISource, annexIVersion } from './iva-annex-i.ts';
import { productionOptionCheck, productionOptionVersion, type ProductionTaxOption } from './iva-production-option.ts';
import { temporaryBenefits, temporaryBenefit, temporaryBenefitNotice, temporaryBenefitVersion } from './iva-temporary-benefits.ts';
import { directExportTreatments } from './iva-export-operations.ts';
import { internationalAssetTreatments } from './iva-international-assets.ts';
import { exportServiceTreatments, isExportService } from './iva-export-services.ts';
import { onboardSupplyTreatments, onboardSupplyIssue, supplyCategories, isOnboardSupply, type SupplyCategory } from './iva-onboard-supplies.ts';
import { monthlySalesFromDraft, readMonthlyIvaSettings } from './monthly-iva.ts';
import { addFractions, decimalFraction, fraction, fractionLabel, fractionPresentation, type FiscalFraction } from './fiscal-rational.ts';
export const operationVersion = 'iva-operations-l1/2';
// The accepted v2 full-catalogue key predates scoped keys. Freeze its members
// so later, independent catalogue additions cannot invalidate those snapshots.
const legacyV2TreatmentIds = ['general','private_health','private_education','private_training','personal_lessons','export_goods','housing_rent','public_health','public_education','public_training','foreign_operation','other'];
const source2022 = 'Lei22/2022, BR250, 2.º suplemento, PDF1–4 (2252(25)–(28)); arts.1/2/6; efeitos01/01/2023';
const source2016 = 'CIVA republicado Lei13/2016, BR156, 10.º suplemento, PDF9–15 (1426(267)–(273))';
const source2025 = 'Lei10/2025, BR248, suplemento1, PDF14–15 (2180(14)–(15)); arts.1/2/3/5; efeitos01/01/2026';
const healthGoodsSource = 'CIVA republicado Lei13/2016, PDF9, p.1426(267), art.9(1)(b–f); PDF15, p.1426(273), art.19(1); Lei22/2022 art.1, PDF1, p.2252(25), mantém9(1)(b–f). Âmbito técnico2026/MZN';
const internalOperation = 'Operação interna localizada em Moçambique; não é importação nem operação localizada no estrangeiro';
export const modeloA06Correspondence = 'Exemplar recebido:06 é base de operações isentas, com remissão18(1)(b); nessa lei18(1)(b) trata IVA de importações, enquanto19(1)(b) enumera operações com direito. O mesmo exemplar já tem05 para vendas isentas com direito. O formulário antigo da AT usa03 para a remissão e06 para existências. Não há correspondência unívoca nem instrução aplicável que separe05/06 no acervo conferido: não atribuir06 automaticamente a operações no estrangeiro ou importar instruções antigas por número.';
export type OperationTreatment = {id:string; label:string; field:string|null; rate:number|null; article:string; source:string; conditions:string[];logicVersion?:string};
const nonprofitConditions = [
'Não distribui nem disponibiliza lucros; os corpos gerentes não têm interesse directo ou indirecto nos resultados, por si ou interposta pessoa',
'Escrituração abrange todas as actividades e está à disposição dos serviços fiscais para comprovação',
'Preços homologados pela autoridade competente ou, quando não susceptíveis de homologação, inferiores aos de operações análogas das empresas comerciais sujeitas a imposto',
'Não entra em concorrência directa com sujeitos passivos do imposto',
];
function socialTreatment(id:string,label:string,article:string,conditions:string[],nonprofit:boolean):OperationTreatment {
return {id,label,field:'07',rate:0,article:`CIVA arts.9(2)(${article}),10(${nonprofit?'2':'1'}),19(1)`,source:'CIVA republicado Lei13/2016, PDF9, p.1426(267), art.9(2)(a/c/d); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF2, p.2252(26),10(1–2). Âmbito técnico2026/MZN',conditions:[internalOperation,...(nonprofit?nonprofitConditions:['Entidade pública: órgão ou instituição da Administração Pública que desempenha funções administrativas do Estado, nos termos da legislação aplicável']),...conditions]};
}
const culturalSource = 'CIVA republicado Lei13/2016, PDF9, p.1426(267), art.9(2)(e–g); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF1, p.2252(25), mantém9(2)(e–g), e PDF2, p.2252(26),10(1–2). Âmbito técnico2026/MZN';
const culturalTreatments:OperationTreatment[] = ([false,true] as const).flatMap(nonprofit=>{
const suffix=nonprofit?'nonprofit':'public',entity=nonprofit?'organismo sem finalidade lucrativa':'entidade pública';
const make=(id:string,label:string,article:string,conditions:string[]):OperationTreatment=>({...socialTreatment(id,label,article,conditions,nonprofit),source:culturalSource});
return [
make(`cultural_visits_${suffix}`,`Visitas culturais/naturais — ${entity}`,'e',['Visita, guiada ou não, a museu, galeria de arte, monumento, parque, perímetro florestal, jardim botânico/zoológico ou similar pertencente ao Estado, a entidade pública ou a entidade sem finalidade lucrativa','Serviço efectuado pela própria entidade, por intermédio dos seus próprios agentes; organismo sem finalidade lucrativa devidamente autorizado quando aplicável','Se houver bens, são transmissões estreitamente conexas com essa visita; não venda autónoma nem serviço de intermediário']),
make(`religious_personnel_${suffix}`,`Cedência de pessoal religiosa/filosófica — ${entity}`,'f',['Cedência de pessoal efectuada por instituição religiosa ou filosófica identificada','Destino identificado: actividade isenta nos termos do CIVA, com fundamento específico, ou assistência espiritual; não qualquer fornecimento de mão-de-obra']),
];
});
culturalTreatments.push({id:'statutory_membership',label:'Serviços colectivos aos associados por quota estatutária',field:'07',rate:0,article:'CIVA arts.9(2)(g),10(2),19(1)',source:culturalSource,conditions:[internalOperation,...nonprofitConditions,'Serviços efectuados no interesse colectivo dos próprios associados por organismo sem finalidade lucrativa','Objectivos de natureza política, sindical, religiosa, patriótica, filantrópica, recreativa, desportiva, cultural, cívica ou de representação de interesses económicos, identificados','A única contraprestação é uma quota fixada nos respectivos estatutos; não pagamentos adicionais por serviços individuais']});
const listedGoodsTreatments:OperationTreatment[] = [
['maize','Milho','Bem transmitido identificado como milho'],
['maize_flour','Farinha de milho','Bem transmitido identificado como farinha de milho'],
['rice','Arroz','Bem transmitido identificado como arroz'],
['bread','Pão','Bem transmitido identificado como pão'],
['iodised_salt','Sal iodado','Sal identificado como iodado; não qualquer sal'],
['infant_powdered_milk','Leite em pó para lactente até um ano','Leite em pó identificado como destinado a lactente até um ano; não qualquer leite ou alimento infantil'],
['wheat','Trigo','Bem transmitido identificado como trigo'],
['wheat_flour','Farinha de trigo','Bem transmitido identificado como farinha de trigo'],
['fresh_chilled_tomato','Tomate fresco ou refrigerado','Tomate identificado como fresco ou refrigerado; não alargar automaticamente a conserva ou preparação'],
['potato','Batata','Bem transmitido identificado como batata'],
['onion','Cebola','Bem transmitido identificado como cebola'],
['frozen_horse_mackerel','Carapau congelado','Peixe identificado como carapau congelado; não qualquer espécie ou estado de conservação'],
['lighting_kerosene','Petróleo de iluminação','Produto identificado como petróleo de iluminação; não qualquer combustível'],
['domestic_lpg','Gás doméstico — GPL','Produto identificado como gás doméstico GPL; não qualquer gás industrial'],
['jet_fuel','Jet fuel','Produto identificado como jet fuel; não qualquer combustível de transporte'],
['eligible_bicycles','Bicicletas comuns e de ferro até 4 velocidades','Produto identificado na enumeração legal «bicicletas comuns e de ferro até 4 velocidades», com características sustentadas; não qualquer veículo'],
['condoms','Preservativos','Bem transmitido identificado como preservativo'],
['insecticides','Insecticidas','Bem transmitido identificado como insecticida; não qualquer produto químico'],
].map(([id,label,condition])=>({id:`listed_${id}`,label:`Lista legal — ${label}`,field:'05',rate:0,article:'CIVA arts.9(10),19(1)(b)(v), redacção Lei22/2022',source:'Lei22/2022 art.1, PDF2, p.2252(26),9(10); CIVA republicado Lei13/2016, PDF15, p.1426(273),19(1)(b)(v). Âmbito técnico2026/MZN',conditions:[internalOperation,'Transmissão do próprio bem enumerado, identificado; não um serviço autónomo nem extensão por sector, marca ou destino',condition]}));
export const operationTreatments:OperationTreatment[] = [
...exportServiceTreatments,
...onboardSupplyTreatments,
...internationalAssetTreatments,
...directExportTreatments,
...temporaryBenefits.map(item=>({id:item.id,label:`Benefício terminado31/12/2025 — ${item.label}`,field:null,rate:null,article:`CIVA art.${item.article}`,source:`${item.source} CIVA republicado Lei13/2016,9(14),PDF10/p.1426(268),apenas para9(13)(b/f). Âmbito:cessação nas operações internas2026/MZN;sem cálculo histórico.`,conditions:[],logicVersion:temporaryBenefitVersion})),
{id:'annexI_goods',label:'Equipamento, sementes e outros bens do Anexo I — artigo9(12)(h)',field:'07',rate:0,logicVersion:annexIVersion,article:'CIVA arts.9(12)(h),19(1); Lei22/2022 art.3(1)',source:`CIVA republicado Lei13/2016, PDF10, p.1426(268),9(12)(h), e PDF15, p.1426(273),19(1); rectificação BR89/2017, PDF1, p.569; ${annexISource}. Âmbito técnico2026/MZN`,conditions:[internalOperation,'O bem transmitido corresponde ao código e à designação da posição escolhida no Anexo I; não basta a actividade agrícola, a marca ou uma indicação genérica de equipamento','Qualificadores expressos na posição conferidos e fundamentados, incluindo natureza, destino, certificação, peso, capacidade ou potência quando exigidos nessa linha; não acrescentar condições a linhas que não as exigem']},
{id:'pharma_manufacturing_inputs',label:'Bens do Anexo III para fabrico de medicamentos — estabelecimento integrado no SNS',field:'07',rate:0,logicVersion:pharmaAnnexVersion,article:'CIVA arts.9(1)(g),19(1); Lei22/2022 art.3(1)',source:`CIVA republicado Lei13/2016, PDF9, p.1426(267),9(1)(g), e PDF15, p.1426(273),19(1); rectificação BR89/2017, PDF1, p.569; ${pharmaAnnexSource}. Âmbito técnico2026/MZN`,conditions:[internalOperation,'Transmissão efectuada pelo próprio estabelecimento público ou privado identificado, integrado no Serviço Nacional de Saúde; não basta que o adquirente ou destino seja um hospital','Bens a utilizar como matérias-primas, produtos intermédios ou componentes para o fabrico de medicamentos, com utilização/fundamento identificados; não mera venda de produto acabado ou utilização genérica','Bem corresponde cumulativamente ao código e à designação da linha seleccionada no Anexo III; confirmar as especificações aplicáveis sem corrigir ou completar a pauta por suposição']},
...([false,true] as const).map(nonprofit=>({...socialTreatment(`fundraising_${nonprofit?'nonprofit':'public'}`,`Angariação ocasional de fundos — ${nonprofit?'organismo sem finalidade lucrativa':'entidade pública'}`,'h',['Actividade habitual isenta identificada:9(1)(a),9(2)(a/b/c/d/e/g) ou9(3)(a/b), com condições dessa isenção e fundamento identificados','Manifestação ocasional destinada à angariação de fundos em proveito exclusivo da entidade organizadora','Total anual declarado inclui esta manifestação e as realizadas fora deste dossier; não superior a oito no ano'],nonprofit),logicVersion:'fundraising/1',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(2)(h); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF1, p.2252(25),9(1–3), e PDF2, p.2252(26),10(1–2). Âmbito técnico2026/MZN'})),
...(['agriculture','forestry','livestock','fishing'] as const).flatMap((kind,index)=>{
const label=['Produção agrícola, avicultura e apicultura','Produção silvícola','Produção pecuária','Pesca'][index],letter=['a','b','c','d'][index];
const conditions=[internalOperation,'Operação no âmbito da própria produção identificada, utilizando os próprios recursos; não mera revenda/comércio','Se houver transformação, é acessória, pelo próprio produtor sobre produtos da sua produção, por meios geralmente utilizados nas respectivas explorações'];
const source=`CIVA republicado Lei13/2016, PDF10, p.1426(268),9(7)(${letter}); PDF11, p.1426(269),11; PDF15, p.1426(273),19(1)(b)(v); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(7). Âmbito técnico2026/MZN`;
const exempt:OperationTreatment={id:`production_${kind}`,label:`${label} — isenção`,field:kind==='agriculture'?'05':'07',rate:0,article:`CIVA arts.9(7)(${letter}),19(1)${kind==='agriculture'?'(b)(v)':',11'}`,source,conditions:[...conditions,...(kind==='agriculture'?[]:['Regime de isenção aplicável nesta operação: não existe opção de tributação eficaz do art.11 no período; fundamento/histórico identificado'])]};
return kind==='agriculture'?[exempt]:[exempt,{id:`production_${kind}_opted`,logicVersion:productionOptionVersion,label:`${label} — opção de tributação eficaz`,field:'01',rate:16,article:`CIVA arts.9(7)(${letter}),11,15(1),17(1),19(1)(a),34`,source:`${source}; ${source2022}; ${source2025}`,conditions:[...conditions,'Opção declarada à Direcção da Área Fiscal competente, na declaração adequada; se opção no início, consta da declaração de início da actividade','Operação no regime normal por opção eficaz; contraprestação completa, sem base especial do art.15(2) ou outro tratamento próprio']}];
}),
...listedGoodsTreatments,
{...socialTreatment('public_security','Bens e serviços ligados à segurança por entidade pública','b',['Transmissão de bens ou prestação ligada à segurança identificada e efectuada pela própria entidade pública; não presumir segurança social nem extensão a prestador privado contratado'],false),source:'CIVA republicado Lei13/2016, PDF9, p.1426(267),9(2)(b); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF1, p.2252(25), mantém9(2)(b); PDF2, p.2252(26),10(1). Âmbito técnico2026/MZN'},
{id:'official_military_supplies',label:'Fornecimentos oficiais militares/paramilitares elegíveis',field:'07',rate:0,article:'CIVA arts.9(11),19(1)',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(11); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(11). Âmbito técnico2026/MZN',conditions:[internalOperation,'Bem/serviço no fornecimento de material de guerra e de aquartelamento ou fardamento militar/paramilitar, identificado','Destino de utilização oficial das Forças de Defesa e Segurança Nacional; actividade efectuada exclusivamente para aqueles serviços','Estabelecimento reconhecido pelo Ministério competente, com reconhecimento identificado; não basta o cliente ser militar']},
{id:'sisa_subject_operation',label:'Operação sujeita a SISA, ainda que dela isenta',field:'07',rate:0,article:'CIVA arts.9(12)(d),19(1)',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(12)(d); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(12)(d). Âmbito técnico2026/MZN',conditions:[internalOperation,'Operação e fundamento de sujeição a SISA identificados, ainda que exista isenção desse imposto; não qualquer operação imobiliária','Esta linha corresponde à operação sujeita a SISA, não a locação, mediação ou outro serviço autónomo; este bloco não calcula SISA']},
{id:'exempt_activity_asset_sale',label:'Alienação de bem exclusivamente afecto a actividade isenta',field:'07',rate:0,article:'CIVA arts.9(12)(e),19(1)',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(12)(e); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(12)(e). Âmbito técnico2026/MZN',conditions:[internalOperation,'Transmissão de bem identificado, com histórico de afectação disponível','Bem afecto exclusivamente a sector de actividade isento; não mera afectação parcial ou existência de alguma operação isenta na entidade']},
{id:'no_deduction_right_asset_sale',label:'Alienação de bem sem direito anterior à dedução',field:'07',rate:0,article:'CIVA arts.9(12)(e),19(1)',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(12)(e); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(12)(e). Âmbito técnico2026/MZN',conditions:[internalOperation,'Transmissão de bem identificado, com histórico fiscal da aquisição/afectação disponível','Bem não foi objecto de direito à dedução, com fundamento identificado; não basta não ter exercido um direito existente nem desconhecer o histórico']},
{id:'excluded_deduction_asset_sale',label:'Alienação de bem adquirido com exclusão do artigo 20',field:'07',rate:0,article:'CIVA arts.9(12)(e),20,19(1)',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(12)(e); PDF15, p.1426(273),19(1)/20(1); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(12)(e), e PDF3, p.2252(27),20(2–3). Âmbito técnico2026/MZN',conditions:[internalOperation,'Transmissão de bem identificado e aquisição correspondente documentada ou expressamente pressuposta','Aquisição feita com exclusão do direito à dedução nos termos do artigo20: identificar número/alínea aplicável e conferir as excepções do20(3); não assumir exclusão apenas por falta de documento ou dedução não exercida']},
{id:'special_tax_games',label:'Jogos e operações sujeitos ao imposto especial sobre o jogo',field:'07',rate:0,article:'CIVA arts.9(8),19(1)',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(8); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(8). Âmbito técnico2026/MZN',conditions:[internalOperation,'Exploração/prática de jogo de fortuna ou azar ou diversão social nos termos da legislação própria, respectiva comissão, título de aposta ou bilhete de acesso/ingresso à área de jogo, identificado','Esta operação está sujeita ao imposto especial sobre o jogo, com fundamento identificado; não qualquer entretenimento ou serviço acessório autónomo; o imposto especial não é calculado neste bloco']},
{id:'stamped_values',label:'Transmissão de valores selados',field:'07',rate:0,article:'CIVA arts.9(12)(a),19(1), redacção Lei22/2022',source:'Lei22/2022 art.1, PDF2, p.2252(26),9(12)(a); CIVA republicado Lei13/2016, PDF15, p.1426(273),19(1). Âmbito técnico2026/MZN',conditions:[internalOperation,'Bem transmitido identificado como valor selado, com natureza sustentada pelo documento ou pressuposto da operação','A linha corresponde à transmissão do valor selado; comissão de venda ou serviço autónomo não é abrangido automaticamente por esta opção']},
{id:'public_passenger_transport',label:'Serviço de transporte público de passageiros',field:'07',rate:0,article:'CIVA arts.9(12)(j),19(1)',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(12)(j); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(12)(j). Âmbito técnico2026/MZN',conditions:[internalOperation,'Serviço identificado como transporte público de passageiros, com natureza da prestação sustentada; não inferido apenas da natureza pública do prestador','A linha corresponde ao transporte de passageiros; não transporte de mercadorias, aluguer autónomo de veículo ou outro serviço acessório sem enquadramento próprio']},
{id:'industrial_feed',label:'Rações de produção industrial para animais elegíveis',field:'05',rate:0,article:'CIVA arts.9(12)(f),19(1)(b)(v)',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(12)(f); PDF15, p.1426(273),19(1)(b)(v); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(12)(f). Âmbito técnico2026/MZN',conditions:[internalOperation,'Transmissão de bens resultantes de actividade industrial de produção de rações, identificada; não presumir isenção de qualquer alimento para animais','Rações destinadas à alimentação de animais de reprodução e abate para consumo humano, com destino identificado']},
{id:'industrial_feed_inputs',label:'Insumos enumerados para produção industrial de rações',field:'07',rate:0,article:'CIVA arts.9(12)(g),19(1)',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(12)(g); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(12)(g). Âmbito técnico2026/MZN',conditions:[internalOperation,'Bem identificado na enumeração: grão de soja, bagaço de soja, soja integral, farinha de peixe, farinha de carne, pós de osso, monofosfato de cálcio, lisina ou metionina','Utilização como matéria-prima na actividade industrial de produção de rações destinadas à alimentação de animais de reprodução e abate para consumo humano, identificada']},
{id:'veterinary_goods',label:'Agulhas, seringas e medicamentos de uso veterinário',field:'07',rate:0,article:'CIVA arts.9(12)(i),19(1)',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(12)(i); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(12)(i). Âmbito técnico2026/MZN',conditions:[internalOperation,'Transmissão de agulha, seringa ou medicamento identificado; não qualquer equipamento ou serviço veterinário','Uso veterinário identificado para os bens da operação']},
{id:'agricultural_services',label:'Serviços agrícolas de canais, regadio, drenagem e pulverização',field:'07',rate:0,article:'CIVA arts.9(15),19(1)',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(15); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(15). Âmbito técnico2026/MZN',conditions:[internalOperation,'Serviço identificado: abertura de canais, ceifa, drenagem, fornecimento de água para irrigação, limpeza de valas de drenagem ou pulverização da terra','Serviço efectuado no âmbito da actividade agrícola, com afectação identificada; não qualquer obra, limpeza ou fornecimento de água']},
{id:'author_rights',label:'Direitos de autor pelo autor, herdeiro ou legatário',field:'07',rate:0,article:'CIVA arts.9(9)(a),19(1)',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(9)(a); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(9). Âmbito técnico2026/MZN',conditions:[internalOperation,'Operação identificada como transmissão de direitos de autor ou autorização para utilização de obra intelectual','Efectuada pelo próprio autor, seu herdeiro ou legatário, com qualidade identificada; não presumir isenção de revenda/intermediação por terceiro']},
{id:'cultural_publications',label:'Jornais, revistas e livros de natureza elegível',field:'07',rate:0,article:'CIVA arts.9(9)(b),19(1)',source:'CIVA republicado Lei13/2016, PDF10, p.1426(268),9(9)(b); PDF15, p.1426(273),19(1); Lei22/2022 art.1, PDF2, p.2252(26), mantém9(9). Âmbito técnico2026/MZN',conditions:[internalOperation,'Transmissão de jornal, revista ou livro identificado; não qualquer material escolar, serviço editorial ou fornecimento autónomo','Natureza cultural, educativa, técnica ou recreativa da publicação identificada e sustentada; não inferida apenas do nome do fornecedor ou sector']},
...culturalTreatments,
{id:'general',label:'Operação interna geral',field:'01',rate:16,article:'CIVA arts.1,6,15(1),17(1–2); art.34 (Lei10/2025)',source:`${source2016}; ${source2022}; ${source2025}`,conditions:['Operação localizada e tributável em Moçambique, no regime normal','Contraprestação completa; sem base especial do art.15(2), isenção ou taxa reduzida']},
{id:'private_health',label:'Serviços médicos e sanitários privados',field:'03',rate:5,article:'CIVA arts.15(10),17-A(a)',source:source2022,conditions:['Serviço médico/sanitário ou operação estreitamente conexa','Prestador hospitalar privado, clínica, dispensário ou similar']},
{id:'private_education',label:'Ensino privado reconhecido',field:'03',rate:5,article:'CIVA arts.15(10),17-A(b)',source:source2022,conditions:['Ensino ou bens/serviços conexos prestados pelo estabelecimento','Estabelecimento privado integrado no Sistema Nacional de Ensino e reconhecido pelo Ministério competente']},
{id:'private_training',label:'Formação profissional privada',field:'03',rate:5,article:'CIVA arts.15(10),17-A(c)',source:source2022,conditions:['Formação profissional ou fornecimentos conexos pelo prestador, não venda autónoma de materiais','Prestador privado']},
{id:'personal_lessons',label:'Lições ministradas a título pessoal',field:'03',rate:5,article:'CIVA arts.15(10),17-A(d)',source:source2022,conditions:['Lições ministradas a título pessoal','Matérias de ensino escolar ou superior']},
{id:'export_goods',label:'Exportação de bens pelo vendedor',field:'05',rate:0,article:'CIVA arts.13(1)(a),19(1)(b)(i)',source:source2016,conditions:['Bens expedidos/transportados para o estrangeiro pelo vendedor ou terceiro por sua conta','Saída documentada, ou pressuposto expresso da projecção; não mera venda a cliente estrangeiro']},
{id:'housing_rent',label:'Locação de imóvel para habitação',field:'07',rate:0,article:'CIVA art.9(5), redacção Lei22/2022; art.19(1)',source:source2022,conditions:['Locação de imóvel para fins de habitação','Não é hospedagem nem locação comercial/industrial ou serviço autónomo']},
{id:'public_health',label:'Serviços médicos e sanitários públicos',field:'07',rate:0,article:'CIVA arts.9(1)(a),10(1),19(1)',source:source2022,conditions:['Serviço médico/sanitário ou operação estreitamente conexa','Estabelecimento hospitalar público, dispensário ou similar; natureza pública confirmada']},
{id:'public_education',label:'Ensino público reconhecido',field:'07',rate:0,article:'CIVA arts.9(3)(a),10(1),19(1)',source:source2022,conditions:['Ensino ou fornecimentos conexos pelo estabelecimento','Estabelecimento público integrado no Sistema Nacional de Ensino e reconhecido pelo Ministério competente']},
{id:'public_training',label:'Formação profissional pública',field:'07',rate:0,article:'CIVA arts.9(3)(b),10(1),19(1)',source:source2022,conditions:['Formação profissional ou fornecimentos conexos pelo prestador','Prestador público']},
{id:'financial_stamp',label:'Operação bancária/financeira sujeita a Selo',field:'07',rate:0,article:'CIVA art.9(4), redacção Lei22/2022; art.19(1)',source:`${source2022}; ${source2016}`,conditions:['A operação é bancária ou financeira, não um serviço acessório autónomo','Sujeição a Imposto do Selo identificada para esta operação; não depende de calcular o Selo neste bloco']},
{id:'insurance_stamp',label:'Seguro/resseguro ou mediação conexa sujeitos a Selo',field:'07',rate:0,article:'CIVA art.9(6), redacção Lei22/2022; art.19(1)',source:`${source2022}; ${source2016}`,conditions:['Seguro/resseguro ou serviço conexo efectuado por corrector ou outro mediador de seguros','Sujeição a Imposto do Selo identificada para esta operação']},
{id:'public_waste',label:'Remoção de lixo pública ou por entidade contratada',field:'07',rate:0,article:'CIVA art.9(12)(b), redacção Lei22/2022; art.19(1)',source:`${source2022}; ${source2016}`,conditions:['Prestação de serviço de remoção de lixo, não qualquer serviço de limpeza','Efectuada por entidade pública ou por entidade por ela contratada, com relação identificada']},
{id:'public_funeral',label:'Serviços funerários/cremação públicos e bens acessórios',field:'07',rate:0,article:'CIVA art.9(12)(c), redacção Lei22/2022; art.19(1)',source:`${source2022}; ${source2016}`,conditions:['Serviço funerário/cremação ou transmissão de bem acessório a esse serviço','Efectuado por entidade pública; não aplicar automaticamente a funerária privada']},
{id:'health_assistive',label:'Bens de compensação da deficiência, próteses e braille',field:'07',rate:0,article:'CIVA arts.9(1)(b),19(1)',source:healthGoodsSource,conditions:[internalOperation,'Bem identificado na enumeração: cadeira de rodas/veículo semelhante, aparelho/máquina/impressora braille, prótese ou material de compensação','Destino documentado conforme a categoria: deficiência, substituição de membro/órgão, fractura, pessoa invisual ou correcção da audição; não qualquer equipamento médico']},
{id:'human_materials',label:'Órgãos, sangue e leite humanos',field:'07',rate:0,article:'CIVA arts.9(1)(c),19(1)',source:healthGoodsSource,conditions:[internalOperation,'Transmissão de órgãos, sangue ou leite de origem humana, identificada; não produto de origem animal nem serviço autónomo']},
{id:'patient_transport',label:'Transporte de doentes/feridos por organismo autorizado',field:'07',rate:0,article:'CIVA arts.9(1)(d),19(1)',source:healthGoodsSource,conditions:[internalOperation,'Transporte de doente ou ferido em ambulância ou outro veículo apropriado','Organismo que efectua o transporte devidamente autorizado, com autorização identificada; não basta o destino hospitalar']},
{id:'mosquito_nets',label:'Transmissão de redes mosquiteiras',field:'07',rate:0,article:'CIVA arts.9(1)(e),19(1)',source:healthGoodsSource,conditions:[internalOperation,'Bem identificado como rede mosquiteira; não extensão automática a outros produtos de prevenção']},
{id:'medicines',label:'Medicamentos e artigos terapêuticos/profilácticos elegíveis',field:'07',rate:0,article:'CIVA arts.9(1)(f),19(1)',source:healthGoodsSource,conditions:[internalOperation,'Medicamento/especialidade farmacêutica ou produto farmacêutico exclusivamente terapêutico/profiláctico; ou pasta, gaze, algodão hidrófilo, tira/penso adesivo ou análogo','Finalidade elegível identificada: terapêutica/profiláctica nos produtos farmacêuticos; higiénica, medicinal ou cirúrgica nos artigos enumerados, mesmo impregnados/revestidos; não qualquer produto vendido por farmácia']},
...([false,true] as const).flatMap(nonprofit=>{
const suffix=nonprofit?'nonprofit':'public',entity=nonprofit?'organismo sem finalidade lucrativa':'entidade pública';
return [
socialTreatment(`social_assistance_${suffix}`,`Assistência social — ${entity}`,'a',['Prestação de assistência social ou transmissão de bens estreitamente conexa, identificada','Fins e objecto da entidade reconhecidos pelas autoridades competentes, com fundamento identificado'],nonprofit),
socialTreatment(`social_care_${suffix}`,`Equipamentos sociais/creches/lares — ${entity}`,'c',['Prestação ou bem estreitamente conexo no exercício da actividade habitual de creche, jardim de infância, centro de tempos livres, lar ou outro equipamento social enumerado no art.9(2)(c)','Equipamento pertencente à entidade e fins/objecto reconhecidos pelas autoridades competentes; não qualquer alojamento ou empresa de cuidados'],nonprofit),
socialTreatment(`activity_facilities_${suffix}`,`Prática artística/desportiva/recreativa — ${entity}`,'d',['Serviço efectuado pela própria entidade que explora o estabelecimento ou instalação','Instalação destinada à prática artística, desportiva, recreativa ou de educação física e serviço prestado a quem a pratica; não isenção automática de bilhetes para espectadores'],nonprofit),
];
}),
{id:'foreign_operation',label:'Operação no estrangeiro — analisar territorialidade',field:null,rate:null,article:'CIVA art.6: localização por natureza da operação; art.19(1)(b)(ii) não determina sozinho a caixa06 do formulário',source:source2016,conditions:[]},
{id:'other',label:'Outra operação / enquadramento ainda desconhecido',field:null,rate:null,article:'Fundamento específico ainda necessário; não presumir taxa ou isenção',source:'Sem fonte operacional determinada para esta linha',conditions:[]},
];
export type SalesOperation = {id:string;period:string;description:string;establishment:string;amount:string;basis:''|'net'|'included';treatment:string;confirmed:number[];evidence:string;sourceAmount:string|null;sourcePeriod:string;sourceCurrency:string;source:string;taxOption?:ProductionTaxOption;fundraiser?:FundraisingContext;pharmaAnnexItem?:string;annexIItem?:string;annexIOnly?:boolean;temporaryBenefitOrigin?:string;relatedExport?:{id:string;description:string;treatment:string};supplyCategory?:SupplyCategory; splitSource?:{id:string;amount:string|null;period:string;currency:string;basis:string}};
export type SalesBook = {currency:string;rows:SalesOperation[];periods:Array<{period:string;complete:boolean}>; result?:SalesResult; history?:SalesResult[]};
export type SalesLineResult = {id:string;field:string|null;net:string|null;vat:string|null;gross:string|null;rate:number|null;status:'calculated'|'exempt'|'indeterminate';reason:string;article:string;source:string;exact?:{net:FiscalFraction;vat:FiscalFraction;gross:FiscalFraction}};
export type SalesResult = {version:string;revision:number;calculatedAt:string;opportunity:string;location:string;currency:string;key:string;inputs:SalesOperation[];rows:SalesLineResult[];periods:Array<{period:string;fields:Record<string,string|null>;exactFields?:Record<string,FiscalFraction|null>;reasons:string[]}>;rounding:string};
type Store = ReturnType<typeof readAcquisitionStore> & {salesOperations?:Record<string,SalesBook>};
export function newSalesOperation(id:string,period:string,currency:string):SalesOperation {return {id,period,description:'',establishment:'',amount:'',basis:'',treatment:'other',confirmed:[],evidence:'',sourceAmount:null,sourcePeriod:period,sourceCurrency:currency,source:'Introdução directa; projecção, não declaração submetida'};}
export function continueAnnexIOperation(row:SalesOperation,targetId:string):SalesOperation {
const entry=annexIEntry(row.annexIItem),target=operationTreatments.find(t=>t.id===targetId);
if(row.treatment!=='annexI_goods'||!entry?.relatedTreatments?.includes(targetId)||!target)throw new Error('O tratamento de continuidade não corresponde à posição escolhida; dados conservados.');
return {...row,treatment:targetId,confirmed:[],annexIOnly:false,source:`${row.source}; continuidade expressamente escolhida a partir de ${annexIReference(entry)} para ${target.label}; rever condições do tratamento, sem alterar montante/moeda/contexto`};
}
export function continueTemporaryOperation(row:SalesOperation,targetId:string):SalesOperation {
const benefit=temporaryBenefit(row.treatment),target=operationTreatments.find(item=>item.id===targetId);
if(!benefit||!target||temporaryBenefit(targetId))throw new Error('Escolha um enquadramento actual distinto do benefício terminado; dados conservados.');
return {...row,treatment:targetId,confirmed:[],temporaryBenefitOrigin:benefit.id,source:`${row.source}; continuidade expressamente escolhida de ${benefit.id}/${benefit.branch}, CIVA art.${benefit.article}, termo31/12/2025, ${temporaryBenefitVersion}, para ${target.label}; ${benefit.source}; montante/moeda/período conservados; rever condições, sem cálculo automático`};
}
export function referenceExportOperation(row:SalesOperation,related:SalesOperation):SalesOperation {
if(!isExportService(row.treatment)||row.id===related.id)throw new Error('Escolha outra operação para referenciar neste serviço; dados conservados.');
return {...row,relatedExport:{id:related.id,description:related.description,treatment:related.treatment},confirmed:[]};
}
export function salesBook(draft:Record<string,unknown>):SalesBook {
const store=readAcquisitionStore(draft.modelo_a_snapshot) as Store;
if(store.salesOperations!==undefined&&(!store.salesOperations||typeof store.salesOperations!=='object'||Array.isArray(store.salesOperations)))throw new Error('Formato das operações IVA não recuperável; dados preservados, sem substituição.');
const book=store.salesOperations?.[acquisitionScope(draft)];
if(!book)return {currency:String(draft.currency??''),rows:[],periods:[]};
if(typeof book.currency!=='string'||!Array.isArray(book.rows)||!Array.isArray(book.periods)||book.rows.some(r=>!r||Object.keys(newSalesOperation('','','')).some(k=>k==='confirmed'?!Array.isArray(r.confirmed)||r.confirmed.some(c=>!Number.isInteger(c)):k==='sourceAmount'?!(r.sourceAmount===null||typeof r.sourceAmount==='string'):typeof r[k as keyof SalesOperation]!=='string'))||book.periods.some(p=>!p||!/^\d{4}-\d{2}$/.test(p.period)||typeof p.complete!=='boolean'))throw new Error('Operações IVA não recuperáveis; os dados originais foram preservados.');
return book;
}
export function saveSalesBook(draft:Record<string,unknown>,book:SalesBook):string {const store=readAcquisitionStore(draft.modelo_a_snapshot) as Store;return JSON.stringify({...store,salesOperations:{...store.salesOperations,[acquisitionScope(draft)]:book}});}
export function reuseSales(draft:Record<string,unknown>,book:SalesBook):SalesBook {
const source=monthlySalesFromDraft(draft),settings=readMonthlyIvaSettings(String(draft.monthly_iva_settings??''));
if(!/^2026-(0[1-9]|1[0-2])$/.test(settings.start)||Number(settings.start.slice(5))+source.amounts.length>13)throw new Error('Defina o período da projecção dentro de2026 antes de reutilizar vendas.');
if(book.currency!==draft.currency)throw new Error('Moeda da origem divergente; valores preservados, sem conversão.');
const rows=[...book.rows],periods=[...book.periods];
source.amounts.forEach((value,index)=>{const period=`2026-${String(Number(settings.start.slice(5))+index).padStart(2,'0')}`;
if(!periods.some(p=>p.period===period))periods.push({period,complete:false});
if(!rows.some(r=>r.sourcePeriod===period&&r.source!=='Introdução directa; projecção, não declaração submetida'))rows.push({...newSalesOperation(`sales-${period}`,period,book.currency),description:`Vendas do plano — ${period}`,amount:value??'',basis:settings.basis==='unknown'?'':settings.basis,sourceAmount:value,source:source.source,evidence:source.source});
});return {...book,rows,periods};
}
export function splitSales(book:SalesBook,id:string,newId:string):SalesBook {
const row=book.rows.find(r=>r.id===id);if(!row)throw new Error('Operação de origem não encontrada.');
if(row.sourceAmount===null&&!row.splitSource)throw new Error('Reparta uma venda reutilizada com valor de origem determinado; para entradas directas acrescente as operações em falta.');
const source=row.splitSource??{id:row.id,amount:row.sourceAmount??row.amount,period:row.period,currency:row.sourceCurrency,basis:row.basis};
if(!source.basis||source.amount===null||amount(source.amount)===null)throw new Error('Determine o valor e a representação do preço antes de repartir a origem.');
const first={...row,amount:'',sourceAmount:null,splitSource:source,source:`Repartição explícita de ${source.id}: ${source.amount} ${source.currency}; ${row.source}`};
return {...book,rows:[...book.rows.map(r=>r.id===id?first:r),{...first,id:newId,description:'Parcela adicional da mesma venda',treatment:'other',confirmed:[],evidence:''}],periods:book.periods.map(p=>p.period===row.period?{...p,complete:false}:p)};
}
export function recordSales(draft:Record<string,unknown>,book:SalesBook):SalesBook {return {...book,history:book.result?[...(book.history??[]),book.result]:book.history,result:calculateSales(draft,book)};}
function amount(raw:unknown):bigint|null {if(typeof raw!=='string'||!/^\d{1,15}(\.\d{1,6})?$/.test(raw.trim()))return null;const [n,d='']=raw.trim().split('.');return BigInt(n)*1000000n+BigInt(d.padEnd(6,'0'));}
function money(n:bigint):string {return `${n/1000000n}.${(n%1000000n).toString().padStart(6,'0').replace(/0+$/,'').padEnd(2,'0')}`;}
function sum(values:Array<string|null>):string|null {const parsed=values.map(amount);return parsed.some(v=>v===null)?null:money((parsed as bigint[]).reduce((a,b)=>a+b,0n));}
export function evaluateSalesOperation(row:SalesOperation,currency:string):SalesLineResult {
const rule=operationTreatments.find(r=>r.id===row.treatment),n=amount(row.amount);
const annex=row.treatment==='pharma_manufacturing_inputs'?pharmaAnnexEntry(row.pharmaAnnexItem):undefined;
const annexI=row.treatment==='annexI_goods'?annexIEntry(row.annexIItem):undefined;
const result:SalesLineResult={id:row.id,field:rule?.field??null,net:null,vat:null,gross:null,rate:rule?.rate??null,status:'indeterminate',reason:'',article:rule?.article??'Tratamento desconhecido',source:(rule?.source??'Fonte em falta')+(annex?`; ${pharmaAnnexReference(annex)}`:'')+(annexI?`; ${annexIReference(annexI)}`:'')};
const stop=(reason:string)=>({...result,reason});
if(currency!=='MZN'||row.sourceCurrency!==currency)return stop('Moeda fora de MZN ou divergente da origem; sem conversão silenciosa.');
if(!/^2026-(0[1-9]|1[0-2])$/.test(row.period))return stop('Período fora da cobertura de2026; sem cálculo histórico presumido.');
if(temporaryBenefit(row.treatment))return stop(temporaryBenefitNotice(row.treatment,row.period));
const supplyIssue=onboardSupplyIssue(row.treatment,row.supplyCategory);
if(supplyIssue)return {...stop(supplyIssue),field:null,rate:null};
if(!rule||rule.rate===null||!rule.field)return stop('Operação não calculada: delimite incidência, territorialidade e fundamento desta linha. A remissão do campo06 não constitui uma regra de classificação de todas as operações no estrangeiro.');
if(n===null||!['net','included'].includes(row.basis))return stop('Montante ou indicação de IVA incluído/sem IVA em falta; vazio não significa zero.');
if(!row.description.trim()||!row.establishment.trim())return stop('Indique a operação e o estabelecimento a que pertence; não inferidos da localização do investimento.');
if(rule.conditions.some((_,i)=>!row.confirmed.includes(i))||!row.evidence.trim())return stop('Condições da operação ou fundamento/pressuposto em falta; o sector não prova o tratamento fiscal.');
if(row.sourceAmount!==null&&amount(row.sourceAmount)!==n)return stop('Divergência com o valor reutilizado: conserve a origem e prepare a repartição explicitamente; não substituir silenciosamente.');
if(row.treatment==='pharma_manufacturing_inputs'&&!annex)return stop('Escolha a linha aplicável do Anexo III/2022, com código e designação; um código livre, desconhecido ou de outro anexo não comprova a isenção.');
if(row.treatment==='annexI_goods'){
if(!annexI)return stop('Escolha a posição aplicável do Anexo I/2022, com código, designação e qualificadores; não presumir isenção por sector ou código livre.');
if(annexI.relatedRequired)return stop('Esta designação tem tratamento específico já disponível no artigo9(10), com direito à dedução nas condições do19(1)(b)(v). Escolha a continuidade indicada e confirme as suas condições; não atribuir07 apenas pela presença no Anexo I.');
if(annexI.relatedTreatments?.length&&row.annexIOnly!==true)return stop('A natureza ou o destino deste bem pode corresponder a outro tratamento já disponível. Escolha a continuidade aplicável ou fundamente expressamente por que a operação pertence apenas a9(12)(h); desconhecido não significa ausência desse enquadramento.');
}
if(row.treatment==='fundraising_public'||row.treatment==='fundraising_nonprofit'){const error=fundraisingError(row.fundraiser,row.treatment==='fundraising_nonprofit');if(error)return stop(error);}
const option=row.treatment.startsWith('production_')&&row.treatment.endsWith('_opted')?productionOptionCheck(row.taxOption,row.period):{};
if(option.error)return stop(option.error);
if(row.basis==='included'&&rule.rate===5){
const exact={net:fraction(n*20n,21000000n),vat:fraction(n,21000000n),gross:fraction(n,1000000n)};
return {...result,net:fractionPresentation(exact.net).decimal,vat:fractionPresentation(exact.vat).decimal,gross:money(n),exact,status:'calculated',reason:'Base e IVA conservados como fracções exactas (preço×20/21 e preço/21). Decimal a6casas é apresentação técnica, metade para cima; não é regra de arredondamento da declaração nem imposto final a pagar.'};
}
let net=n,vat=0n;
if(rule.rate===16&&row.basis==='included') {net=((n*100n+58000000n)/116000000n)*1000000n;vat=n-net;if(vat<0n)return stop('Arredondamento à unidade produz IVA negativo para este montante; reveja a linha e a documentação.');}
else vat=(n*BigInt(rule.rate)+50n)/100n;
return {...result,net:money(net),vat:money(vat),gross:money(row.basis==='included'?n:net+vat),status:rule.rate===0?'exempt':'calculated',reason:(rule.rate===0?(rule.field==='05'?'Isenção com direito à dedução nas condições legais; não é taxa zero nem dedução automática de compras.':'Isenção sem direito à dedução para esta operação; não é isenção geral da entidade.'):'IVA da operação projectada; não é imposto final a pagar nem declaração submetida.')+(option.summary?' '+option.summary:'')};
}
function key(draft:Record<string,unknown>,book:SalesBook,catalog=operationTreatments.filter(t=>book.rows.some(r=>r.treatment===t.id))):string {return JSON.stringify([operationVersion,catalog,acquisitionScope(draft),draft.currency,draft.province_id,draft.district_id,draft.business_plan_snapshot,draft.cashflow_snapshot,draft.monthly_iva_settings,book.currency,book.rows,book.periods]);}
export function salesCurrent(draft:Record<string,unknown>,book:SalesBook):boolean {return !!book.result&&book.result.version===operationVersion&&book.result.opportunity===acquisitionScope(draft)&&(book.result.key===key(draft,book)||book.result.key===key(draft,book,operationTreatments.filter(t=>legacyV2TreatmentIds.includes(t.id))));}
export function calculateSales(draft:Record<string,unknown>,book:SalesBook,now=new Date().toISOString()):SalesResult {
if(book.currency!=='MZN'||draft.currency!==book.currency)throw new Error('Confirme a moeda original MZN; sem conversão ou reinterpretação.');
if(new Set(book.rows.map(r=>r.id)).size!==book.rows.length||new Set(book.periods.map(p=>p.period)).size!==book.periods.length)throw new Error('Identificadores/períodos duplicados; corrija sem somar em duplicado.');
if(!book.periods.length||book.rows.some(r=>!book.periods.some(p=>p.period===r.period))||book.periods.some(p=>!/^2026-(0[1-9]|1[0-2])$/.test(p.period)))throw new Error('Cada operação deve pertencer a um período válido de2026 incluído na cobertura.');
let live:ReturnType<typeof monthlySalesFromDraft>|null=null;try {live=monthlySalesFromDraft(draft);}catch{ /* Explicitly block stale imported values below. */ }
const start=readMonthlyIvaSettings(String(draft.monthly_iva_settings??'')).start;
const rows=book.rows.map(r=>{
const result=evaluateSalesOperation(r,book.currency);
if(isExportService(r.treatment)&&r.relatedExport!==undefined){
const ref=r.relatedExport,target=ref&&typeof ref==='object'?book.rows.find(item=>item.id===ref.id&&item.id!==r.id):undefined;
if(!target||ref.description!==target.description||ref.treatment!==target.treatment)return {...result,net:null,vat:null,gross:null,status:'indeterminate' as const,reason:'A operação relacionada foi removida ou alterada. Actualize a referência e reveja as condições; preço do serviço e resultado anterior conservados.'};
}
const fundraiser=r.fundraiser;
if(r.treatment.startsWith('fundraising_')&&fundraiser&&book.rows.some(v=>v.id!==r.id&&v.treatment.startsWith('fundraising_')&&v.period.slice(0,4)===r.period.slice(0,4)&&String(v.fundraiser?.entityReference??'').trim()===String(fundraiser.entityReference??'').trim()&&v.fundraiser?.annualEvents!==fundraiser.annualEvents))return {...result,net:null,vat:null,gross:null,status:'indeterminate' as const,reason:'Totais anuais divergentes para a mesma entidade; resolva a divergência sem substituir dados de outra linha.'};
if(r.splitSource) {
const source=r.splitSource,group=book.rows.filter(v=>v.splitSource?.id===source.id),index=Number(source.period.slice(5))-Number(start.slice(5));
if(group.some(v=>v.period!==source.period||v.basis!==source.basis||v.sourceCurrency!==source.currency||JSON.stringify(v.splitSource)!==JSON.stringify(source))||sum(group.map(v=>v.amount))!==(amount(source.amount)===null?null:money(amount(source.amount)!))||!live||live.amounts[index]!==source.amount)return {...result,exact:undefined,net:null,vat:null,gross:null,status:'indeterminate' as const,reason:'Repartição não reconciliada com o total, período, moeda e representação do preço da origem; nenhuma parcela foi presumida.'};
}
if(r.sourceAmount!==null||r.source.startsWith('Vendas por produto')||r.source.startsWith('Receita mensal')) {
const index=Number(r.sourcePeriod.slice(5))-Number(start.slice(5));
if(!live||!/^2026-/.test(start)||r.sourcePeriod!==r.period||live.amounts[index]!==r.sourceAmount)return {...result,exact:undefined,net:null,vat:null,gross:null,status:'indeterminate' as const,reason:'A origem/período das vendas mudou. Reveja e confirme a nova origem; o resultado anterior foi conservado.'};
}
return result;
});
const periods=book.periods.map(p=>{
const matching=book.rows.map((r,i)=>({input:r,result:rows[i]})).filter(r=>r.input.period===p.period),fields:Record<string,string|null>={},exactFields:Record<string,FiscalFraction|null>={},reasons=matching.filter(r=>r.result.status==='indeterminate').map(r=>`${r.input.description||r.input.id}: ${r.result.reason}`);
const known=p.complete&&!matching.some(r=>r.result.status==='indeterminate');
for(const f of ['01','03','05','07'])fields[f]=known?sum(matching.filter(r=>r.result.field===f).map(r=>r.result.net)):null;
for(const [f,base] of [['02','01'],['04','03']])fields[f]=known?sum(matching.filter(r=>r.result.field===base).map(r=>r.result.vat)):null;
fields['06']=known?'0.00':null;
if(matching.some(r=>r.result.exact)) {
for(const [f,base,part] of [['01','01','net'],['02','01','vat'],['03','03','net'],['04','03','vat'],['05','05','net'],['06','06','net'],['07','07','net']] as const) {
exactFields[f]=known?addFractions(matching.filter(r=>r.result.field===base).map(r=>r.result.exact?.[part]??decimalFraction(r.result[part]!))):null;
fields[f]=exactFields[f]?fractionPresentation(exactFields[f]!).decimal:null;
}
}
if(!p.complete)reasons.push('Confirme que todas as operações do período foram incluídas; uma lista vazia só é zero após essa confirmação.');
return {period:p.period,fields,...(Object.keys(exactFields).length?{exactFields}:{}),reasons};
});
const labels=draft.selection_labels as Record<string,unknown>|undefined;
return {version:operationVersion,revision:(book.result?.revision??0)+1,calculatedAt:now,opportunity:acquisitionScope(draft),location:['province_id','district_id'].filter(k=>draft[k]).map(k=>String(labels?.[k]??draft[k])).join(' / '),currency:book.currency,key:key(draft,book),inputs:structuredClone(book.rows),rows,periods,rounding:'Base líquida: precisão técnica6decimais, metade para cima, sem arredondamento final da declaração. Preço geral com IVA: base=preço×100/116, arredondada à unidade mais próxima (metade para cima), IVA=preço−base, CIVA art.34 redacção Lei10/2025. Preço incluído5%: fracções exactas preço×20/21 e preço/21 conservadas; decimal a6casas/metade para cima apenas na apresentação. A regra declarativa não é presumida.'};
}
export function salesReportRows(draft:Record<string,unknown>):Array<[string,string,string,string]> {
try {const book=salesBook(draft),r=book.result;if(!r)return [];
const context=`${r.currency}; oportunidade ${r.opportunity}; ${r.location||'localização não indicada'}; ${r.version}; revisão ${r.revision}; ${r.calculatedAt}`;
const out:Array<[string,string,string,string]>=[['IVA mensal','Operações IVA L1',salesCurrent(draft,book)?'Resultado correspondente às entradas':'Histórico desactualizado; não aplicar à projecção actual',context],['IVA mensal','Método e limites L1',r.rounding,'Sem apuramento integral, dedução automática ou submissão AT']];
for(const row of r.inputs){const value=r.rows.find(v=>v.id===row.id)!;out.push(['IVA mensal',`${row.period} — ${row.description} — ${row.establishment}`,`Declarado ${row.amount||'em falta'} ${row.sourceCurrency}; ${row.basis==='included'?'IVA incluído':row.basis==='net'?'sem IVA':'base desconhecida'}; líquido ${value.net??'Indeterminado'}; IVA ${value.vat??'Indeterminado'}; bruto ${value.gross??'Indeterminado'}; campo ${value.field??'não determinado'}; ${value.reason}`,`${context}; ${value.article}; ${value.source}; origem: ${row.source}; pressuposto/documento: ${row.evidence||'em falta'}; condições confirmadas: ${row.confirmed.join(',')||'nenhuma'}`]);}
for(const row of r.inputs.filter(v=>v.fundraiser))out.push(['IVA mensal',`Manifestação ocasional — ${row.description}`,`Entidade ${row.fundraiser!.entityReference}; ano ${row.period.slice(0,4)}; total anual declarado ${row.fundraiser!.annualEvents}; manifestação ${row.fundraiser!.eventNumber}; actividade ${row.fundraiser!.activity}`,`${context}; dados declarados para a entidade, incluindo manifestações fora deste dossier; não é contagem automática das vendas.`]);
for(const row of r.inputs.filter(v=>isExportService(v.treatment)&&v.relatedExport))out.push(['IVA mensal',`Operação relacionada — ${row.description}`,`${row.relatedExport!.description}; ID ${row.relatedExport!.id}; tratamento ${row.relatedExport!.treatment}`,`${context}; referência escolhida expressamente nesta oportunidade,sem copiar valor para preço do serviço nem provar automaticamente o enquadramento subjacente`]);
for(const row of r.inputs.filter(v=>isOnboardSupply(v.treatment)))out.push(['IVA mensal',`Natureza do abastecimento — ${row.description}`,supplyCategories.find(([value])=>value===row.supplyCategory)?.[1]??'Por identificar',`${context}; CIVA13(2–3); natureza conservada no cálculo/relatório, sem aplicar dedução ou restituição automaticamente`]);
for(const value of r.rows.filter(v=>v.exact))out.push(['IVA mensal',`Precisão exacta — ${value.id}`,`Líquido ${fractionLabel(value.exact!.net)} MZN; IVA ${fractionLabel(value.exact!.vat)} MZN; bruto ${fractionLabel(value.exact!.gross)} MZN`,`${context}; apresentação decimal a6casas, aproximação quando a fracção não termina; não aplicar à declaração sem a sua regra própria.`]);
for(const p of r.periods){out.push(['IVA mensal',`Operações L1 — ${p.period}`,Object.entries(p.fields).map(([f,v])=>`${f}: ${v??'Indeterminado'}`).join('; '),`${context}; ${p.reasons.join(' ')}`]);
if(p.exactFields)out.push(['IVA mensal',`Precisão exacta do período — ${p.period}`,Object.entries(p.exactFields).map(([f,v])=>`${f}: ${v?fractionLabel(v):'Indeterminado'}`).join('; '),`${context}; totais em fracções MZN, calculados antes da apresentação decimal, sem regra declarativa presumida.`]);
}return out;
}catch{return [['IVA mensal','Operações IVA L1','Não foi possível recuperar as operações guardadas','Originais preservados; sem substituição por zero']];}
}
+180
View File
@@ -0,0 +1,180 @@
// Transcription of the accepted official exemplar, not a tariff classification service.
// Keep duplicated codes and printed incomplete positions distinct; never infer missing digits.
export const pharmaAnnexVersion='annexIII-lei22-2022/1';
export const pharmaAnnexSource='Lei22/2022, art.3(1), AnexoIII, PDF12–16, p.2252(36)–(40); efeitos01/01/2023';
export const pharmaAnnexPdfSha256='ea1b0dc6f5cf6e595f6d9a19e7042f398999e0087caef1785f6e8fac571b5f53';
export type PharmaAnnexEntry={id:string;code:string;label:string;pdfPage:number;lastPdfPage:number};
export const pharmaAnnexEntries:PharmaAnnexEntry[]=[
{"id":"annexIII-2022-001","code":"1108.11.00","label":"- Amido de trigo","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-002","code":"1108.12.00","label":"- Amido de milho","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-003","code":"1108.19.00","label":"- Outros amidos e féculas","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-004","code":"1301.20.00","label":"- Goma – arábica","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-005","code":"1301.90.00","label":"- Goma – laca; Gomas, resinas, gomas – resinas e oleorresinas (bálsamo, por exemplo), naturais - Outras","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-006","code":"1505.00.00","label":"- Lanolina","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-007","code":"1521.90.00","label":"- Ceras; cera de abelhas; cera de carnaúba; espermacete; ozocerite","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-008","code":"1701.99.00","label":"- Sacarose","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-009","code":"1702.11.00","label":"- Lactose","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-010","code":"1702.19.00","label":"- Lactose mono-hidratada (500 mg)","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-011","code":"1702.30.00","label":"- Glucose","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-012","code":"1702.50.00","label":"- Futose padrão","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-013","code":"2207.10.10","label":"- Álcool etílico para uso hospitalares","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-014","code":"2507.00.00","label":"- Caulino","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-015","code":"2709.00.00","label":"- Óleo Mineral betuminoso","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-016","code":"2806.10.00","label":"- Ácido Clorídrico","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-017","code":"2807.00.00","label":"- Ácido Sulfúrico","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-018","code":"2808.00.00","label":"- Ácido Nítrico","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-019","code":"2809.10.00","label":"- Pentóxido de difósforo","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-020","code":"2809.20.00","label":"- Ácido forfórico","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-021","code":"2810.00.00","label":"- Ácido Bórico","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-022","code":"2811.22.00","label":"- Dióxido de silício","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-023","code":"2811.29.00","label":"- Ácidos inorgânicos e outros componentes oxigenados inorgânicos dos elementos não metálicos - Outros","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-024","code":"2812.90.00","label":"- Halogenetos e oxialogenetos dos elementos não – metálicos - Outros","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-025","code":"2813.90.00","label":"- Sulfuretos dos elementos não-metalicos; trissulfureto de fósforo comercial - Outros","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-026","code":"2815.20.00","label":"- Hidróxido de Potássio","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-027","code":"2815.30.00","label":"- Peróxidos de Sódio ou de Potássio","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-028","code":"2819.90.00","label":"- Óxidos e hidróxidos de crónico - Outros","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-029","code":"2823.00.00","label":"- Óxido de Titânio","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-030","code":"2825.90.00","label":"- Hidrazina e hidroxilamina, e seus sais orgânicos - Outros","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-031","code":"2827.20.00","label":"- Cloreto de cálcio","pdfPage":12,"lastPdfPage":12},
{"id":"annexIII-2022-032","code":"2827.39.00","label":"- Cloretos, oxicloretos e hidroxicloretos, brometos e oxibrometos iodetos e oxiodetos - Outros","pdfPage":12,"lastPdfPage":13},
{"id":"annexIII-2022-033","code":"2827.60.00","label":"- Iodetos e oxidetos","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-034","code":"2829.19.00","label":"- Cloratos e precloratos; bromatos e perbromatos; iodatos e periodatos --Outros","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-035","code":"2829.90.00","label":"- Cloratos e precloratos; bromatos e perbromatos; iodatos e peridatos - Outros","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-036","code":"2832.30.00","label":"- Tiossulfatos","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-037","code":"2833.29.00","label":"- Sulfatos de sódio - Outros","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-038","code":"2834.29.00","label":"- Nitritos, nitratos - Outros","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-039","code":"2835.22.00","label":"- Fosfato sódico monobásico, fosfato sódico dibásico","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-040","code":"2835.24.00","label":"- Fosfato de Potássio Monobásico, fosfato de potássio","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-041","code":"2835.25.00","label":"- Hidrogeno-ortofosfato de cálcio (fosfato dicalcico)","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-042","code":"2835.29.00","label":"- Outros fosfatos","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-043","code":"2836.40.00","label":"- Carbonato de Potássio","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-044","code":"2836.50.00","label":"-Carbonato de Cálcio","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-045","code":"2836.99.00","label":"- Carbonatos; Peroxocarbonatos (percarbonatos); carbonato de amónio comercial que contenha carbonato de amónio - Outros","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-046","code":"2837.19.00","label":"- Solução de Cianeto de Potássio","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-047","code":"2839.90.00","label":"- Trissilicato de magnésio","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-048","code":"2841.50.00","label":"- Cromato de Potássio AR","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-049","code":"2841.61.00","label":"- Permanganato de Potássio; Permanganato de Potássio AR","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-050","code":"2841.70.00","label":"- Solução de Mobibdato de Amónio","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-051","code":"2841.80.00","label":"- Tungstato de sódio","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-052","code":"2841.90.00","label":"- Piroantimoniato de Potássio","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-053","code":"2842.90.00","label":"- Outros sais dos ácidos ou peróxidos inorgânicos","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-054","code":"2843.21.00","label":"- Nitrato de Prata","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-055","code":"2843.29.00","label":"- Cianeto de Potássio; Citrato Cúprico Alcalino TS","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-056","code":"2847.00.00","label":"- Peróxido de Hidrogénio","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-057","code":"2901.29.00","label":"- Hidrocarbonetos acíclicos - Outros","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-058","code":"2902.11.00","label":"- Ciclohexano","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-059","code":"2902.20.00","label":"- Benzeno","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-060","code":"2902.30.00","label":"- Tolueno","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-061","code":"2902.90.00","label":"- Cloreto de Mitileno; Diclorometano;","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-062","code":"2903.13.00","label":"- Clorofórmio","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-063","code":"2903.14.00","label":"- Tetracloreto de Carbono","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-064","code":"2903.22.00","label":"- Tricloetileno","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-065","code":"2904.91.00","label":"- Hidrocarbonetos cíclicos - Outros","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-066","code":"2905.11.00","label":"- Metanol; Metanol HPLC; Metanol P.A","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-067","code":"2905.12.00","label":"- Álcool Isopropílico; Álcool n-Propílico","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-068","code":"2905.13.00","label":"- Etanol; clorobutanol","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-069","code":"2905.14.00","label":"- Álcool estearílico; álcool cetílico; álcool palmítico","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-070","code":"2905.19.00","label":"- Propranolol Cloridrato (200mg)","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-071","code":"2905.31.00","label":"- Etinoglicol","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-072","code":"2905.32.00","label":"- Propilenoglicol","pdfPage":13,"lastPdfPage":13},
{"id":"annexIII-2022-073","code":"2905.43.00","label":"- Manita ou manitol","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-074","code":"2905.44.00","label":"- D-glucitol (sorbitol)","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-075","code":"2905.45.00","label":"- Glicerina","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-076","code":"2905.49.00","label":"- Alcoois acíclicos e seus derivados halogenados, sulfonados, nitrados ou nitrosados - Outros","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-077","code":"2906.13.00","label":"- Esteróis e inositois","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-078","code":"2906.21.00","label":"- Álcool benzílico","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-079","code":"2907.15.00","label":"- 1 – Naftol Ts; 2 -naftol","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-080","code":"2907.19.00","label":"Fénois; fenóis-alcoois - Outros","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-081","code":"2907.29.00","label":"Pelifenois; fénois-alcoois - Outros","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-082","code":"2909.19.00","label":"- Etér Etílico","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-083","code":"2909.49.00","label":"- Outros Eteres","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-084","code":"2912.19.00","label":"- Solução de Formaldeido","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-085","code":"2912.19.00","label":"- Acetaldeíco; Anisaldeído;p-dimetilaminobenzaldeído","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-086","code":"2914.11.00","label":"- Acetona","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-087","code":"2914.13.00","label":"- 4-metilpentan-2-ol","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-088","code":"2915.21.00","label":"- Ácido Acético glacial","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-089","code":"2915.24.00","label":"- Anidrido Acético","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-090","code":"2915.39.00","label":"- Acidos monocarboxilicos acíclicos saturados e seus anidridos, halogenetos, peróxidos e peroxiácidos, seus derivados halogenados, sulfanados, nitrados ou nitrosados - Outros","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-091","code":"2915.50.00","label":"- Ácido propionico, seus sais e seus ésteres","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-092","code":"2915.70.00","label":"- Ácidos palmíticos, ácido esteárico, seus sais e seus ésteres","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-093","code":"2915.90.00","label":"- Ácidos monocarboxilicos acíclicos saturados e seus anidridos, halogenetos, peróxidos e perxiácidos; seus derivados halogenados, sulfanados, nitrados ou nitrosados - Outros","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-094","code":"2916.15.00","label":"- Ácido oleico, linoléico, seus sais e seus ésteres","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-095","code":"2916.31.00","label":"- Ácido benzóico sais e seus ésteres","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-096","code":"2916.32.00","label":"- Cloreto de benzoílo","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-097","code":"2916.39.00","label":"- Benzoato de sódio","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-098","code":"2917.11.00","label":"- Ácido oxálico; Oxalato de amónia AR","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-099","code":"2917.12.00","label":"- Ácido adípico","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-100","code":"2918.11.00","label":"- Ácido láctico, seus sais e seus ésteres","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-101","code":"2918.12.00","label":"- Ácido Tartárico","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-102","code":"2918.14.00","label":"- Ácido Cítrico","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-103","code":"2918.15.00","label":"- Sais e éstres do ácido cítrico: Citrato de sódio","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-104","code":"2918.16.00","label":"- Ácido Glucónico","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-105","code":"2918.19.00","label":"- Tartarato de sódio, ésteres propílico, octílico e dodecílico do ácido gálico","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-106","code":"2918.99.00","label":"- Captopril (200 mg); Captopril","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-107","code":"2921.59.00","label":"- Dietilamina","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-108","code":"2922.12.00","label":"- Dietilamina","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-109","code":"2922.15.00","label":"- Trietanolamina e seus sais","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-110","code":"2922.29.00","label":"- Cloridrato de procaína","pdfPage":14,"lastPdfPage":14},
{"id":"annexIII-2022-111","code":"2922.49.00","label":"- Compostos aminados de funções oxigenadas - Outros","pdfPage":14,"lastPdfPage":15},
{"id":"annexIII-2022-112","code":"2923.90.00","label":"- Sais e Hidróxido de Amónio quatenários - Outros","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-113","code":"2924.29.00","label":"- Compostos de função carboxiamida; compostos de funçãoamida do ácido carbónico - Outros","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-114","code":"2925.11.00","label":"- Sacarina sódica e seus sais","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-115","code":"2925.19.00","label":"- o – Tolina","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-116","code":"2926.10.00","label":"- Acrilonitrila","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-117","code":"2930.90.00","label":"- Tiocompostos orgânicos - Outros","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-118","code":"2932.11.00","label":"- Tetrahidrofurano","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-119","code":"2932.99.00","label":"- Compostos heterocíclicos exclusivamente de heteroátomos de oxigénio - Outros","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-120","code":"2933.31.00","label":"- Piridina e seus sais","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-121","code":"2933.39.00","label":"Compostos hetrocíclicos exclusivamente de heteroatomos de azoto - Outros","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-122","code":"2933.91.00","label":"- Diazepam; Diazepam padrão; Composto Relacionado A de Diazepam; Composto relacionado B de Diazepam; Nordazepam padrão; Haloperidol (200 mg); Haloperido Composto Relacionado A (10 mg); Haloperidol Composto Relacionado B (10mg)","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-123","code":"2935.","label":"- Sulfonamidas","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-124","code":"2936.24.00","label":"- Ácido Fólico (500 mg) (Vitamina M ou Vitamina Bc); Ácido Fólico (500 mg) Composto relacionado A","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-125","code":"2936.27.00","label":"- Ácido ascórbico, ésteres de ácido ascórbico","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-126","code":"2936.28.00","label":"- Tocoferóis","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-127","code":"2936.29.00","label":"- Niacinamida","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-128","code":"2937.21.00","label":"- Prednison padrão","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-129","code":"2937.23.00","label":"- Progesterona 20 mg","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-130","code":"2939.30.00","label":"- Cafeina e seus sais","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-131","code":"2940.00.00","label":"- Açúcares quimicamente puros","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-132","code":"2941.10.00","label":"- Penicilinas e seus derivados","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-133","code":"2941.30.00","label":"- Tetraclinas e seus derivados","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-134","code":"2941.90.00","label":"- Antibióticos - Outros","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-135","code":"2942.00.00","label":"- Compostos orgânicos","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-136","code":"3204.11.00","label":"- Corantes dispersos e preparações à base desses corantes","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-137","code":"3206.19.00","label":"- Outras matérias corantes - Outros","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-138","code":"3404.90.00","label":"- Cera microcristalina","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-139","code":"3503.00.00","label":"- Gelatina","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-140","code":"3505.10.00","label":"- Amidoglicolato de sódio (glicolato de amido sódico); Goma de amido TS; derivados de amido","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-141","code":"3701.99.00","label":"- Filmes, folhas e laminados: filmes de plástico; filmes de celulose regenerada; folhas ou lâminas de alumínio; folhas ou lâminas de alumínio (laminas ou revestidas com uma camada plástica)","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-142","code":"3901.90.00","label":"- Polietileno ( de baixa, média e alta densidade)","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-143","code":"3904.90.00","label":"- Cloresto de polivinilo (PVP) (com ou sem plastificante)","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-144","code":"3906.90.00","label":"- Polímero acrílico em forma primária - Outros","pdfPage":15,"lastPdfPage":15},
{"id":"annexIII-2022-145","code":"3911.90.00","label":"- Resinas sintéticas","pdfPage":16,"lastPdfPage":16},
{"id":"annexIII-2022-146","code":"3912.31.00","label":"- Carboximetilcelulose e seus sais","pdfPage":16,"lastPdfPage":16},
{"id":"annexIII-2022-147","code":"3912.90.00","label":"- Celulose e seus derivados - Outros","pdfPage":16,"lastPdfPage":16},
{"id":"annexIII-2022-148","code":"3923.30.20","label":"- Embalagens para acondicionamento de medicamentos e produtos","pdfPage":16,"lastPdfPage":16},
{"id":"annexIII-2022-149","code":"3926.90.90","label":"- Barricas plásticas, paletes de plástico","pdfPage":16,"lastPdfPage":16},
{"id":"annexIII-2022-150","code":"4014.90.00","label":"- Artigos de higiene ou farmácia de borracha vulcanizada não endurecida - Outras","pdfPage":16,"lastPdfPage":16},
{"id":"annexIII-2022-151","code":"4821.10.00","label":"- Etiquetas impressas (aprovação, reprovado, quarentena)","pdfPage":16,"lastPdfPage":16},
{"id":"annexIII-2022-152","code":"5906.10.00","label":"- Fita gomada","pdfPage":16,"lastPdfPage":16},
{"id":"annexIII-2022-153","code":"7010.10.00","label":"- Frascos de vidro, ampolas","pdfPage":16,"lastPdfPage":16},
{"id":"annexIII-2022-154","code":"7017.90.00","label":"- Artefactos de vidro para laboratório, higiene e farmácia, mesmo graduados ou calibrados - Outros","pdfPage":16,"lastPdfPage":16},
{"id":"annexIII-2022-155","code":"7310.10.00","label":"- Barricas metálicas","pdfPage":16,"lastPdfPage":16},
{"id":"annexIII-2022-156","code":"7313.00.00","label":"- Arame farpado de ferro ou aço; Arames ou tiras retorcidos, mesmoi farpado de ferro ou aço, do tipo utinlizado em cercas","pdfPage":16,"lastPdfPage":16},
{"id":"annexIII-2022-157","code":"7604.29.00","label":"- Placas de alumínio, ou ligas de alumínio","pdfPage":16,"lastPdfPage":16},
{"id":"annexIII-2022-158","code":"7607.19.00","label":"- Placas de alumínio; filmes para fabrico de envelopes, blisters e strips","pdfPage":16,"lastPdfPage":16},
{"id":"annexIII-2022-159","code":"7612.90.00","label":"- Recipientes para armazenamento e transporte de líquido","pdfPage":16,"lastPdfPage":16},
{"id":"annexIII-2022-160","code":"7616.91.00","label":"- Paletes de alumínio","pdfPage":16,"lastPdfPage":16},
{"id":"annexIII-2022-161","code":"8311.90.00","label":"- Outros fios, varetas, tubos, chapas e artefactos semelhantes de metais comuns","pdfPage":16,"lastPdfPage":16},
{"id":"annexIII-2022-162","code":"8414.59.00","label":"- Câmaras de fluxo laminar","pdfPage":16,"lastPdfPage":16},
{"id":"annexIII-2022-163","code":"8418.50.10","label":"-Refrigeradores, congeladores para usos nos laboratórios para fins medicinais","pdfPage":16,"lastPdfPage":16},
{"id":"annexIII-2022-164","code":"8419.89.00","label":"- Estufa de leito fluidizado","pdfPage":16,"lastPdfPage":16},
{"id":"annexIII-2022-165","code":"8456.90.00","label":"- Máquina para moldagem de supositórios","pdfPage":16,"lastPdfPage":16},
{"id":"annexIII-2022-166","code":"8480.20.00","label":"- Placas de fundo para moldes","pdfPage":16,"lastPdfPage":16},
{"id":"annexIII-2022-167","code":"9016.00.00","label":"- Balanças sensíveis e pesos iguais ou inferiores a 5 cg","pdfPage":16,"lastPdfPage":16},
{"id":"annexIII-2022-168","code":"9018.39.00","label":"- Sistemas para bolsas de Injectáveis","pdfPage":16,"lastPdfPage":16},
{"id":"annexIII-2022-169","code":"9025.19.00","label":"- Outros Termómetros","pdfPage":16,"lastPdfPage":16},
{"id":"annexIII-2022-170","code":"9025.90.00","label":"- Partes e acessórios de instrumentos de medição","pdfPage":16,"lastPdfPage":16}
];
export function pharmaAnnexEntry(id:unknown):PharmaAnnexEntry|undefined {return typeof id==='string'?pharmaAnnexEntries.find(entry=>entry.id===id):undefined;}
export function pharmaAnnexReference(entry:PharmaAnnexEntry):string {return `AnexoIII/2022: ${entry.id}; código ${entry.code}; ${entry.label}; PDF${entry.pdfPage}${entry.lastPdfPage===entry.pdfPage?'':`–${entry.lastPdfPage}`}; ${pharmaAnnexVersion}`;}
+36
View File
@@ -0,0 +1,36 @@
export type ProductionTaxOption = {mode:''|'annual'|'startup';declarationDate:string;startupDate:string;returnStatus:''|'none'|'declared';returnDeclarationDate:string;operationDate:string;origin?:{rowId:string;description:string;establishment:string}};
export const productionOptionVersion='production-option/2';
// Civil Code 279(c), read with 296: the term ends at 24:00 on this date.
// A missing anniversary day is clamped within the same month, never rolled to March.
export function productionMinimumTermEnd(effective:string):string {
const year=Number(effective.slice(0,4))+5,month=Number(effective.slice(5,7)),day=Number(effective.slice(8,10));
const leap=year%4===0&&(year%100!==0||year%400===0);
const lastDay=[31,leap?29:28,31,30,31,30,31,31,30,31,30,31][month-1];
return `${String(year).padStart(4,'0')}-${String(month).padStart(2,'0')}-${String(Math.min(day,lastDay)).padStart(2,'0')}`;
}
export const productionReturnEffective=(declarationDate:string):string=>String(Number(declarationDate.slice(0,4))+1).padStart(4,'0')+'-01-01';
export const emptyProductionTaxOption = ():ProductionTaxOption=>({mode:'',declarationDate:'',startupDate:'',returnStatus:'',returnDeclarationDate:'',operationDate:''});
export function productionOptionCheck(option:ProductionTaxOption|undefined,period:string):{error?:string;summary?:string} {
const valid=(value:unknown):value is string=>typeof value==='string'&&/^\d{4}-\d{2}-\d{2}$/.test(value)&&Number(value.slice(0,4))>=1&&Number.isFinite(new Date(value+'T00:00:00Z').valueOf())&&new Date(value+'T00:00:00Z').toISOString().slice(0,10)===value;
if(!option||!['annual','startup'].includes(option.mode)||!valid(option.declarationDate)||!valid(option.operationDate))return {error:'Indique o tipo/data da declaração de opção e a data da operação; não se presume renúncia eficaz.'};
if(option.operationDate.slice(0,7)!==period)return {error:'A data da operação deve pertencer ao período desta linha; não repartir montantes automaticamente.'};
let effective=String(Number(option.declarationDate.slice(0,4))+1).padStart(4,'0')+'-01-01';
if(option.mode==='startup'){
if(!valid(option.startupDate)||option.declarationDate>option.startupDate)return {error:'Na opção constante da declaração de início, indique a data de início e uma declaração que não lhe seja posterior.'};
effective=option.startupDate;
}
if(option.operationDate<effective)return {error:`Opção ainda sem efeitos nesta operação; início de efeitos ${effective}.`};
if(!['none','declared'].includes(option.returnStatus))return {error:'Indique expressamente se existe declaração de regresso à isenção; informação desconhecida não significa ausência de declaração.'};
if(option.returnStatus==='none'&&option.returnDeclarationDate)return {error:'Foi indicada ausência de declaração de regresso, mas existe uma data guardada; resolva a divergência explicitamente.'};
let end='';
if(option.returnStatus==='declared'){
if(!valid(option.returnDeclarationDate))return {error:'Data da declaração de regresso à isenção em falta ou inválida; não presumir uma data.'};
const anniversary=productionMinimumTermEnd(effective);
if(option.returnDeclarationDate<option.declarationDate)return {error:'A declaração de regresso antecede a declaração de opção; resolva a divergência do histórico.'};
if(option.returnDeclarationDate>anniversary)return {error:`A declaração de regresso indicada é posterior ao termo às 24 horas de ${anniversary}; o CIVA, art.11(3), exige entrega antes de expirar o prazo. Não presumir efeitos para esta declaração tardia.`};
end=productionReturnEffective(option.returnDeclarationDate);
if(end<=anniversary)return {error:`O regresso não pode produzir efeitos antes de terminado o prazo mínimo, às 24 horas de ${anniversary}.`};
if(option.operationDate>=end)return {error:`Opção já cessou na data desta operação; regresso à isenção com efeitos ${end}. Reveja o tratamento.`};
}
return {summary:`Art.11 (${productionOptionVersion}): declaração ${option.declarationDate} (${option.mode==='startup'?'opção no início da actividade':'opção anual'}); efeitos ${effective}; termo mínimo às 24 horas de ${productionMinimumTermEnd(effective)} (Código Civil, arts.279.º,c), e296.º); operação ${option.operationDate}; ${end?`declaração de regresso ${option.returnDeclarationDate}, efeitos ${end} (CIVA, art.11(3)); o termo do prazo não antecipa estes efeitos`:'ausência de declaração de regresso expressamente indicada; tributação continua, sem caducidade automática ao fim de cinco anos'}.${option.origin?` Opção reutilizada de ${option.origin.description} (${option.origin.rowId}), estabelecimento ${option.origin.establishment}; escolha confirmada nesta linha.`:''}`};
}
@@ -0,0 +1,26 @@
export const temporaryBenefitVersion = 'temporary-benefit-cessation/1';
export const temporaryBenefitEnd = '2025-12-31';
const amendments = 'Lei10/2025, BR248/suplemento1, art.1, PDF12/p.2180(12): altera3,6,12,18,19,21,23,25,26,27,31,32,33,34, sem prorrogar9(13)/9(16); art.5, PDF15/p.2180(15), efeitos01/01/2026. Art.12(1)(a) retira as remissões a9(13)/9(16) nas importações; este bloco trata operações internas, não calcula importações.';
const sugarOilSource = `Lei3/2025, BR95/suplemento, art.1, PDF1–2/p.478(1)–(2):9(13)(a–f), termo31/12/2025; art.2, PDF2, entrada na publicação21/05/2025. ${amendments}`;
export const temporaryBenefits = [
{ id: 'temporary_sugar', branch: 'P038', label: 'Transmissão do açúcar', article: '9(13)(a)', historicalScope: 'Transmissão do açúcar.', source: sugarOilSource },
{ id: 'temporary_sugar_industry_goods', branch: 'P039', label: 'Bens transmitidos pela indústria nacional do açúcar', article: '9(13)(b);9(14)', historicalScope: 'Matérias-primas, produtos intermediários, peças, equipamentos e componentes: a redacção de2025 diz efectuadas pela indústria nacional do açúcar. Art.9(14): documentos aduaneiros apropriados ou declaração do adquirente, consoante o caso, sobre incorporação no processo de produção.', source: sugarOilSource },
{ id: 'temporary_oils_soap', branch: 'P040', label: 'Óleos alimentares e sabões', article: '9(13)(c)', historicalScope: 'Transmissões de óleos alimentares e de sabões.', source: sugarOilSource },
{ id: 'temporary_oils_soap_factory', branch: 'P041', label: 'Produção industrial de óleo alimentar e sabões', article: '9(13)(d)', historicalScope: 'Bens resultantes da actividade industrial de produção de óleo alimentar e de sabões, transmitidos pelas respectivas fábricas.', source: sugarOilSource },
{ id: 'temporary_oils_soap_inputs', branch: 'P042', label: 'Matérias-primas para óleo/sabões — Anexo II', article: '9(13)(e)', historicalScope: 'Bens para utilização como matéria-prima na indústria de óleo e sabões, constantes da Pauta e discriminados noAnexoII daLei3/2025,PDF2. A lista não prorroga o prazo nem determina por si outra isenção.', source: sugarOilSource },
{ id: 'temporary_sugar_cane', branch: 'P043', label: 'Actividade agrícola de cana-de-açúcar para a indústria', article: '9(13)(f);9(14)', historicalScope: 'Bens e serviços no âmbito da actividade agrícola de produção de cana-de-açúcar destinados à indústria. Art.9(14): documentos aduaneiros apropriados ou declaração do adquirente, consoante o caso, sobre incorporação no processo de produção. A produção agrícola própria do9(7)(a) exige análise distinta.', source: sugarOilSource },
{ id: 'temporary_solar_inputs', branch: 'P045', label: 'Factores de produção de painéis solares para electrificação rural', article: '9(16)', historicalScope: 'Factores de produção de painéis solares para electrificação rural, constantes da Pauta e discriminados noAnexoIV. Não é uma isenção genérica de painéis ou de projectos de energia.', source: `Lei22/2022, art.1, PDF2/p.2252(26),9(16), termo31/12/2025;art.3(2),PDF4/p.2252(28),aditaAnexoIV;art.6,PDF4,efeitos01/01/2023. ${amendments}` },
] as const;
export function temporaryBenefit(id: string | undefined) {
return temporaryBenefits.find(item => item.id === id);
}
export function temporaryBenefitNotice(id: string, period: string): string {
const benefit = temporaryBenefit(id);
if (!benefit) throw new Error('Benefício temporário não identificado; dados conservados.');
if (!/^2026-(0[1-9]|1[0-2])$/.test(period)) return 'Período fora da cobertura de2026; não se calcula nem se certifica a isenção histórica.';
return `O benefício temporário do art.${benefit.article} terminou em31/12/2025 e não é aplicável a${period}. A cessação não determina, por si, a taxa ou outra isenção desta operação. Escolha expressamente o enquadramento actual e confirme as respectivas condições; montantes e imposto ficam por determinar até essa escolha.`;
}
+15 -4
View File
@@ -17,7 +17,9 @@ export function defaultCashflowDraftInputs() {
}
export type CashflowDraftSnapshot = {
version: 1;
version: 1 | 2;
/** Missing in legacy v1: never infer it from the current project. */
currency?: string | null;
taxMode: 'fixed' | 'schedule';
inputs: ReturnType<typeof defaultCashflowDraftInputs>;
};
@@ -31,7 +33,8 @@ export function restoreCashflowDraftSnapshot(
const parsed = JSON.parse(snapshot);
if (
!parsed ||
parsed.version !== 1 ||
![1, 2].includes(parsed.version) ||
(parsed.version === 2 && parsed.currency !== null && (typeof parsed.currency !== 'string' || !/^[A-Z]{3}$/.test(parsed.currency))) ||
!['fixed', 'schedule'].includes(parsed.taxMode) ||
!parsed.inputs ||
typeof parsed.inputs !== 'object' ||
@@ -55,7 +58,7 @@ export function restoreCashflowDraftSnapshot(
} else if (typeof value !== 'string' || value.length > 160)
return null;
}
return { version: 1, taxMode: parsed.taxMode, inputs: parsed.inputs };
return { version: parsed.version, ...(parsed.version === 2 ? {currency: parsed.currency} : {}), taxMode: parsed.taxMode, inputs: parsed.inputs };
} catch {
return null;
}
@@ -64,8 +67,16 @@ export function restoreCashflowDraftSnapshot(
export function serializeCashflowDraftSnapshot(
taxMode: CashflowDraftSnapshot['taxMode'],
inputs: CashflowDraftSnapshot['inputs'],
currency?: string | null,
): string {
return JSON.stringify({ version: 1, taxMode, inputs });
return JSON.stringify({ version: currency === undefined ? 1 : 2, ...(currency !== undefined ? {currency} : {}), taxMode, inputs });
}
export function cashflowCurrency(saved: CashflowDraftSnapshot, projectCurrency: string): {currency: string; matchesProject: boolean; notice: string} {
const currency = saved.version === 2 ? saved.currency : null;
if (!currency) throw new Error('A moeda de origem da tesouraria guardada está por confirmar. Os montantes foram preservados; confirme a moeda na ferramenta de tesouraria antes de calcular ou reutilizar as vendas.');
const matchesProject = currency === projectCurrency;
return {currency, matchesProject, notice: matchesProject ? '' : `A tesouraria foi guardada em ${currency}, mas o projecto está em ${projectCurrency || 'moeda por indicar'}. Os montantes continuam em ${currency}; não foram convertidos nem reinterpretados. Para os reutilizar no projecto, restaure explicitamente a moeda de origem. Uma projecção noutra moeda exige pressupostos próprios.`};
}
export type MonthlyCashflowInput = {
+10 -1
View File
@@ -1,5 +1,5 @@
import { monthlyProjectedSales, restoreBusinessPlanSnapshot } from './business-financial-plan.ts';
import { restoreCashflowDraftSnapshot } from './monthly-cashflow.ts';
import { cashflowCurrency, restoreCashflowDraftSnapshot } from './monthly-cashflow.ts';
import { isApiSimulationReadResponseV1, type ApiSimulationExecutionV1 } from './simulation-contract.ts';
export type MonthlyIvaInput = {
@@ -27,6 +27,8 @@ export function monthlySalesFromDraft(draft: Record<string, unknown>): { amounts
if (draft.cashflow_snapshot) {
const saved = restoreCashflowDraftSnapshot(String(draft.cashflow_snapshot));
if (!saved) throw new Error('Não foi possível recuperar a receita projectada.');
const origin = cashflowCurrency(saved, String(draft.currency ?? ''));
if (!origin.matchesProject) throw new Error(origin.notice);
return {amounts: Array.from({length: 12}, () => saved.inputs.monthlyRevenue.trim() === '' ? null : saved.inputs.monthlyRevenue), source: 'Receita mensal constante já declarada na projecção de tesouraria; confirme que corresponde a vendas tributáveis.'};
}
return {amounts: Array.from({length: 12}, () => null), source: 'Sem projecção de vendas guardada. Prepare as vendas no plano empresarial; não é necessário voltar a introduzi-las aqui.'};
@@ -48,4 +50,11 @@ export function readMonthlyIvaRecord(raw?: string): MonthlyIvaRecord | null {
} catch { /* Keep the stored value intact; no fallback fiscal result. */ }
return null;
}
/** Read an admitted execution through the existing ownership-protected endpoint; never create one. */
export async function recoverMonthlyIvaRecord(record: MonthlyIvaRecord, request: typeof fetch = fetch): Promise<MonthlyIvaRecord> {
const response = await request(`/api/v1/simulations/${encodeURIComponent(record.execution.id)}`, {credentials:'same-origin', headers:{Accept:'application/json'}});
const value: unknown = await response.json();
if (!response.ok || !isApiSimulationReadResponseV1(value) || value.data.id !== record.execution.id) throw new Error('Não foi possível recuperar a execução mensal guardada. Os dados foram preservados e não foi criada uma execução alternativa.');
return {input: record.input, execution: value.data};
}
export const monthlyIvaCashTreatment = 'IVA apresentado separadamente: não é somado novamente aos recebimentos declarados nem deduzido como custo ou imposto final a pagar. A tesouraria conserva os recebimentos e pagamentos introduzidos, antes de uma liquidação fiscal não apurada; não se presume cobrança integral das vendas no mesmo mês.';
+10 -2
View File
@@ -3,10 +3,13 @@ import { investmentFieldOrigin } from './context-inheritance.ts';
import { investmentLandPreparation } from './investment-land-preparation.ts';
import { monthlyIvaInput, monthlyIvaKey, readMonthlyIvaRecord, readMonthlyIvaSettings } from './monthly-iva.ts';
import { modeloAPurchaseReferences } from './iva-modelo-a.ts';
import { acquisitionReportRows } from './iva-acquisitions.ts';
import { salesReportRows } from './iva-operations.ts';
import { fiscalQaRows } from './fiscal-qa-preview.ts';
import { csvCellWithDelimiter } from './csv.js';
import {
restoreCashflowDraftSnapshot,
cashflowCurrency,
projectMonthlyCashflow,
} from './monthly-cashflow.ts';
import {
@@ -613,12 +616,15 @@ export function buildProjectDossierRows(
'Planeado/realizado declarado pelo utilizador',
]);
}
rows.push(...acquisitionReportRows(draft));
const operationRows = salesReportRows(draft);
rows.push(...operationRows);
if (draft.monthly_iva_snapshot) {
const saved = readMonthlyIvaRecord(String(draft.monthly_iva_snapshot));
let current = false;
try { current = !!saved && monthlyIvaKey(monthlyIvaInput(draft, readMonthlyIvaSettings(String(draft.monthly_iva_settings ?? '')))) === monthlyIvaKey(saved.input); } catch { /* An old fiscal version is never silently made current. */ }
rows.push(['IVA mensal', 'Estado da versão', current ? 'Entradas correspondentes à projecção guardada' : 'Histórico desactualizado face às vendas ou pressupostos actuais; não aplicar como resultado actual', 'Execução versionada no servidor; sem apuramento final']);
if (saved?.execution.result_snapshot) for (const [label,value] of fiscalQaRows(saved.execution.result_snapshot)) rows.push(['IVA mensal', label, value, 'Snapshot fiscal preservado; sem recálculo na exportação']);
if (saved?.execution.result_snapshot) for (const [label,value] of fiscalQaRows(saved.execution.result_snapshot)) rows.push(['IVA mensal', operationRows.length ? `Execução geral separada — ${label}` : label, value, operationRows.length ? 'Snapshot geral conservado como execução separada; não somar nem substituir a classificação por operação L1. Sem recálculo na exportação.' : 'Snapshot fiscal preservado; sem recálculo na exportação']);
else rows.push(['IVA mensal', 'Resultado', 'Indeterminado ou execução ainda não concluída', 'Sem substituição por zero']);
try {
for (const purchase of modeloAPurchaseReferences(draft)) rows.push(['IVA mensal', `Compras/encomendas — mês ${purchase.month}`, purchase.declared ?? 'Sem informação', 'Pressuposto actual do plano, não resultado fiscal histórico; base/IVA incluído por classificar; IVA suportado e dedutível indeterminados; não é data de factura ou pagamento']);
@@ -637,7 +643,9 @@ export function buildProjectDossierRows(
throw new Error(
'Pressupostos de tesouraria não recuperáveis; não foram substituídos por valores alternativos.',
);
const currency = String(draft.currency ?? '');
const originCurrency = cashflowCurrency(saved, String(draft.currency ?? ''));
const currency = originCurrency.currency;
if (originCurrency.notice) rows.push(['Tesouraria', 'Divergência de moeda', originCurrency.notice, 'Moeda original preservada; sem conversão']);
if (!currency)
throw new Error(
'Indique uma moeda para interpretar os montantes de tesouraria.',
+33
View File
@@ -0,0 +1,33 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Tests\TestCase;
final class IvaAgroDraftTest extends TestCase
{
use DatabaseTransactions;
public function test_agro_context_preserves_accepted_opportunities(): void
{
$target = DB::selectOne('select current_database() as name,inet_server_port() as port');
$this->assertSame('simulator_fiscal_delta_20261021_test', $target->name);
$this->assertSame(55441, (int) $target->port);
config(['investor-path.enabled' => true, 'suitecrm.enabled' => false]);
$this->actingAs(User::factory()->create(['email_verified_at' => now()]));
$draft = json_decode(file_get_contents(getenv('IVA_G2E_INPUT') ?: base_path('outputs/iva-l1-g2-agro-20261024/calculated.json')), true, flags: JSON_THROW_ON_ERROR);
$id = $this->postJson('/api/v1/simulation-drafts', ['personal_snapshot' => [], 'economic_snapshot' => $draft], ['Idempotency-Key' => (string) Str::uuid()])->assertCreated()->json('data.id');
$recovered = $this->getJson('/api/v1/simulation-drafts/'.$id)->assertOk()->json('data.economic_snapshot');
$this->assertSame($draft['modelo_a_snapshot'], $recovered['modelo_a_snapshot']);
$book = json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:314'];
$this->assertCount(4, $book['result']['rows']);
$this->assertSame('300.00', $book['result']['periods'][0]['fields']['07']);
$this->assertSame('100.00', $book['result']['periods'][0]['fields']['05']);
$this->assertSame(json_decode($draft['modelo_a_snapshot'], true)['salesOperations']['opportunity:310'], json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:310']);
$this->assertSame(json_decode($draft['modelo_a_snapshot'], true)['salesOperations']['opportunity:309'], json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:309']);
foreach ($book['result']['rows'] as $row) $this->assertSame('0.00', $row['vat']);
if (getenv('IVA_G2E_RECOVERED')) file_put_contents(getenv('IVA_G2E_RECOVERED'), json_encode($recovered, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE));
}
}
+44
View File
@@ -0,0 +1,44 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Tests\TestCase;
final class IvaAnnexIDraftTest extends TestCase
{
use DatabaseTransactions;
public function test_annex_i_and_explicit_continuations_recover_in_their_selected_opportunity(): void
{
$target = DB::selectOne('select current_database() as name,inet_server_port() as port');
$this->assertSame('simulator_fiscal_delta_20261021_test', $target->name);
$this->assertSame(55441, (int) $target->port);
config(['investor-path.enabled' => true, 'suitecrm.enabled' => false]);
$this->actingAs(User::factory()->create(['email_verified_at' => now()]));
$draft = json_decode(file_get_contents(getenv('IVA_G2L_INPUT') ?: base_path('outputs/iva-l1-g2-agro-annex-20261024/calculated.json')), true, flags: JSON_THROW_ON_ERROR);
$id = $this->postJson('/api/v1/simulation-drafts', ['personal_snapshot' => [], 'economic_snapshot' => $draft], ['Idempotency-Key' => (string) Str::uuid()])->assertCreated()->json('data.id');
$recovered = $this->getJson('/api/v1/simulation-drafts/'.$id)->assertOk()->json('data.economic_snapshot');
$this->assertSame($draft['modelo_a_snapshot'], $recovered['modelo_a_snapshot']);
$store = json_decode($recovered['modelo_a_snapshot'], true);
$book = $store['salesOperations']['opportunity:321'];
$this->assertSame('opportunity:321', $book['result']['opportunity']);
$this->assertSame('MZN', $book['result']['currency']);
$this->assertSame('2026-09', $book['result']['periods'][0]['period']);
$this->assertCount(10, $book['result']['rows']);
$this->assertSame('800.00', $book['result']['periods'][0]['fields']['07']);
$this->assertSame('200.00', $book['result']['periods'][0]['fields']['05']);
$this->assertSame('listed_fresh_chilled_tomato', $book['rows'][6]['treatment']);
$this->assertSame('listed_insecticides', $book['rows'][7]['treatment']);
$this->assertStringContainsString('annexI-2022-023', $book['rows'][6]['source']);
$this->assertStringContainsString('PDF8–9', $book['result']['rows'][5]['source']);
$this->assertStringContainsString('Outros tractores', $book['result']['rows'][4]['source']);
$this->assertTrue($book['rows'][8]['annexIOnly']);
$original = json_decode(file_get_contents(base_path('tests/frontend/fixtures/iva-pharma-inputs.json')), true, flags: JSON_THROW_ON_ERROR);
foreach (json_decode($original['modelo_a_snapshot'], true)['salesOperations'] as $key => $value) {
$this->assertSame($value, $store['salesOperations'][$key]);
}
if (getenv('IVA_G2L_RECOVERED')) file_put_contents(getenv('IVA_G2L_RECOVERED'), json_encode($recovered, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE));
}
}
+33
View File
@@ -0,0 +1,33 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Tests\TestCase;
final class IvaConditionalDraftTest extends TestCase
{
use DatabaseTransactions;
public function test_conditional_context_preserves_accepted_opportunities(): void
{
$target = DB::selectOne('select current_database() as name,inet_server_port() as port');
$this->assertSame('simulator_fiscal_delta_20261021_test', $target->name);
$this->assertSame(55441, (int) $target->port);
config(['investor-path.enabled' => true, 'suitecrm.enabled' => false]);
$this->actingAs(User::factory()->create(['email_verified_at' => now()]));
$draft = json_decode(file_get_contents(getenv('IVA_G2G_INPUT') ?: base_path('outputs/iva-l1-g2-conditional-20261024/calculated.json')), true, flags: JSON_THROW_ON_ERROR);
$id = $this->postJson('/api/v1/simulation-drafts', ['personal_snapshot' => [], 'economic_snapshot' => $draft], ['Idempotency-Key' => (string) Str::uuid()])->assertCreated()->json('data.id');
$recovered = $this->getJson('/api/v1/simulation-drafts/'.$id)->assertOk()->json('data.economic_snapshot');
$this->assertSame($draft['modelo_a_snapshot'], $recovered['modelo_a_snapshot']);
$book = json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:316'];
$this->assertCount(6, $book['result']['rows']);
$this->assertSame('600.00', $book['result']['periods'][0]['fields']['07']);
$this->assertSame('0.00', $book['result']['periods'][0]['fields']['05']);
$this->assertSame(json_decode($draft['modelo_a_snapshot'], true)['salesOperations']['opportunity:310'], json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:310']);
$this->assertSame(json_decode($draft['modelo_a_snapshot'], true)['salesOperations']['opportunity:309'], json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:309']);
foreach ($book['result']['rows'] as $row) $this->assertSame('0.00', $row['vat']);
if (getenv('IVA_G2G_RECOVERED')) file_put_contents(getenv('IVA_G2G_RECOVERED'), json_encode($recovered, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE));
}
}
+32
View File
@@ -0,0 +1,32 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Tests\TestCase;
final class IvaCulturalDraftTest extends TestCase
{
use DatabaseTransactions;
public function test_cultural_context_preserves_accepted_opportunities(): void
{
$target = DB::selectOne('select current_database() as name,inet_server_port() as port');
$this->assertSame('simulator_fiscal_delta_20261021_test', $target->name);
$this->assertSame(55441, (int) $target->port);
config(['investor-path.enabled' => true, 'suitecrm.enabled' => false]);
$this->actingAs(User::factory()->create(['email_verified_at' => now()]));
$draft = json_decode(file_get_contents(getenv('IVA_G2C_INPUT') ?: base_path('outputs/iva-l1-g2-cultural-20261024/calculated.json')), true, flags: JSON_THROW_ON_ERROR);
$id = $this->postJson('/api/v1/simulation-drafts', ['personal_snapshot' => [], 'economic_snapshot' => $draft], ['Idempotency-Key' => (string) Str::uuid()])->assertCreated()->json('data.id');
$recovered = $this->getJson('/api/v1/simulation-drafts/'.$id)->assertOk()->json('data.economic_snapshot');
$this->assertSame($draft['modelo_a_snapshot'], $recovered['modelo_a_snapshot']);
$book = json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:312'];
$this->assertCount(5, $book['result']['rows']);
$this->assertSame('500.00', $book['result']['periods'][0]['fields']['07']);
$this->assertSame(json_decode($draft['modelo_a_snapshot'], true)['salesOperations']['opportunity:310'], json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:310']);
$this->assertSame(json_decode($draft['modelo_a_snapshot'], true)['salesOperations']['opportunity:309'], json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:309']);
foreach ($book['result']['rows'] as $row) $this->assertSame('0.00', $row['vat']);
if (getenv('IVA_G2C_RECOVERED')) file_put_contents(getenv('IVA_G2C_RECOVERED'), json_encode($recovered, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE));
}
}
@@ -0,0 +1,44 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Tests\TestCase;
final class IvaExportDirectDraftTest extends TestCase
{
use DatabaseTransactions;
public function test_direct_export_rules_recover_with_the_selected_opportunity_and_previous_books(): void
{
$target = DB::selectOne('select current_database() as name,inet_server_port() as port');
$this->assertSame('simulator_fiscal_delta_20261021_test', $target->name);
$this->assertSame(55441, (int) $target->port);
config(['investor-path.enabled' => true, 'suitecrm.enabled' => false]);
$this->actingAs(User::factory()->create(['email_verified_at' => now()]));
$draft = json_decode(file_get_contents(base_path('outputs/iva-l1-g4-export-20261024/calculated.json')), true, flags: JSON_THROW_ON_ERROR);
$id = $this->postJson('/api/v1/simulation-drafts', ['personal_snapshot' => [], 'economic_snapshot' => $draft], ['Idempotency-Key' => (string) Str::uuid()])->assertCreated()->json('data.id');
$recovered = $this->getJson('/api/v1/simulation-drafts/'.$id)->assertOk()->json('data.economic_snapshot');
$this->assertSame($draft['modelo_a_snapshot'], $recovered['modelo_a_snapshot']);
$this->assertSame('opportunity:323', $recovered['context_opportunity']);
$this->assertSame('Manica', $recovered['selection_labels']['province_id']);
$store = json_decode($recovered['modelo_a_snapshot'], true, flags: JSON_THROW_ON_ERROR);
$book = $store['salesOperations']['opportunity:323'];
$this->assertSame('opportunity:323', $book['result']['opportunity']);
$this->assertSame('MZN', $book['result']['currency']);
$this->assertSame('2026-11', $book['result']['periods'][0]['period']);
$this->assertSame('500.00', $book['result']['periods'][0]['fields']['05']);
$this->assertCount(5, $book['rows']);
foreach ($book['result']['rows'] as $row) {
$this->assertSame('05', $row['field']);
$this->assertSame('0.00', $row['vat']);
}
$frozen = json_decode(file_get_contents(base_path('tests/frontend/fixtures/iva-g3-inputs.json')), true, flags: JSON_THROW_ON_ERROR);
foreach (json_decode($frozen['modelo_a_snapshot'], true, flags: JSON_THROW_ON_ERROR)['salesOperations'] as $context => $original) {
$this->assertSame($original, $store['salesOperations'][$context]);
}
file_put_contents(base_path('outputs/iva-l1-g4-export-20261024/recovered.json'), json_encode($recovered, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE));
}
}
@@ -0,0 +1,47 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Tests\TestCase;
final class IvaExportServiceDraftTest extends TestCase
{
use DatabaseTransactions;
public function test_linked_export_services_recover_with_the_selected_opportunity_and_previous_books(): void
{
$target = DB::selectOne('select current_database() as name,inet_server_port() as port');
$this->assertSame('simulator_fiscal_delta_20261021_test', $target->name);
$this->assertSame(55441, (int) $target->port);
config(['investor-path.enabled' => true, 'suitecrm.enabled' => false]);
$this->actingAs(User::factory()->create(['email_verified_at' => now()]));
$draft = json_decode(file_get_contents(base_path('outputs/iva-l1-g4-services-20261024/calculated.json')), true, flags: JSON_THROW_ON_ERROR);
$id = $this->postJson('/api/v1/simulation-drafts', ['personal_snapshot' => [], 'economic_snapshot' => $draft], ['Idempotency-Key' => (string) Str::uuid()])->assertCreated()->json('data.id');
$recovered = $this->getJson('/api/v1/simulation-drafts/'.$id)->assertOk()->json('data.economic_snapshot');
$this->assertSame($draft['modelo_a_snapshot'], $recovered['modelo_a_snapshot']);
$this->assertSame('opportunity:325', $recovered['context_opportunity']);
$this->assertSame('Manica', $recovered['selection_labels']['province_id']);
$store = json_decode($recovered['modelo_a_snapshot'], true, flags: JSON_THROW_ON_ERROR);
$book = $store['salesOperations']['opportunity:325'];
$this->assertSame('opportunity:325', $book['result']['opportunity']);
$this->assertSame('MZN', $book['result']['currency']);
$this->assertSame('2026-12', $book['result']['periods'][0]['period']);
$this->assertSame('1300.00', $book['result']['periods'][0]['fields']['05']);
$this->assertCount(4, $book['rows']);
$this->assertSame('g4c-goods', $book['rows'][2]['relatedExport']['id']);
$this->assertSame('100', $book['rows'][2]['amount']);
$this->assertSame('1000', $book['rows'][0]['amount']);
foreach ($book['result']['rows'] as $row) {
$this->assertSame('05', $row['field']);
$this->assertSame('0.00', $row['vat']);
}
$frozen = json_decode(file_get_contents(base_path('tests/frontend/fixtures/iva-g4b-inputs.json')), true, flags: JSON_THROW_ON_ERROR);
foreach (json_decode($frozen['modelo_a_snapshot'], true, flags: JSON_THROW_ON_ERROR)['salesOperations'] as $context => $original) {
$this->assertSame($original, $store['salesOperations'][$context]);
}
file_put_contents(base_path('outputs/iva-l1-g4-services-20261024/recovered.json'), json_encode($recovered, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE));
}
}
+32
View File
@@ -0,0 +1,32 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Tests\TestCase;
final class IvaFundraisingDraftTest extends TestCase
{
use DatabaseTransactions;
public function test_fundraising_context_preserves_accepted_opportunities(): void
{
$target = DB::selectOne('select current_database() as name,inet_server_port() as port');
$this->assertSame('simulator_fiscal_delta_20261021_test', $target->name);
$this->assertSame(55441, (int) $target->port);
config(['investor-path.enabled' => true, 'suitecrm.enabled' => false]);
$this->actingAs(User::factory()->create(['email_verified_at' => now()]));
$draft = json_decode(file_get_contents(getenv('IVA_G2J_INPUT') ?: base_path('outputs/iva-l1-g2-fundraising-20261024/calculated.json')), true, flags: JSON_THROW_ON_ERROR);
$id = $this->postJson('/api/v1/simulation-drafts', ['personal_snapshot' => [], 'economic_snapshot' => $draft], ['Idempotency-Key' => (string) Str::uuid()])->assertCreated()->json('data.id');
$recovered = $this->getJson('/api/v1/simulation-drafts/'.$id)->assertOk()->json('data.economic_snapshot');
$this->assertSame($draft['modelo_a_snapshot'], $recovered['modelo_a_snapshot']);
$book = json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:319'];
$this->assertCount(2, $book['result']['rows']);
$this->assertSame('200.00', $book['result']['periods'][0]['fields']['07']);
$this->assertSame('0.00', $book['result']['periods'][0]['fields']['05']);
$this->assertSame(json_decode($draft['modelo_a_snapshot'], true)['salesOperations']['opportunity:310'], json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:310']);
$this->assertSame(json_decode($draft['modelo_a_snapshot'], true)['salesOperations']['opportunity:309'], json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:309']);
if (getenv('IVA_G2J_RECOVERED')) file_put_contents(getenv('IVA_G2J_RECOVERED'), json_encode($recovered, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE));
}
}
+31
View File
@@ -0,0 +1,31 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Tests\TestCase;
final class IvaHealthGoodsDraftTest extends TestCase
{
use DatabaseTransactions;
public function test_health_goods_round_trip_preserves_other_opportunity(): void
{
$target = DB::selectOne('select current_database() as name,inet_server_port() as port');
$this->assertSame('simulator_fiscal_delta_20261021_test', $target->name);
$this->assertSame(55441, (int) $target->port);
config(['investor-path.enabled' => true, 'suitecrm.enabled' => false]);
$this->actingAs(User::factory()->create(['email_verified_at' => now()]));
$draft = json_decode(file_get_contents(getenv('IVA_G2A_INPUT') ?: base_path('outputs/iva-l1-g2-health-20261024/calculated.json')), true, flags: JSON_THROW_ON_ERROR);
$id = $this->postJson('/api/v1/simulation-drafts', ['personal_snapshot' => [], 'economic_snapshot' => $draft], ['Idempotency-Key' => (string) Str::uuid()])->assertCreated()->json('data.id');
$recovered = $this->getJson('/api/v1/simulation-drafts/'.$id)->assertOk()->json('data.economic_snapshot');
$this->assertSame($draft['modelo_a_snapshot'], $recovered['modelo_a_snapshot']);
$book = json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:309'];
$this->assertCount(5, $book['result']['rows']);
$this->assertSame('500.00', $book['result']['periods'][0]['fields']['07']);
$this->assertSame(json_decode($draft['modelo_a_snapshot'], true)['salesOperations']['opportunity:310'], json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:310']);
foreach ($book['result']['rows'] as $row) $this->assertSame('0.00', $row['vat']);
if (getenv('IVA_G2A_RECOVERED')) file_put_contents(getenv('IVA_G2A_RECOVERED'), json_encode($recovered, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE));
}
}
@@ -0,0 +1,44 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Tests\TestCase;
final class IvaInternationalAssetDraftTest extends TestCase
{
use DatabaseTransactions;
public function test_international_asset_rules_recover_with_the_selected_opportunity_and_previous_books(): void
{
$target = DB::selectOne('select current_database() as name,inet_server_port() as port');
$this->assertSame('simulator_fiscal_delta_20261021_test', $target->name);
$this->assertSame(55441, (int) $target->port);
config(['investor-path.enabled' => true, 'suitecrm.enabled' => false]);
$this->actingAs(User::factory()->create(['email_verified_at' => now()]));
$draft = json_decode(file_get_contents(base_path('outputs/iva-l1-g4-transport-20261024/calculated.json')), true, flags: JSON_THROW_ON_ERROR);
$id = $this->postJson('/api/v1/simulation-drafts', ['personal_snapshot' => [], 'economic_snapshot' => $draft], ['Idempotency-Key' => (string) Str::uuid()])->assertCreated()->json('data.id');
$recovered = $this->getJson('/api/v1/simulation-drafts/'.$id)->assertOk()->json('data.economic_snapshot');
$this->assertSame($draft['modelo_a_snapshot'], $recovered['modelo_a_snapshot']);
$this->assertSame('opportunity:324', $recovered['context_opportunity']);
$this->assertSame('Manica', $recovered['selection_labels']['province_id']);
$store = json_decode($recovered['modelo_a_snapshot'], true, flags: JSON_THROW_ON_ERROR);
$book = $store['salesOperations']['opportunity:324'];
$this->assertSame('opportunity:324', $book['result']['opportunity']);
$this->assertSame('MZN', $book['result']['currency']);
$this->assertSame('2026-12', $book['result']['periods'][0]['period']);
$this->assertSame('400.00', $book['result']['periods'][0]['fields']['05']);
$this->assertCount(4, $book['rows']);
foreach ($book['result']['rows'] as $row) {
$this->assertSame('05', $row['field']);
$this->assertSame('0.00', $row['vat']);
}
$frozen = json_decode(file_get_contents(base_path('tests/frontend/fixtures/iva-g4a-inputs.json')), true, flags: JSON_THROW_ON_ERROR);
foreach (json_decode($frozen['modelo_a_snapshot'], true, flags: JSON_THROW_ON_ERROR)['salesOperations'] as $context => $original) {
$this->assertSame($original, $store['salesOperations'][$context]);
}
file_put_contents(base_path('outputs/iva-l1-g4-transport-20261024/recovered.json'), json_encode($recovered, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE));
}
}
+33
View File
@@ -0,0 +1,33 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Tests\TestCase;
final class IvaListedGoodsDraftTest extends TestCase
{
use DatabaseTransactions;
public function test_listed_context_preserves_accepted_opportunities(): void
{
$target = DB::selectOne('select current_database() as name,inet_server_port() as port');
$this->assertSame('simulator_fiscal_delta_20261021_test', $target->name);
$this->assertSame(55441, (int) $target->port);
config(['investor-path.enabled' => true, 'suitecrm.enabled' => false]);
$this->actingAs(User::factory()->create(['email_verified_at' => now()]));
$draft = json_decode(file_get_contents(getenv('IVA_G2H_INPUT') ?: base_path('outputs/iva-l1-g2-listed-20261024/calculated.json')), true, flags: JSON_THROW_ON_ERROR);
$id = $this->postJson('/api/v1/simulation-drafts', ['personal_snapshot' => [], 'economic_snapshot' => $draft], ['Idempotency-Key' => (string) Str::uuid()])->assertCreated()->json('data.id');
$recovered = $this->getJson('/api/v1/simulation-drafts/'.$id)->assertOk()->json('data.economic_snapshot');
$this->assertSame($draft['modelo_a_snapshot'], $recovered['modelo_a_snapshot']);
$book = json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:317'];
$this->assertCount(18, $book['result']['rows']);
$this->assertSame('0.00', $book['result']['periods'][0]['fields']['07']);
$this->assertSame('1800.00', $book['result']['periods'][0]['fields']['05']);
$this->assertSame(json_decode($draft['modelo_a_snapshot'], true)['salesOperations']['opportunity:310'], json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:310']);
$this->assertSame(json_decode($draft['modelo_a_snapshot'], true)['salesOperations']['opportunity:309'], json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:309']);
foreach ($book['result']['rows'] as $row) $this->assertSame('0.00', $row['vat']);
if (getenv('IVA_G2H_RECOVERED')) file_put_contents(getenv('IVA_G2H_RECOVERED'), json_encode($recovered, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE));
}
}
@@ -0,0 +1,45 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Tests\TestCase;
final class IvaOnboardSupplyDraftTest extends TestCase
{
use DatabaseTransactions;
public function test_onboard_supplies_recover_with_the_selected_opportunity_and_previous_books(): void
{
$target = DB::selectOne('select current_database() as name,inet_server_port() as port');
$this->assertSame('simulator_fiscal_delta_20261021_test', $target->name);
$this->assertSame(55441, (int) $target->port);
config(['investor-path.enabled' => true, 'suitecrm.enabled' => false]);
$this->actingAs(User::factory()->create(['email_verified_at' => now()]));
$draft = json_decode(file_get_contents(base_path('outputs/iva-l1-g4-supplies-20261024/calculated.json')), true, flags: JSON_THROW_ON_ERROR);
$id = $this->postJson('/api/v1/simulation-drafts', ['personal_snapshot' => [], 'economic_snapshot' => $draft], ['Idempotency-Key' => (string) Str::uuid()])->assertCreated()->json('data.id');
$recovered = $this->getJson('/api/v1/simulation-drafts/'.$id)->assertOk()->json('data.economic_snapshot');
$this->assertSame($draft['modelo_a_snapshot'], $recovered['modelo_a_snapshot']);
$this->assertSame('opportunity:326', $recovered['context_opportunity']);
$this->assertSame('Manica', $recovered['selection_labels']['province_id']);
$store = json_decode($recovered['modelo_a_snapshot'], true, flags: JSON_THROW_ON_ERROR);
$book = $store['salesOperations']['opportunity:326'];
$this->assertSame('opportunity:326', $book['result']['opportunity']);
$this->assertSame('MZN', $book['result']['currency']);
$this->assertSame('2026-12', $book['result']['periods'][0]['period']);
$this->assertSame('400.00', $book['result']['periods'][0]['fields']['05']);
$this->assertCount(4, $book['rows']);
$this->assertSame(['provisions','fuel','beverages','cargo_products'], array_column($book['rows'], 'supplyCategory'));
foreach ($book['result']['rows'] as $row) {
$this->assertSame('05', $row['field']);
$this->assertSame('0.00', $row['vat']);
}
$frozen = json_decode(file_get_contents(base_path('tests/frontend/fixtures/iva-g4c-inputs.json')), true, flags: JSON_THROW_ON_ERROR);
foreach (json_decode($frozen['modelo_a_snapshot'], true, flags: JSON_THROW_ON_ERROR)['salesOperations'] as $context => $original) {
$this->assertSame($original, $store['salesOperations'][$context]);
}
file_put_contents(base_path('outputs/iva-l1-g4-supplies-20261024/recovered.json'), json_encode($recovered, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE));
}
}
+47
View File
@@ -0,0 +1,47 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Tests\TestCase;
final class IvaOperationsDraftTest extends TestCase
{
use DatabaseTransactions;
public function test_l1_ui_payload_round_trips_without_duplicate_drafts_or_new_rules_and_other_owner_cannot_read(): void
{
$identity = DB::selectOne('select current_database() as name,inet_server_port() as port');
$this->assertSame('simulator_fiscal_delta_20261021_test', $identity->name);
$this->assertSame(55441, (int) $identity->port);
config(['investor-path.enabled' => true, 'suitecrm.enabled' => false]);
$fingerprint = DB::selectOne("select md5(string_agg(row_to_json(r)::text,E'\\n' order by id)) as hash from simulation_tax_rule_versions r")->hash;
$this->actingAs(User::factory()->create(['email_verified_at' => now()]));
$path = getenv('IVA_L1_UI_INPUT') ?: base_path('tests/frontend/fixtures/iva-operations.json');
$draft = json_decode(file_get_contents($path), true, flags: JSON_THROW_ON_ERROR);
$draft['purpose'] = 'simulate_only';
$key = (string) Str::uuid();
$payload = ['personal_snapshot' => [], 'economic_snapshot' => $draft];
$created = $this->postJson('/api/v1/simulation-drafts', $payload, ['Idempotency-Key' => $key])->assertCreated();
$id = $created->json('data.id');
$retry = $this->postJson('/api/v1/simulation-drafts', $payload, ['Idempotency-Key' => $key]);
$this->assertSame($id, $retry->json('data.id'));
$saved = $this->getJson('/api/v1/simulation-drafts/'.$id)->assertOk();
$economic = $saved->json('data.economic_snapshot');
$this->assertSame($draft['modelo_a_snapshot'], $economic['modelo_a_snapshot']);
$this->assertSame($draft['context_opportunity'], $economic['context_opportunity']);
$store = json_decode($economic['modelo_a_snapshot'], true, flags: JSON_THROW_ON_ERROR);
$book = $store['salesOperations'][$draft['context_opportunity']];
$this->assertSame('iva-operations-l1/1', $book['result']['version']);
$this->assertCount(12, $book['result']['rows']);
$this->assertSame('160.00', $book['result']['rows'][0]['vat']);
$this->assertNull($book['result']['rows'][10]['vat']);
if (getenv('IVA_L1_RECOVERED_OUT')) file_put_contents(getenv('IVA_L1_RECOVERED_OUT'), json_encode($economic, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE));
$this->actingAs(User::factory()->create(['email_verified_at' => now()]));
$this->getJson('/api/v1/simulation-drafts/'.$id)->assertNotFound();
$this->assertSame($fingerprint, DB::selectOne("select md5(string_agg(row_to_json(r)::text,E'\\n' order by id)) as hash from simulation_tax_rule_versions r")->hash);
}
}
@@ -0,0 +1,43 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Tests\TestCase;
final class IvaPharmaInputsDraftTest extends TestCase
{
use DatabaseTransactions;
public function test_selected_annex_rows_round_trip_with_their_own_opportunity(): void
{
$target = DB::selectOne('select current_database() as name,inet_server_port() as port');
$this->assertSame('simulator_fiscal_delta_20261021_test', $target->name);
$this->assertSame(55441, (int) $target->port);
config(['investor-path.enabled' => true, 'suitecrm.enabled' => false]);
$this->actingAs(User::factory()->create(['email_verified_at' => now()]));
$draft = json_decode(file_get_contents(getenv('IVA_G2K_INPUT') ?: base_path('outputs/iva-l1-g2-pharma-inputs-20261024/calculated.json')), true, flags: JSON_THROW_ON_ERROR);
$id = $this->postJson('/api/v1/simulation-drafts', ['personal_snapshot' => [], 'economic_snapshot' => $draft], ['Idempotency-Key' => (string) Str::uuid()])->assertCreated()->json('data.id');
$recovered = $this->getJson('/api/v1/simulation-drafts/'.$id)->assertOk()->json('data.economic_snapshot');
$this->assertSame($draft['modelo_a_snapshot'], $recovered['modelo_a_snapshot']);
$store = json_decode($recovered['modelo_a_snapshot'], true);
$book = $store['salesOperations']['opportunity:320'];
$this->assertSame('opportunity:320', $book['result']['opportunity']);
$this->assertSame('MZN', $book['result']['currency']);
$this->assertSame('2026-12', $book['result']['periods'][0]['period']);
$this->assertCount(5, $book['result']['rows']);
$this->assertSame('500.00', $book['result']['periods'][0]['fields']['07']);
$this->assertSame('0.00', $book['result']['periods'][0]['fields']['05']);
$this->assertNotSame($book['rows'][1]['pharmaAnnexItem'], $book['rows'][2]['pharmaAnnexItem']);
$this->assertStringContainsString('2912.19.00', $book['result']['rows'][1]['source']);
$this->assertStringContainsString('2912.19.00', $book['result']['rows'][2]['source']);
$this->assertStringContainsString('2935.', $book['result']['rows'][3]['source']);
$this->assertStringContainsString('PDF16', $book['result']['rows'][4]['source']);
$original = json_decode(file_get_contents(base_path('tests/frontend/fixtures/iva-fundraising.json')), true, flags: JSON_THROW_ON_ERROR);
foreach (json_decode($original['modelo_a_snapshot'], true)['salesOperations'] as $key => $value) {
$this->assertSame($value, $store['salesOperations'][$key]);
}
if (getenv('IVA_G2K_RECOVERED')) file_put_contents(getenv('IVA_G2K_RECOVERED'), json_encode($recovered, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE));
}
}
@@ -0,0 +1,34 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Tests\TestCase;
final class IvaProductionCalendarDraftTest extends TestCase
{
use DatabaseTransactions;
public function test_calendar_delta_round_trips_without_replacing_previous_result(): void
{
$target = DB::selectOne('select current_database() as name,inet_server_port() as port');
$this->assertSame('simulator_fiscal_delta_20261021_test', $target->name);
$this->assertSame(55441, (int) $target->port);
config(['investor-path.enabled' => true, 'suitecrm.enabled' => false]);
$this->actingAs(User::factory()->create(['email_verified_at' => now()]));
$draft = json_decode(file_get_contents(base_path('outputs/iva-l1-g2-production-20261024/calendar-calculated.json')), true, flags: JSON_THROW_ON_ERROR);
$id = $this->postJson('/api/v1/simulation-drafts', ['personal_snapshot' => [], 'economic_snapshot' => $draft], ['Idempotency-Key' => (string) Str::uuid()])->assertCreated()->json('data.id');
$recovered = $this->getJson('/api/v1/simulation-drafts/'.$id)->assertOk()->json('data.economic_snapshot');
$this->assertSame($draft['modelo_a_snapshot'], $recovered['modelo_a_snapshot']);
$book = json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:318'];
$this->assertSame('2020-02-29', $book['rows'][2]['taxOption']['startupDate']);
$this->assertStringContainsString('24 horas de 2025-02-28', $book['result']['rows'][2]['reason']);
$this->assertStringContainsString('production-option/2', $book['result']['rows'][2]['reason']);
$this->assertSame('48.00', $book['result']['periods'][0]['fields']['02']);
$original = json_decode(file_get_contents(base_path('tests/frontend/fixtures/iva-production.json')), true, flags: JSON_THROW_ON_ERROR);
$old = json_decode($original['modelo_a_snapshot'], true)['salesOperations']['opportunity:318']['result'];
$this->assertSame($old, $book['history'][array_key_last($book['history'])]);
file_put_contents(base_path('outputs/iva-l1-g2-production-20261024/calendar-recovered.json'), json_encode($recovered, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE));
}
}
+36
View File
@@ -0,0 +1,36 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Tests\TestCase;
final class IvaProductionDraftTest extends TestCase
{
use DatabaseTransactions;
public function test_production_context_preserves_accepted_opportunities(): void
{
$target = DB::selectOne('select current_database() as name,inet_server_port() as port');
$this->assertSame('simulator_fiscal_delta_20261021_test', $target->name);
$this->assertSame(55441, (int) $target->port);
config(['investor-path.enabled' => true, 'suitecrm.enabled' => false]);
$this->actingAs(User::factory()->create(['email_verified_at' => now()]));
$draft = json_decode(file_get_contents(getenv('IVA_G2I_INPUT') ?: base_path('outputs/iva-l1-g2-production-20261024/calculated.json')), true, flags: JSON_THROW_ON_ERROR);
$id = $this->postJson('/api/v1/simulation-drafts', ['personal_snapshot' => [], 'economic_snapshot' => $draft], ['Idempotency-Key' => (string) Str::uuid()])->assertCreated()->json('data.id');
$recovered = $this->getJson('/api/v1/simulation-drafts/'.$id)->assertOk()->json('data.economic_snapshot');
$this->assertSame($draft['modelo_a_snapshot'], $recovered['modelo_a_snapshot']);
$book = json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:318'];
$this->assertCount(7, $book['result']['rows']);
$this->assertSame('300.00', $book['result']['periods'][0]['fields']['07']);
$this->assertSame('100.00', $book['result']['periods'][0]['fields']['05']);
$this->assertSame(json_decode($draft['modelo_a_snapshot'], true)['salesOperations']['opportunity:310'], json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:310']);
$this->assertSame(json_decode($draft['modelo_a_snapshot'], true)['salesOperations']['opportunity:309'], json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:309']);
$this->assertSame('300.00', $book['result']['periods'][0]['fields']['01']);
$this->assertSame('48.00', $book['result']['periods'][0]['fields']['02']);
$this->assertSame('2024-12-15', $book['rows'][2]['taxOption']['declarationDate']);
$this->assertSame('2026-10-15', $book['rows'][2]['taxOption']['operationDate']);
if (getenv('IVA_G2I_RECOVERED')) file_put_contents(getenv('IVA_G2I_RECOVERED'), json_encode($recovered, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE));
}
}
@@ -0,0 +1,32 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Tests\TestCase;
final class IvaPublicationsDraftTest extends TestCase
{
use DatabaseTransactions;
public function test_publications_context_preserves_accepted_opportunities(): void
{
$target = DB::selectOne('select current_database() as name,inet_server_port() as port');
$this->assertSame('simulator_fiscal_delta_20261021_test', $target->name);
$this->assertSame(55441, (int) $target->port);
config(['investor-path.enabled' => true, 'suitecrm.enabled' => false]);
$this->actingAs(User::factory()->create(['email_verified_at' => now()]));
$draft = json_decode(file_get_contents(getenv('IVA_G2D_INPUT') ?: base_path('outputs/iva-l1-g2-publications-20261024/calculated.json')), true, flags: JSON_THROW_ON_ERROR);
$id = $this->postJson('/api/v1/simulation-drafts', ['personal_snapshot' => [], 'economic_snapshot' => $draft], ['Idempotency-Key' => (string) Str::uuid()])->assertCreated()->json('data.id');
$recovered = $this->getJson('/api/v1/simulation-drafts/'.$id)->assertOk()->json('data.economic_snapshot');
$this->assertSame($draft['modelo_a_snapshot'], $recovered['modelo_a_snapshot']);
$book = json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:313'];
$this->assertCount(2, $book['result']['rows']);
$this->assertSame('200.00', $book['result']['periods'][0]['fields']['07']);
$this->assertSame(json_decode($draft['modelo_a_snapshot'], true)['salesOperations']['opportunity:310'], json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:310']);
$this->assertSame(json_decode($draft['modelo_a_snapshot'], true)['salesOperations']['opportunity:309'], json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:309']);
foreach ($book['result']['rows'] as $row) $this->assertSame('0.00', $row['vat']);
if (getenv('IVA_G2D_RECOVERED')) file_put_contents(getenv('IVA_G2D_RECOVERED'), json_encode($recovered, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE));
}
}
+38
View File
@@ -0,0 +1,38 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Tests\TestCase;
final class IvaRationalDraftTest extends TestCase
{
use DatabaseTransactions;
public function test_periodic_results_and_accepted_first_opportunity_round_trip_exactly(): void
{
$identity = DB::selectOne('select current_database() as name,inet_server_port() as port');
$this->assertSame('simulator_fiscal_delta_20261021_test', $identity->name);
$this->assertSame(55441, (int) $identity->port);
config(['investor-path.enabled' => true, 'suitecrm.enabled' => false]);
$this->actingAs(User::factory()->create(['email_verified_at' => now()]));
$path = getenv('IVA_RATIONAL_INPUT') ?: base_path('tests/frontend/fixtures/iva-rational.json');
$draft = json_decode(file_get_contents($path), true, flags: JSON_THROW_ON_ERROR);
$store = json_decode($draft['modelo_a_snapshot'], true, flags: JSON_THROW_ON_ERROR);
$first = $store['salesOperations']['opportunity:309'];
$id = $this->postJson('/api/v1/simulation-drafts', ['personal_snapshot' => [], 'economic_snapshot' => $draft], ['Idempotency-Key' => (string) Str::uuid()])->assertCreated()->json('data.id');
$economic = $this->getJson('/api/v1/simulation-drafts/'.$id)->assertOk()->json('data.economic_snapshot');
$this->assertSame($draft['modelo_a_snapshot'], $economic['modelo_a_snapshot']);
$saved = json_decode($economic['modelo_a_snapshot'], true, flags: JSON_THROW_ON_ERROR);
$this->assertSame($first, $saved['salesOperations']['opportunity:309']);
$second = $saved['salesOperations']['opportunity:310']['result'];
$this->assertSame('iva-operations-l1/2', $second['version']);
$this->assertSame(['numerator' => '20', 'denominator' => '21'], $second['rows'][0]['exact']['net']);
$this->assertSame(['numerator' => '1', 'denominator' => '21'], $second['rows'][0]['exact']['vat']);
$this->assertSame('0.047619', $second['rows'][0]['vat']);
if (getenv('IVA_RATIONAL_RECOVERED')) file_put_contents(getenv('IVA_RATIONAL_RECOVERED'), json_encode($economic, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE));
}
}
@@ -0,0 +1,30 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Tests\TestCase;
final class IvaServicesGroupDraftTest extends TestCase
{
use DatabaseTransactions;
public function test_services_group_round_trips_with_conditions_and_source(): void
{
$target = DB::selectOne('select current_database() as name,inet_server_port() as port');
$this->assertSame('simulator_fiscal_delta_20261021_test', $target->name);
$this->assertSame(55441, (int) $target->port);
config(['investor-path.enabled' => true, 'suitecrm.enabled' => false]);
$this->actingAs(User::factory()->create(['email_verified_at' => now()]));
$draft = json_decode(file_get_contents(getenv('IVA_G1_INPUT') ?: base_path('outputs/iva-l1-groups-20261024/calculated.json')), true, flags: JSON_THROW_ON_ERROR);
$id = $this->postJson('/api/v1/simulation-drafts', ['personal_snapshot' => [], 'economic_snapshot' => $draft], ['Idempotency-Key' => (string) Str::uuid()])->assertCreated()->json('data.id');
$recovered = $this->getJson('/api/v1/simulation-drafts/'.$id)->assertOk()->json('data.economic_snapshot');
$this->assertSame($draft['modelo_a_snapshot'], $recovered['modelo_a_snapshot']);
$book = json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:310'];
$this->assertCount(4, $book['result']['rows']);
$this->assertSame('400.00', $book['result']['periods'][0]['fields']['07']);
foreach ($book['result']['rows'] as $row) $this->assertSame('0.00', $row['vat']);
if (getenv('IVA_G1_RECOVERED')) file_put_contents(getenv('IVA_G1_RECOVERED'), json_encode($recovered, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE));
}
}
@@ -0,0 +1,33 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Tests\TestCase;
final class IvaServicesNatureDraftTest extends TestCase
{
use DatabaseTransactions;
public function test_services_context_preserves_accepted_opportunities(): void
{
$target = DB::selectOne('select current_database() as name,inet_server_port() as port');
$this->assertSame('simulator_fiscal_delta_20261021_test', $target->name);
$this->assertSame(55441, (int) $target->port);
config(['investor-path.enabled' => true, 'suitecrm.enabled' => false]);
$this->actingAs(User::factory()->create(['email_verified_at' => now()]));
$draft = json_decode(file_get_contents(getenv('IVA_G2F_INPUT') ?: base_path('outputs/iva-l1-g2-services-20261024/calculated.json')), true, flags: JSON_THROW_ON_ERROR);
$id = $this->postJson('/api/v1/simulation-drafts', ['personal_snapshot' => [], 'economic_snapshot' => $draft], ['Idempotency-Key' => (string) Str::uuid()])->assertCreated()->json('data.id');
$recovered = $this->getJson('/api/v1/simulation-drafts/'.$id)->assertOk()->json('data.economic_snapshot');
$this->assertSame($draft['modelo_a_snapshot'], $recovered['modelo_a_snapshot']);
$book = json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:315'];
$this->assertCount(3, $book['result']['rows']);
$this->assertSame('300.00', $book['result']['periods'][0]['fields']['07']);
$this->assertSame('0.00', $book['result']['periods'][0]['fields']['05']);
$this->assertSame(json_decode($draft['modelo_a_snapshot'], true)['salesOperations']['opportunity:310'], json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:310']);
$this->assertSame(json_decode($draft['modelo_a_snapshot'], true)['salesOperations']['opportunity:309'], json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:309']);
foreach ($book['result']['rows'] as $row) $this->assertSame('0.00', $row['vat']);
if (getenv('IVA_G2F_RECOVERED')) file_put_contents(getenv('IVA_G2F_RECOVERED'), json_encode($recovered, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE));
}
}
+32
View File
@@ -0,0 +1,32 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Tests\TestCase;
final class IvaSocialDraftTest extends TestCase
{
use DatabaseTransactions;
public function test_social_context_preserves_both_accepted_opportunities(): void
{
$target = DB::selectOne('select current_database() as name,inet_server_port() as port');
$this->assertSame('simulator_fiscal_delta_20261021_test', $target->name);
$this->assertSame(55441, (int) $target->port);
config(['investor-path.enabled' => true, 'suitecrm.enabled' => false]);
$this->actingAs(User::factory()->create(['email_verified_at' => now()]));
$draft = json_decode(file_get_contents(getenv('IVA_G2B_INPUT') ?: base_path('outputs/iva-l1-g2-social-20261024/calculated.json')), true, flags: JSON_THROW_ON_ERROR);
$id = $this->postJson('/api/v1/simulation-drafts', ['personal_snapshot' => [], 'economic_snapshot' => $draft], ['Idempotency-Key' => (string) Str::uuid()])->assertCreated()->json('data.id');
$recovered = $this->getJson('/api/v1/simulation-drafts/'.$id)->assertOk()->json('data.economic_snapshot');
$this->assertSame($draft['modelo_a_snapshot'], $recovered['modelo_a_snapshot']);
$book = json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:311'];
$this->assertCount(6, $book['result']['rows']);
$this->assertSame('600.00', $book['result']['periods'][0]['fields']['07']);
$this->assertSame(json_decode($draft['modelo_a_snapshot'], true)['salesOperations']['opportunity:310'], json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:310']);
$this->assertSame(json_decode($draft['modelo_a_snapshot'], true)['salesOperations']['opportunity:309'], json_decode($recovered['modelo_a_snapshot'], true)['salesOperations']['opportunity:309']);
foreach ($book['result']['rows'] as $row) $this->assertSame('0.00', $row['vat']);
if (getenv('IVA_G2B_RECOVERED')) file_put_contents(getenv('IVA_G2B_RECOVERED'), json_encode($recovered, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE));
}
}
@@ -0,0 +1,52 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Tests\TestCase;
final class IvaTemporaryBenefitDraftTest extends TestCase
{
use DatabaseTransactions;
public function test_cessation_and_explicit_continuations_recover_with_their_opportunity_and_history(): void
{
$target = DB::selectOne('select current_database() as name,inet_server_port() as port');
$this->assertSame('simulator_fiscal_delta_20261021_test', $target->name);
$this->assertSame(55441, (int) $target->port);
config(['investor-path.enabled' => true, 'suitecrm.enabled' => false]);
$this->actingAs(User::factory()->create(['email_verified_at' => now()]));
$draft = json_decode(file_get_contents(base_path('outputs/iva-l1-g3-temporary-20261024/calculated.json')), true, flags: JSON_THROW_ON_ERROR);
$id = $this->postJson('/api/v1/simulation-drafts', ['personal_snapshot' => [], 'economic_snapshot' => $draft], ['Idempotency-Key' => (string) Str::uuid()])->assertCreated()->json('data.id');
$recovered = $this->getJson('/api/v1/simulation-drafts/'.$id)->assertOk()->json('data.economic_snapshot');
$this->assertSame($draft['modelo_a_snapshot'], $recovered['modelo_a_snapshot']);
$this->assertSame('opportunity:322', $recovered['context_opportunity']);
$this->assertSame('Manica', $recovered['selection_labels']['province_id']);
$store = json_decode($recovered['modelo_a_snapshot'], true, flags: JSON_THROW_ON_ERROR);
$book = $store['salesOperations']['opportunity:322'];
$this->assertSame('opportunity:322', $book['result']['opportunity']);
$this->assertSame('MZN', $book['result']['currency']);
$this->assertSame('2026-10', $book['result']['periods'][0]['period']);
$this->assertSame('700.00', $book['result']['periods'][0]['fields']['01']);
$this->assertSame('112.00', $book['result']['periods'][0]['fields']['02']);
$this->assertSame('100.00', $book['result']['periods'][0]['fields']['05']);
$this->assertCount(8, $book['rows']);
$this->assertSame('116', $book['rows'][0]['amount']);
$this->assertSame('included', $book['rows'][0]['basis']);
$this->assertSame('temporary_sugar', $book['rows'][0]['temporaryBenefitOrigin']);
$this->assertSame('temporary_solar_inputs', $book['rows'][6]['temporaryBenefitOrigin']);
$this->assertSame('production_agriculture', $book['rows'][7]['treatment']);
$this->assertStringContainsString('P045', $book['rows'][6]['source']);
$this->assertCount(7, $book['history'][0]['rows']);
$this->assertNull($book['history'][0]['periods'][0]['fields']['01']);
$this->assertStringContainsString('terminou em31/12/2025', $book['history'][0]['rows'][0]['reason']);
$frozen = json_decode(file_get_contents(base_path('tests/frontend/fixtures/iva-annex-i-inputs.json')), true, flags: JSON_THROW_ON_ERROR);
foreach (json_decode($frozen['modelo_a_snapshot'], true, flags: JSON_THROW_ON_ERROR)['salesOperations'] as $context => $original) {
$this->assertSame($original, $store['salesOperations'][$context]);
}
file_put_contents(base_path('outputs/iva-l1-g3-temporary-20261024/recovered.json'), json_encode($recovered, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE));
}
}
@@ -0,0 +1,69 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Tests\TestCase;
final class ModeloAAcquisitionsDraftTest extends TestCase
{
use DatabaseTransactions;
public function test_ui_calculated_payload_is_saved_recovered_and_used_as_the_report_source(): void
{
$identity = DB::selectOne('select current_database() as name,inet_server_port() as port');
$this->assertSame('simulator_fiscal_delta_20261021_test', $identity->name);
$this->assertSame(55441, (int) $identity->port);
$this->actingAs(User::factory()->create(['email_verified_at' => now()]));
$path = getenv('IVA_ACQUISITION_UI_INPUT') ?: base_path('tests/frontend/fixtures/modelo-a-acquisitions.json');
$draft = json_decode(file_get_contents($path), true, flags: JSON_THROW_ON_ERROR);
$draft['purpose'] = 'simulate_only';
$created = $this->postJson('/api/v1/simulation-drafts', ['personal_snapshot' => [], 'economic_snapshot' => $draft], ['Idempotency-Key' => (string) Str::uuid()])->assertCreated();
$recovered = $this->getJson('/api/v1/simulation-drafts/'.$created->json('data.id'))->assertOk()->json('data.economic_snapshot');
$this->assertSame($draft['modelo_a_snapshot'], $recovered['modelo_a_snapshot']);
$this->assertSame($draft['context_opportunity'], $recovered['context_opportunity']);
if (getenv('IVA_ACQUISITION_UI_RECOVERED_OUT')) file_put_contents(getenv('IVA_ACQUISITION_UI_RECOVERED_OUT'), json_encode($recovered, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE));
}
public function test_calculated_acquisitions_round_trip_in_private_draft_and_other_owner_cannot_read(): void
{
$identity = DB::selectOne('select current_database() as name,inet_server_port() as port');
$this->assertSame('simulator_fiscal_delta_20261021_test', $identity->name);
$this->assertSame(55441, (int) $identity->port);
config(['investor-path.enabled' => true, 'suitecrm.enabled' => false]);
$fingerprint = DB::selectOne("select md5(string_agg(row_to_json(r)::text,E'\\n' order by id)) as hash from simulation_tax_rule_versions r")->hash;
$actor = User::factory()->create(['email_verified_at' => now()]);
$this->actingAs($actor);
$draft = json_decode(file_get_contents(base_path('tests/frontend/fixtures/modelo-a-acquisitions.json')), true, flags: JSON_THROW_ON_ERROR);
$draft['purpose'] = 'simulate_only';
$created = $this->postJson('/api/v1/simulation-drafts', ['personal_snapshot' => [], 'economic_snapshot' => $draft], ['Idempotency-Key' => (string) Str::uuid()])->assertCreated();
$id = $created->json('data.id');
$this->assertNotEmpty($id);
$saved = $this->getJson('/api/v1/simulation-drafts/'.$id)->assertOk();
$economic = $saved->json('data.economic_snapshot');
$this->assertSame($draft['modelo_a_snapshot'], $economic['modelo_a_snapshot']);
$store = json_decode($economic['modelo_a_snapshot'], true, flags: JSON_THROW_ON_ERROR);
$first = $store['books']['opportunity:309'];
$this->assertSame('144.0048', $first['result']['periods'][0]['fields'][17]);
$store['books']['opportunity:310'] = $first;
$store['books']['opportunity:310']['rows'][0]['net'] = '200';
$store['books']['opportunity:310']['rows'][0]['vat'] = '32';
$economic['context_opportunity'] = 'opportunity:310';
$economic['modelo_a_snapshot'] = json_encode($store, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE);
$this->putJson('/api/v1/simulation-drafts/'.$id, ['personal_snapshot' => [], 'economic_snapshot' => $economic], ['If-Match' => $saved->headers->get('ETag')])->assertOk();
$recovered = $this->getJson('/api/v1/simulation-drafts/'.$id)->assertOk()->json('data.economic_snapshot');
$this->assertSame($economic['modelo_a_snapshot'], $recovered['modelo_a_snapshot']);
$this->assertSame($first, json_decode($recovered['modelo_a_snapshot'], true)['books']['opportunity:309']);
if (getenv('IVA_ACQUISITION_RECOVERED_OUT')) {
// The original calculated opportunity, recovered through the real private API, is the report source.
$economic['context_opportunity'] = 'opportunity:309';
file_put_contents(getenv('IVA_ACQUISITION_RECOVERED_OUT'), json_encode($economic, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE));
}
$this->actingAs(User::factory()->create(['email_verified_at' => now()]));
$this->getJson('/api/v1/simulation-drafts/'.$id)->assertNotFound();
$this->assertSame($fingerprint, DB::selectOne("select md5(string_agg(row_to_json(r)::text,E'\\n' order by id)) as hash from simulation_tax_rule_versions r")->hash);
}
}
@@ -0,0 +1,67 @@
<?php
namespace Tests\Feature;
use App\Jobs\RunSimulation;
use App\Models\Simulation;
use App\Models\SimulationTaxRuleVersion;
use App\Models\User;
use App\Services\SimulationExecution;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Queue;
use Illuminate\Support\Str;
use Tests\TestCase;
final class SimulatorClosureRecoveryTest extends TestCase
{
use DatabaseTransactions;
public function test_existing_monthly_admission_can_be_read_and_finished_when_new_admissions_are_off(): void
{
$identity = DB::selectOne('select current_database() as name,inet_server_port() as port');
$this->assertSame('simulator_fiscal_delta_20261021_test', $identity->name);
$this->assertSame(55441, (int) $identity->port);
Queue::fake();
// Reuse the existing isolated synthetic rule. No create/publish/suspend of any rule.
$rule = SimulationTaxRuleVersion::findOrFail('01a15e50-7972-72e0-8991-82ca28df9b49');
$before = $this->ruleFingerprint();
config(['simulation-fiscal-consumer.enabled' => true, 'simulation-fiscal-consumer.rule_id' => $rule->id, 'simulation-fiscal-consumer.rule_version' => $rule->rule_version]);
$actor = User::factory()->create(['email_verified_at' => now()]);
$input = ['scenario_kind' => 'fiscal_rule_published', 'currency' => 'MZN', 'scope_declared' => true, 'sales_vat_basis' => 'net', 'monthly_sales' => [['date' => '2026-01-01', 'amount' => '1000.03']]];
$id = $this->actingAs($actor)->postJson('/api/v1/simulations', $input, ['Idempotency-Key' => (string) Str::uuid()])->assertAccepted()->json('data.id');
$count = Simulation::count();
config(['simulation-fiscal-consumer.enabled' => false]);
$this->getJson('/api/v1/fiscal-consumer')->assertOk()->assertJsonPath('data.enabled', false);
$this->getJson('/api/v1/simulations/'.$id)->assertOk()->assertJsonPath('data.id', $id)->assertJsonPath('data.status', 'queued');
$this->postJson('/api/v1/simulations', $input, ['Idempotency-Key' => (string) Str::uuid()])->assertStatus(503);
(new RunSimulation($id, $actor->id, null))->handle(app(SimulationExecution::class));
$this->getJson('/api/v1/simulations/'.$id)->assertOk()->assertJsonPath('data.id', $id)->assertJsonPath('data.status', 'completed');
$this->assertSame($count, Simulation::count());
$this->actingAs(User::factory()->create(['email_verified_at' => now()]))->getJson('/api/v1/simulations/'.$id)->assertNotFound();
$this->assertSame($before, $this->ruleFingerprint());
}
private function ruleFingerprint(): string
{
return DB::selectOne("select md5(string_agg(row_to_json(r)::text,E'\\n' order by id)) as hash from simulation_tax_rule_versions r")->hash;
}
public function test_cashflow_original_currency_and_amounts_round_trip_in_the_existing_private_draft(): void
{
$identity = DB::selectOne('select current_database() as name,inet_server_port() as port');
$this->assertSame('simulator_fiscal_delta_20261021_test', $identity->name);
$this->assertSame(55441, (int) $identity->port);
config(['investor-path.enabled' => true, 'suitecrm.enabled' => false]);
$actor = User::factory()->create(['email_verified_at' => now()]);
$this->actingAs($actor);
$id = $this->postJson('/investimentos', ['title' => 'SYNTHETIC QA — moeda de tesouraria', 'client_key' => (string) Str::uuid(), 'reuse_consent' => true])->assertCreated()->json('id');
$snapshot = json_encode(['version' => 2, 'currency' => 'USD', 'taxMode' => 'fixed', 'inputs' => ['monthlyRevenue' => '123', 'monthlyTaxSchedule' => ['0', '', '0']]], JSON_THROW_ON_ERROR);
$this->postJson('/api/v1/simulation-drafts', ['context' => $id, 'personal_snapshot' => [], 'economic_snapshot' => ['purpose' => 'simulate_only', 'project_title' => 'SYNTHETIC QA — moeda', 'currency' => 'MZN', 'cashflow_snapshot' => $snapshot]], ['Idempotency-Key' => (string) Str::uuid()])->assertCreated();
$this->actingAs($actor->fresh());
$saved = $this->getJson('/api/v1/simulation-drafts/current?context='.$id)->assertOk()->json('data.economic_snapshot');
$this->assertSame('MZN', $saved['currency']);
$this->assertSame($snapshot, $saved['cashflow_snapshot']);
$this->assertSame('USD', json_decode($saved['cashflow_snapshot'], true)['currency']);
}
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,9 @@
import fs from 'node:fs';
import {newSalesOperation,recordSales,saveSalesBook} from '../../../resources/js/lib/iva-operations.ts';
export function l1DeltaFixture(){
const draft=JSON.parse(fs.readFileSync(new URL('iva-operations.json',import.meta.url),'utf8'));
draft.context_opportunity='opportunity:310';draft.project_title='SYNTHETIC QA — L1 precisão racional';
const context=JSON.parse(draft.context_applicability_snapshot);context.opportunity_choices.push({opportunity:{key:'opportunity:310',title:'SYNTHETIC QA — segunda oportunidade racional'}});draft.context_applicability_snapshot=JSON.stringify(context);
let book={currency:'MZN',rows:['1','100','0.02'].map((amount,i)=>({...newSalesOperation(`rational-${i}`,'2026-01','MZN'),amount,description:`SYNTHETIC QA periódico ${i+1}`,establishment:'SYNTHETIC QA estabelecimento',basis:'included',treatment:'private_health',confirmed:[0,1],evidence:'SYNTHETIC QA — pressupostos já delimitados do tratamento, preço incluído'})),periods:[{period:'2026-01',complete:true}]};
book=recordSales(draft,book);draft.modelo_a_snapshot=saveSalesBook(draft,book);return {draft,book};
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,15 @@
{
"project_title": "SYNTHETIC QA — aquisições e apuramento parcial Modelo A",
"currency": "MZN",
"context_opportunity": "opportunity:309",
"context_applicability_snapshot": "{\"version\":1,\"context_revision\":13,\"consumer_opportunity\":\"opportunity:309\",\"opportunity_choices\":[{\"opportunity\":{\"key\":\"opportunity:309\",\"title\":\"SYNTHETIC QA — segunda oportunidade Manica\"}}],\"path\":{\"steps\":[]}}",
"business_plan_snapshot": "{\"version\":17,\"plan\":{\"openingCash\":\"0\",\"monthlyCollections\":\"0\",\"monthlyVariableCostPayments\":\"0\",\"monthlyInventoryPurchases\":\"0\",\"monthlyOperatingExpenses\":\"0\",\"monthlyOperatingPayments\":\"0\",\"monthlyPayrollExpense\":\"0\",\"monthlyPayrollPayments\":\"0\",\"assetInvestment\":\"0\",\"inventory\":\"0\",\"receivables\":\"0\",\"payables\":\"0\",\"equity\":\"0\",\"shareholderLoans\":\"0\",\"bankLoanProceeds\":\"0\",\"grants\":\"0\",\"assetDepreciation\":\"0\",\"monthlyInterestExpense\":\"0\",\"monthlyInterestPayment\":\"0\",\"monthlyPrincipalRepayment\":\"0\",\"currency\":\"MZN\",\"periods\":4,\"depreciationLifeMonths\":60,\"products\":[{\"label\":\"SYNTHETIC QA\",\"monthlyUnits\":\"1\",\"unitPrice\":\"1000.03\",\"unitVariableCost\":\"0\",\"monthlyUnitsByPeriod\":[\"1\",\"2\",\"0\",\"\"]}],\"inventoryPurchaseLeadMonths\":0,\"inventoryPurchaseSchedule\":null,\"useInventoryPurchaseSchedule\":false,\"useProductInventorySchedule\":false,\"useSupplierPaymentTerms\":false,\"monthlyVariableCostPaymentsByPeriod\":null,\"salesCollectionLagMonths\":null,\"salesCollectionPercent\":\"100\",\"openingReceivablesCollectionMonth\":null,\"openingReceivablesCollectionPercent\":\"100\",\"openingReceivablesInstallments\":[],\"openingPayablesInstallments\":[],\"salesRecoverySchedule\":[]}}",
"monthly_iva_settings": "{\"start\":\"2026-01\",\"basis\":\"net\",\"declared\":true,\"auto\":false}",
"monthly_iva_snapshot": "{\"input\":{\"scenario_kind\":\"fiscal_rule_published\",\"monthly_sales\":[{\"date\":\"2026-01-01\",\"amount\":\"1000.03\"},{\"date\":\"2026-02-01\",\"amount\":\"2000.06\"},{\"date\":\"2026-03-01\",\"amount\":\"0.00\"},{\"date\":\"2026-04-01\",\"amount\":null}],\"sales_vat_basis\":\"net\",\"currency\":\"MZN\",\"scope_declared\":true},\"execution\":{\"id\":\"06566910-9672-4176-804d-aad8350417cb\",\"status\":\"completed\",\"version_no\":2,\"result_snapshot\":{\"contract_version\":1,\"scenario_kind\":\"fiscal_rule_published\",\"base\":null,\"currency\":\"MZN\",\"indicative_total\":null,\"legal_interpretation\":false,\"formula_version\":\"investmoz.tax.v1\",\"context\":{\"reference_date\":\"2026-01-01\",\"currency\":\"MZN\",\"currency_fraction_digits\":2,\"scenario_id\":\"61000100-0000-4000-8000-000000000099\",\"scenario_version\":1,\"engine_version\":\"fiscal-published-v1\",\"ruleset_version\":\"IVA-GERAL-BASE-LIQUIDA:4\"},\"result\":{\"status\":\"indeterminate\",\"value\":null,\"unit\":\"MZN\",\"explanation\":\"IVA das vendas projectadas; sem apuramento final.\",\"missing_inputs\":[\"monthly_sales\"],\"source_ids\":[\"synthetic-qa-source\"]},\"presentation\":{\"value\":null,\"rounding_applied\":false},\"fiscal_provenance\":{\"rule\":{\"rule_code\":\"IVA-GERAL-BASE-LIQUIDA\",\"rule_version\":4,\"valid_from\":\"2023-01-01\",\"valid_until\":null,\"source_sha256\":\"synthetic-qa-source-hash\",\"source\":{\"diploma\":\"Fonte sintética QA — regra já ensaiada\",\"article\":\"Cópia do snapshot aceite\"}},\"scope_status\":\"user_declared\"},\"monthly_projection\":{\"input\":{\"scenario_kind\":\"fiscal_rule_published\",\"monthly_sales\":[{\"date\":\"2026-01-01\",\"amount\":\"1000.03\"},{\"date\":\"2026-02-01\",\"amount\":\"2000.06\"},{\"date\":\"2026-03-01\",\"amount\":\"0.00\"},{\"date\":\"2026-04-01\",\"amount\":null}],\"sales_vat_basis\":\"net\",\"currency\":\"MZN\",\"scope_declared\":true},\"rows\":[{\"date\":\"2026-01-01\",\"sales_declared\":\"1000.03\",\"net_sales\":\"1000.03\",\"rate\":\"16\",\"vat\":\"160.0048\",\"gross_sales\":\"1160.0348\",\"status\":\"calculated\"},{\"date\":\"2026-02-01\",\"sales_declared\":\"2000.06\",\"net_sales\":\"2000.06\",\"rate\":\"16\",\"vat\":\"320.0096\",\"gross_sales\":\"2320.0696\",\"status\":\"calculated\"},{\"date\":\"2026-03-01\",\"sales_declared\":\"0.00\",\"net_sales\":\"0.00\",\"rate\":\"16\",\"vat\":\"0\",\"gross_sales\":\"0\",\"status\":\"calculated\"},{\"date\":\"2026-04-01\",\"sales_declared\":null,\"net_sales\":null,\"rate\":null,\"vat\":null,\"gross_sales\":null,\"status\":\"missing_sales\"}],\"cash_treatment\":\"IVA separado da tesouraria; não é imposto final a pagar.\"}}}}",
"province_id": "cf5e81f1-ffbc-535d-b1b6-b44b445c4421",
"district_id": "",
"selection_labels": {
"province_id": "Manica"
},
"modelo_a_snapshot": "{\"version\":1,\"books\":{\"opportunity:309\":{\"currency\":\"MZN\",\"taxpayerRegistered\":\"yes\",\"rows\":[{\"id\":\"qa-inventory\",\"field\":\"09\",\"period\":\"2026-01\",\"origin\":\"projected\",\"sourceMonth\":null,\"sourceAmount\":null,\"sourceCurrency\":\"MZN\",\"sourceBasis\":\"\",\"net\":\"100\",\"vat\":\"16\",\"gross\":\"116\",\"documentType\":\"invoice\",\"documentRef\":\"SYNTHETIC QA 001\",\"documentDate\":\"2026-01-10\",\"documentLine\":\"\",\"supplier\":\"SYNTHETIC QA supplier\",\"supplierRegistered\":\"yes\",\"legalDocument\":\"yes\",\"held\":\"yes\",\"domestic\":\"yes\",\"allocation\":\"taxable_only\",\"exclusion\":\"none\",\"integrity\":\"yes\",\"description\":\"SYNTHETIC QA existências\"}],\"periods\":[{\"period\":\"2026-01\",\"complete\":true,\"absent\":[\"03\",\"04\",\"05\",\"06\",\"07\",\"11\",\"12\",\"13\"]},{\"period\":\"2026-02\",\"complete\":true,\"absent\":[\"03\",\"04\",\"05\",\"06\",\"07\",\"11\",\"12\",\"13\"]},{\"period\":\"2026-03\",\"complete\":true,\"absent\":[\"03\",\"04\",\"05\",\"06\",\"07\",\"11\",\"12\",\"13\"]},{\"period\":\"2026-04\",\"complete\":true,\"absent\":[\"03\",\"04\",\"05\",\"06\",\"07\",\"11\",\"12\",\"13\"]}],\"result\":{\"version\":\"modelo-a-internal-acquisitions/1\",\"revision\":1,\"calculatedAt\":\"2026-10-24T12:00:00.000Z\",\"opportunity\":\"opportunity:309\",\"location\":\"Manica\",\"currency\":\"MZN\",\"sourceKey\":\"5009:840f2acff1252a8e\",\"basis\":\"CIVA arts.18(1)(a),18(2) (Lei10/2025),18(3–5),19(1)(a),19(2),20 (Lei22/2022),21(1–3); âmbito interno, afectação exclusiva, mesmo período, sem exclusões ou dedução parcial.\",\"sources\":\"Modelo A DOCX 62c198e9 / v1 63d45fa8; VAT Return.pdf SHA256 9c0b99a810c7db53eb75d63c22ee22fb86a50ba57bd5509041ed80ee10f75741, p.1; CIVA republicado Lei13/2016, PDF14–16; Lei22/2022, art.20; Lei10/2025, arts.18/19, PDF13.\",\"declarations\":{\"taxpayerRegistered\":\"yes\",\"periods\":[{\"period\":\"2026-01\",\"complete\":true,\"absent\":[\"03\",\"04\",\"05\",\"06\",\"07\",\"11\",\"12\",\"13\"]},{\"period\":\"2026-02\",\"complete\":true,\"absent\":[\"03\",\"04\",\"05\",\"06\",\"07\",\"11\",\"12\",\"13\"]},{\"period\":\"2026-03\",\"complete\":true,\"absent\":[\"03\",\"04\",\"05\",\"06\",\"07\",\"11\",\"12\",\"13\"]},{\"period\":\"2026-04\",\"complete\":true,\"absent\":[\"03\",\"04\",\"05\",\"06\",\"07\",\"11\",\"12\",\"13\"]}]},\"rows\":[{\"id\":\"qa-inventory\",\"net\":\"100.00\",\"vat\":\"16.00\",\"gross\":\"116.00\",\"deductible\":\"16.00\",\"reason\":\"Dedução projectada sob pressupostos explícitos; não certifica factura ou declaração.\"}],\"inputs\":[{\"id\":\"qa-inventory\",\"field\":\"09\",\"period\":\"2026-01\",\"origin\":\"projected\",\"sourceMonth\":null,\"sourceAmount\":null,\"sourceCurrency\":\"MZN\",\"sourceBasis\":\"\",\"net\":\"100\",\"vat\":\"16\",\"gross\":\"116\",\"documentType\":\"invoice\",\"documentRef\":\"SYNTHETIC QA 001\",\"documentDate\":\"2026-01-10\",\"documentLine\":\"\",\"supplier\":\"SYNTHETIC QA supplier\",\"supplierRegistered\":\"yes\",\"legalDocument\":\"yes\",\"held\":\"yes\",\"domestic\":\"yes\",\"allocation\":\"taxable_only\",\"exclusion\":\"none\",\"integrity\":\"yes\",\"description\":\"SYNTHETIC QA existências\"}],\"periods\":[{\"period\":\"2026-01\",\"fields\":{\"10\":\"0.00\",\"11\":\"0.00\",\"12\":\"0.00\",\"13\":\"0.00\",\"14\":\"1000.03\",\"15\":\"16.00\",\"16\":\"160.0048\",\"17\":\"144.0048\",\"18\":\"0.00\",\"01\":\"1000.03\",\"02\":\"160.0048\",\"03\":\"0.00\",\"04\":\"0.00\",\"05\":\"0.00\",\"06\":\"0.00\",\"07\":\"0.00\",\"08\":\"0.00\",\"09\":\"16.00\"},\"reasons\":[]},{\"period\":\"2026-02\",\"fields\":{\"10\":\"0.00\",\"11\":\"0.00\",\"12\":\"0.00\",\"13\":\"0.00\",\"14\":\"2000.06\",\"15\":\"0.00\",\"16\":\"320.0096\",\"17\":\"320.0096\",\"18\":\"0.00\",\"01\":\"2000.06\",\"02\":\"320.0096\",\"03\":\"0.00\",\"04\":\"0.00\",\"05\":\"0.00\",\"06\":\"0.00\",\"07\":\"0.00\",\"08\":\"0.00\",\"09\":\"0.00\"},\"reasons\":[]},{\"period\":\"2026-03\",\"fields\":{\"10\":\"0.00\",\"11\":\"0.00\",\"12\":\"0.00\",\"13\":\"0.00\",\"14\":\"0.00\",\"15\":\"0.00\",\"16\":\"0.00\",\"17\":\"0.00\",\"18\":\"0.00\",\"01\":\"0.00\",\"02\":\"0\",\"03\":\"0.00\",\"04\":\"0.00\",\"05\":\"0.00\",\"06\":\"0.00\",\"07\":\"0.00\",\"08\":\"0.00\",\"09\":\"0.00\"},\"reasons\":[]},{\"period\":\"2026-04\",\"fields\":{\"10\":\"0.00\",\"11\":\"0.00\",\"12\":\"0.00\",\"13\":\"0.00\",\"14\":null,\"15\":\"0.00\",\"16\":null,\"17\":null,\"18\":null,\"01\":null,\"02\":null,\"03\":\"0.00\",\"04\":\"0.00\",\"05\":\"0.00\",\"06\":\"0.00\",\"07\":\"0.00\",\"08\":\"0.00\",\"09\":\"0.00\"},\"reasons\":[\"01/02: vendas ou IVA mensal em falta, execução incompleta ou desactualizada.\"]}]}}}}"
}
@@ -0,0 +1,13 @@
import {serializeBusinessPlanSnapshot} from '../../../resources/js/lib/business-financial-plan.ts';
export function closureFixture(status='completed') {
const fields=['openingCash','monthlyCollections','monthlyVariableCostPayments','monthlyInventoryPurchases','monthlyOperatingExpenses','monthlyOperatingPayments','monthlyPayrollExpense','monthlyPayrollPayments','assetInvestment','inventory','receivables','payables','equity','shareholderLoans','bankLoanProceeds','grants','assetDepreciation','monthlyInterestExpense','monthlyInterestPayment','monthlyPrincipalRepayment'];
const plan={...Object.fromEntries(fields.map(k=>[k,'0'])),currency:'MZN',periods:4,depreciationLifeMonths:60,products:[{label:'SYNTHETIC QA',monthlyUnits:'1',unitPrice:'1000.03',unitVariableCost:'0',monthlyUnitsByPeriod:['1','2','0','']}]};
const input={scenario_kind:'fiscal_rule_published',monthly_sales:[{date:'2026-01-01',amount:'1000.03'},{date:'2026-02-01',amount:'2000.06'},{date:'2026-03-01',amount:'0.00'},{date:'2026-04-01',amount:null}],sales_vat_basis:'net',currency:'MZN',scope_declared:true};
// Frozen numbers already accepted in the monthly QA receipt; no tax calculation here.
const rows=[{date:'2026-01-01',sales_declared:'1000.03',net_sales:'1000.03',rate:'16',vat:'160.0048',gross_sales:'1160.0348',status:'calculated'},{date:'2026-02-01',sales_declared:'2000.06',net_sales:'2000.06',rate:'16',vat:'320.0096',gross_sales:'2320.0696',status:'calculated'},{date:'2026-03-01',sales_declared:'0.00',net_sales:'0.00',rate:'16',vat:'0',gross_sales:'0',status:'calculated'},{date:'2026-04-01',sales_declared:null,net_sales:null,rate:null,vat:null,gross_sales:null,status:'missing_sales'}];
const snapshot={contract_version:1,scenario_kind:'fiscal_rule_published',base:null,currency:'MZN',indicative_total:null,legal_interpretation:false,formula_version:'investmoz.tax.v1',context:{reference_date:'2026-01-01',currency:'MZN',currency_fraction_digits:2,scenario_id:'61000100-0000-4000-8000-000000000099',scenario_version:1,engine_version:'fiscal-published-v1',ruleset_version:'IVA-GERAL-BASE-LIQUIDA:4'},result:{status:'indeterminate',value:null,unit:'MZN',explanation:'IVA das vendas projectadas; sem apuramento final.',missing_inputs:['monthly_sales'],source_ids:['synthetic-qa-source']},presentation:{value:null,rounding_applied:false},fiscal_provenance:{rule:{rule_code:'IVA-GERAL-BASE-LIQUIDA',rule_version:4,valid_from:'2023-01-01',valid_until:null,source_sha256:'synthetic-qa-source-hash',source:{diploma:'Fonte sintética QA — regra já ensaiada',article:'Cópia do snapshot aceite'}},scope_status:'user_declared'},monthly_projection:{input,rows,cash_treatment:'IVA separado da tesouraria; não é imposto final a pagar.'}};
const execution={id:'06566910-9672-4176-804d-aad8350417cb',status,version_no:2,result_snapshot:status==='completed'?snapshot:null};
const context={version:1,context_revision:13,consumer_opportunity:'opportunity:309',opportunity_choices:[{opportunity:{key:'opportunity:309',title:'SYNTHETIC QA — segunda oportunidade Manica'}}],path:{steps:[]}};
return {input,snapshot,execution,draft:{project_title:'SYNTHETIC QA — fecho do simulador S1 S2 S3',currency:'MZN',context_opportunity:'opportunity:309',context_applicability_snapshot:JSON.stringify(context),business_plan_snapshot:serializeBusinessPlanSnapshot(plan),monthly_iva_settings:JSON.stringify({start:'2026-01',basis:'net',declared:true,auto:false}),monthly_iva_snapshot:JSON.stringify({input,execution})}};
}
+78
View File
@@ -0,0 +1,78 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import fs from 'node:fs';
import {closureFixture} from './fixtures/simulator-closure-fixture.mjs';
import {acquisitionBook,acquisitionCurrent,acquisitionExcludedFields,acquisitionPlanReferences,acquisitionReportRows,calculateAcquisitions,evaluateAcquisition,newAcquisition,reuseAcquisitions,saveAcquisitionBook} from '../../resources/js/lib/iva-acquisitions.ts';
import {createProjectDossierReport} from '../../resources/js/lib/project-dossier-report.ts';
import {serializeBusinessPlanSnapshot,restoreBusinessPlanSnapshot} from '../../resources/js/lib/business-financial-plan.ts';
export function acquisitionsFixture(){
const draft=closureFixture().draft;
draft.project_title='SYNTHETIC QA — aquisições e apuramento parcial Modelo A';
draft.province_id='cf5e81f1-ffbc-535d-b1b6-b44b445c4421';draft.district_id='';draft.selection_labels={province_id:'Manica'};
const book={currency:'MZN',taxpayerRegistered:'yes',rows:[{...newAcquisition('qa-inventory','2026-01','MZN'),net:'100',vat:'16',gross:'116',documentType:'invoice',documentRef:'SYNTHETIC QA 001',documentDate:'2026-01-10',supplier:'SYNTHETIC QA supplier',supplierRegistered:'yes',legalDocument:'yes',held:'yes',domestic:'yes',allocation:'taxable_only',exclusion:'none',integrity:'yes',description:'SYNTHETIC QA existências'}],periods:['2026-01','2026-02','2026-03','2026-04'].map(period=>({period,complete:true,absent:[...acquisitionExcludedFields]}))};
return {draft,book};
}
test('a recorded purchase does not establish VAT, legal document or deduction',()=>{
const row=newAcquisition('a','2026-01','MZN');row.net='100';
assert.equal(evaluateAcquisition(row,'MZN','yes').deductible,null);
row.vat='16';let r=evaluateAcquisition(row,'MZN','yes');assert.equal(r.gross,'116.00');assert.equal(r.deductible,null);
row.gross='117';assert.match(evaluateAcquisition(row,'MZN','yes').reason,/corresponder/);
});
test('eligibility handles exclusions, mixed use, document, supplier, date and currency without inventing rules',()=>{
const row=acquisitionsFixture().book.rows[0];
assert.equal(evaluateAcquisition(row,'MZN').deductible,null);
assert.equal(evaluateAcquisition(row,'MZN','yes').deductible,'16.00');
for(const patch of [{documentRef:''},{supplierRegistered:''},{held:''},{allocation:'mixed'},{exclusion:'special'},{documentDate:'2026-02-10'},{documentDate:'2026-99-10'},{domestic:'no'},{sourceCurrency:'USD'}]) assert.equal(evaluateAcquisition({...row,...patch},'MZN','yes').deductible,null,JSON.stringify(patch));
for(const patch of [{supplierRegistered:'no'},{allocation:'no_right'},{exclusion:'excluded'},{integrity:'no'}]) assert.equal(evaluateAcquisition({...row,...patch},'MZN','yes').deductible,'0.00');
assert.equal(evaluateAcquisition({...row,origin:'effective'},'MZN','yes').deductible,'16.00');
assert.equal(evaluateAcquisition({...row,net:'100',vat:'0',gross:'100',documentRef:''},'MZN','yes').deductible,'0.00');
});
test('duplicates, ambiguous opportunity and absent declarations are not silently accepted',()=>{
const {draft,book}=acquisitionsFixture();
book.rows.push({...book.rows[0],id:'duplicate'});assert.throws(()=>calculateAcquisitions(draft,book),/repetido/);
assert.throws(()=>acquisitionBook({...draft,context_opportunity:'',context_applicability_snapshot:JSON.stringify({opportunity_choices:[{},{}]})}),/Escolha a oportunidade/);
const missing=acquisitionsFixture();missing.book.periods[0].absent=[];missing.book.result=calculateAcquisitions(missing.draft,missing.book);missing.draft.modelo_a_snapshot=saveAcquisitionBook(missing.draft,missing.book);
assert.match(JSON.stringify(acquisitionReportRows(missing.draft)),/nenhum/);
assert.equal(missing.book.result.periods[0].fields['17'],null);
});
test('08–10, formulas14–18, decimal precision, missing parcels and explicit absence',()=>{
const {draft,book}=acquisitionsFixture();
book.rows.push({...book.rows[0],id:'asset',field:'08',documentLine:'2',net:'200',vat:'32',gross:'232'},{...book.rows[0],id:'service',field:'10',documentLine:'3',net:'50',vat:'8',gross:'58'});
const result=calculateAcquisitions(draft,book);const f=result.periods[0].fields;
assert.equal(f['08'],'32.00');assert.equal(f['09'],'16.00');assert.equal(f['10'],'8.00');assert.equal(f['14'],'1000.03');assert.equal(f['15'],'56.00');assert.equal(f['16'],'160.0048');assert.equal(f['17'],'104.0048');assert.equal(f['18'],'0.00');
assert.equal(result.periods[2].fields['17'],'0.00');assert.equal(result.periods[3].fields['17'],null);
book.periods[0].absent=[];const incomplete=calculateAcquisitions(draft,book).periods[0];for(const field of ['14','15','16','17','18'])assert.equal(incomplete.fields[field],null);
book.periods[0].absent=[...acquisitionExcludedFields];book.periods[0].complete=false;assert.equal(calculateAcquisitions(draft,book).periods[0].fields['15'],null);
const credit=acquisitionsFixture();credit.book.rows[0]={...credit.book.rows[0],net:'2000',vat:'320',gross:'2320'};assert.equal(calculateAcquisitions(credit.draft,credit.book).periods[0].fields['18'],'159.9952');
assert.throws(()=>calculateAcquisitions({...draft,imports:'5'},book),/importa/);
});
test('reuse keeps source values unclassified, preserves deliberate changes and detects source drift',()=>{
const {draft}=acquisitionsFixture();let book=reuseAcquisitions(draft,acquisitionBook(draft));assert.equal(book.rows[0].sourceAmount,'0.00');assert.equal(book.rows[0].net,'');assert.equal(book.rows[0].sourceBasis,'');
book.rows[0].net='123';book=reuseAcquisitions(draft,book);assert.equal(book.rows[0].net,'123');assert.equal(book.rows.length,4);
const plan=restoreBusinessPlanSnapshot(draft.business_plan_snapshot);plan.monthlyInventoryPurchases='1';const changed={...draft,business_plan_snapshot:serializeBusinessPlanSnapshot(plan)};assert.throws(()=>calculateAcquisitions(changed,book),/plano mudaram/);
});
test('asset and operating budgets can be reused explicitly without becoming VAT or deductions',()=>{
const {draft,book}=acquisitionsFixture();const plan=restoreBusinessPlanSnapshot(draft.business_plan_snapshot);plan.assetInvestment='200';plan.monthlyOperatingExpenses='50';draft.business_plan_snapshot=serializeBusinessPlanSnapshot(plan);
const refs=acquisitionPlanReferences(draft);assert.equal(refs.find(r=>r.kind==='asset').amount,'200');assert.equal(refs.find(r=>r.key==='operating:1').amount,'50');
const row={...newAcquisition('asset-reference','2026-01','MZN'),field:'08',sourceField:'asset',sourceMonth:1,sourceAmount:'200',sourceBasis:'net',net:'200'};book.rows=[row];assert.equal(calculateAcquisitions(draft,book).rows[0].deductible,null);
row.vat='32';assert.equal(calculateAcquisitions(draft,book).rows[0].deductible,null);
assert.equal(calculateAcquisitions(draft,book).rows[0].gross,'232.00');
});
test('order month is retained as origin and never forces invoice or deduction month',()=>{
const {draft}=acquisitionsFixture();const plan=restoreBusinessPlanSnapshot(draft.business_plan_snapshot);plan.useInventoryPurchaseSchedule=true;plan.inventoryPurchaseSchedule=[{amount:'100',leadMonths:0},{amount:'0',leadMonths:0},{amount:'0',leadMonths:0},{amount:'0',leadMonths:0}];draft.business_plan_snapshot=serializeBusinessPlanSnapshot(plan);
let book=reuseAcquisitions(draft,acquisitionBook(draft));book.taxpayerRegistered='yes';book.periods=book.periods.map(p=>({...p,complete:true,absent:[...acquisitionExcludedFields]}));
book.rows=book.rows.map(row=>({...row,net:row.sourceAmount,vat:'0',sourceBasis:'net'}));
book.rows[0]={...book.rows[0],...acquisitionsFixture().book.rows[0],id:'plan-1',sourceMonth:1,sourcePeriod:'2026-01',sourceAmount:'100.00',sourceBasis:'net',period:'2026-02',documentDate:'2026-02-10'};
const result=calculateAcquisitions(draft,book);assert.equal(result.rows[0].deductible,'16.00');assert.equal(result.periods[0].fields['09'],'0.00');assert.equal(result.periods[1].fields['09'],'16.00');assert.equal(result.inputs[0].sourcePeriod,'2026-01');
});
test('second opportunity changes preserve first book, frozen results and report context after recovery',()=>{
const {draft,book}=acquisitionsFixture();draft.context_opportunity='opportunity:1';book.result=calculateAcquisitions(draft,book);draft.modelo_a_snapshot=saveAcquisitionBook(draft,book);const first=JSON.stringify(acquisitionBook(draft));
draft.context_opportunity='opportunity:309';assert.equal(acquisitionBook(draft).rows.length,0);const second=acquisitionsFixture().book;second.rows[0].vat='32';second.rows[0].net='200';second.rows[0].gross='232';second.result=calculateAcquisitions(draft,second);draft.modelo_a_snapshot=saveAcquisitionBook(draft,second);
const recovered=JSON.parse(JSON.stringify(draft));assert.equal(acquisitionCurrent(recovered,acquisitionBook(recovered)),true);assert.equal(acquisitionBook(recovered).result.periods[0].fields['17'],'128.0048');
assert.equal(JSON.stringify(acquisitionBook({...draft,context_opportunity:'opportunity:1'})),first);
const report=JSON.stringify(createProjectDossierReport(recovered,{selectedSections:new Set(['finance'])}));assert.match(report,/128\.0048/);assert.match(report,/opportunity:309/);assert.doesNotMatch(report,/opportunity:1;/);
const old=JSON.stringify(second.result);second.rows[0].vat='33';draft.modelo_a_snapshot=saveAcquisitionBook(draft,second);assert.equal(acquisitionCurrent(draft,second),false);assert.equal(JSON.stringify(second.result),old);assert.match(JSON.stringify(acquisitionReportRows(draft)),/Histórico desactualizado/);
assert.throws(()=>acquisitionBook({modelo_a_snapshot:'broken'}));
});
if(process.env.IVA_ACQUISITION_FIXTURE_OUT){const {draft,book}=acquisitionsFixture();book.result=calculateAcquisitions(draft,book,'2026-10-24T12:00:00.000Z');draft.modelo_a_snapshot=saveAcquisitionBook(draft,book);fs.writeFileSync(process.env.IVA_ACQUISITION_FIXTURE_OUT,JSON.stringify(draft,null,2));}
+28
View File
@@ -0,0 +1,28 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import fs from 'node:fs';
import {operationTreatments,newSalesOperation,evaluateSalesOperation,recordSales,saveSalesBook,salesBook,salesCurrent} from '../../resources/js/lib/iva-operations.ts';
import {createProjectDossierReport} from '../../resources/js/lib/project-dossier-report.ts';
const ids=['industrial_feed','industrial_feed_inputs','veterinary_goods','agricultural_services'];
function seed(){return JSON.parse(fs.readFileSync(new URL('./fixtures/iva-publications.json',import.meta.url),'utf8'));}
function fixture(){const draft=seed();draft.context_opportunity='opportunity:314';draft.project_title='SYNTHETIC QA — G2E social';
let book={currency:'MZN',rows:ids.map((id,i)=>({...newSalesOperation(`g2e-${i}`,'2026-06','MZN'),description:`SYNTHETIC QA ${id}`,establishment:'SYNTHETIC QA equipamento Manica',amount:'100',basis:i%2?'included':'net',treatment:id,confirmed:operationTreatments.find(t=>t.id===id).conditions.map((_,n)=>n),evidence:'SYNTHETIC QA — natureza, entidade, reconhecimento e condições cumulativas pressupostos documentados; sem certificação'})),periods:[{period:'2026-06',complete:true}]};book=recordSales(draft,book);draft.modelo_a_snapshot=saveSalesBook(draft,book);return {draft,book};}
test('G2E four branches require their own operation and eligibility conditions',()=>{
const {book}=fixture();for(const row of book.rows){const rule=operationTreatments.find(t=>t.id===row.treatment),r=evaluateSalesOperation(row,'MZN');assert.equal(r.field,row.treatment==='industrial_feed'?'05':'07');assert.equal(r.net,'100.00');assert.equal(r.vat,'0.00');assert.equal(r.gross,'100.00');assert.match(r.article,/9\((12|15)\)/);
assert.equal(rule.conditions.length,3);
for(const missing of row.confirmed)assert.equal(evaluateSalesOperation({...row,confirmed:row.confirmed.filter(n=>n!==missing)},'MZN').vat,null);
assert.equal(evaluateSalesOperation({...row,evidence:''},'MZN').vat,null); assert.equal(evaluateSalesOperation({...row,period:'2025-06'},'MZN').vat,null); assert.equal(evaluateSalesOperation(row,'USD').vat,null);
}
assert.equal(book.result.periods[0].fields['07'],'300.00');assert.equal(book.result.periods[0].fields['05'],'100.00');assert.match(book.result.rows[0].reason,/com direito/);assert.ok(book.result.rows.slice(1).every(r=>r.reason.includes('sem direito')));
});
test('new agro context round-trips and reports only its operations, preserving five accepted books without recalculation',()=>{
const {draft,book}=fixture(),original=seed();const old=JSON.parse(original.modelo_a_snapshot).salesOperations;
const recovered=JSON.parse(JSON.stringify(draft)),store=JSON.parse(recovered.modelo_a_snapshot).salesOperations;
for(const id of ['opportunity:309','opportunity:310','opportunity:311','opportunity:312','opportunity:313']){assert.deepEqual(store[id],old[id]);assert.equal(salesCurrent({...recovered,context_opportunity:id},store[id]),true);}
assert.equal(salesCurrent(recovered,salesBook(recovered)),true);
const model=JSON.stringify(createProjectDossierReport(recovered,{selectedSections:new Set(['finance'])}));
for(const token of [...ids,'300.00','opportunity:314','Manica','2026-06','MZN'])assert.ok(model.includes(token),token);
for(const token of ['financial_stamp','patient_transport','social_assistance_public','statutory_membership','author_rights'])assert.equal(model.includes(token),false);
assert.equal(book.result.rows.length,4);assert.equal(draft.currency,original.currency);assert.deepEqual(draft.selection_labels,original.selection_labels);
});
if(process.env.IVA_G2E_OUT)fs.writeFileSync(process.env.IVA_G2E_OUT,JSON.stringify(fixture().draft,null,2));
+67
View File
@@ -0,0 +1,67 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import fs from 'node:fs';
import {annexIEntries,annexIEntry,annexIVersion} from '../../resources/js/lib/iva-annex-i.ts';
import {operationTreatments,newSalesOperation,evaluateSalesOperation,continueAnnexIOperation,recordSales,saveSalesBook,salesBook,salesCurrent} from '../../resources/js/lib/iva-operations.ts';
import {createProjectDossierReport} from '../../resources/js/lib/project-dossier-report.ts';
const rule=operationTreatments.find(t=>t.id==='annexI_goods');
const seed=()=>JSON.parse(fs.readFileSync(new URL('./fixtures/iva-pharma-inputs.json',import.meta.url),'utf8'));
const operation=(entry,i=0)=>({...newSalesOperation(`g2l-${i}`,'2026-09','MZN'),description:`SYNTHETIC QA ${entry.code} ${entry.id}`,establishment:'SYNTHETIC QA estabelecimento Manica',amount:'100',basis:i%2?'included':'net',treatment:rule.id,annexIItem:entry.id,confirmed:rule.conditions.map((_,n)=>n),evidence:'SYNTHETIC QA: correspondência código/designação e qualificadores da posição expressamente pressupostos; não é classificação aduaneira ou certificação'});
function fixture(){const draft=seed();draft.context_opportunity='opportunity:321';draft.project_title='SYNTHETIC QA — G2L Anexo I';
const codes=['0306.36.10','3102.10.00','1007.10.00','8501.61.00','8701.95.00','8201.50.00','0702.00.00','3808.91.00','1101.00.00','0402.21.10'];
const rows=codes.map((code,i)=>{
const entry=annexIEntries.find(e=>e.code===code);let row=operation(entry,i);
if(entry.relatedRequired){row=continueAnnexIOperation(row,entry.relatedTreatments[0]);row.confirmed=operationTreatments.find(t=>t.id===row.treatment).conditions.map((_,n)=>n);}
else if(entry.relatedTreatments){row.annexIOnly=true;row.evidence+=code==='1101.00.00'?'; mistura de trigo com centeio, não farinha de trigo simples':'; leite para utilização industrial, sem destino a lactente até um ano';}
return row;
});
const book=recordSales(draft,{currency:'MZN',rows,periods:[{period:'2026-09',complete:true}]});draft.modelo_a_snapshot=saveSalesBook(draft,book);return {draft,book};}
test('AnexoI has 172 distinct documentary positions, own qualifiers, cross-page text and five contextual tractor entries',()=>{
assert.equal(annexIEntries.length,172);assert.equal(new Set(annexIEntries.map(e=>e.code)).size,172);assert.equal(new Set(annexIEntries.map(e=>e.id)).size,172);
const scissors=annexIEntries.find(e=>e.code==='8201.50.00');assert.equal(scissors.pdfPage,8);assert.equal(scissors.lastPdfPage,9);assert.match(scissors.label,/uma das mãos/);
assert.equal(annexIEntries.filter(e=>e.context==='Outros tractores').length,5);
assert.equal(annexIEntries.find(e=>e.code==='8701.30.00').label.includes('Outros tractores'),false);
for(const [i,entry] of annexIEntries.entries()){
const row={...operation(entry,i),annexIOnly:true},r=evaluateSalesOperation(row,'MZN');
assert.equal(r.vat,entry.relatedRequired?null:'0.00');if(!entry.relatedRequired){assert.equal(r.field,'07');assert.equal(r.gross,'100.00');}
for(const token of [entry.id,entry.code,entry.label,`PDF${entry.pdfPage}`,annexIVersion])assert.ok(r.source.includes(token),token);
}
});
test('P035 requires actual position and qualifiers; overlapping descriptions require explicit applicability, never silently field07',()=>{
const {draft,book}=fixture(),row=book.rows[0];
for(const missing of row.confirmed)assert.equal(evaluateSalesOperation({...row,confirmed:row.confirmed.filter(n=>n!==missing)},'MZN').vat,null);
for(const patch of [{annexIItem:undefined},{annexIItem:''},{annexIItem:'0306.36.10'},{annexIItem:'annexIII-2022-001'},{evidence:''},{establishment:''},{amount:''},{period:'2025-09'},{sourceCurrency:'USD'}])assert.equal(evaluateSalesOperation({...row,...patch},'MZN').vat,null);
assert.equal(evaluateSalesOperation(row,'USD').vat,null);
const overlaps=annexIEntries.filter(e=>e.relatedTreatments);assert.equal(overlaps.length,13);assert.equal(overlaps.filter(e=>e.relatedRequired).length,3);
for(const entry of overlaps){const pending=operation(entry);assert.equal(evaluateSalesOperation(pending,'MZN').vat,null);assert.equal(evaluateSalesOperation({...pending,annexIOnly:true},'MZN').vat,entry.relatedRequired?null:'0.00');}
const incomplete=recordSales(draft,{...book,rows:[{...row,annexIItem:''}]});assert.equal(incomplete.result.periods[0].fields['07'],null);assert.deepEqual(incomplete.history.at(-1),book.result);
});
test('explicit continuation reuses existing treatment identity, preserves money/origin/annex and requires new conditions',()=>{
for(const entry of annexIEntries.filter(e=>e.relatedTreatments)){
for(const target of entry.relatedTreatments){
const before=operation(entry),after=continueAnnexIOperation(before,target),targetRule=operationTreatments.find(t=>t.id===target);
assert.equal(after.treatment,target);assert.equal(after.annexIItem,entry.id);assert.deepEqual(after.confirmed,[]);assert.ok(after.source.startsWith(before.source));assert.ok(after.source.includes(entry.id));
for(const key of ['id','period','amount','basis','sourceCurrency','sourcePeriod','establishment','description','evidence'])assert.equal(after[key],before[key],key);
assert.equal(evaluateSalesOperation(after,'MZN').vat,null);
const r=evaluateSalesOperation({...after,confirmed:targetRule.conditions.map((_,n)=>n)},'MZN');assert.equal(r.field,'05');assert.equal(r.vat,'0.00');
}
}
assert.throws(()=>continueAnnexIOperation(operation(annexIEntries[0]),'general'));
const e=annexIEntries.find(v=>v.code==='0702.00.00');assert.throws(()=>continueAnnexIOperation({...operation(e),treatment:'listed_fresh_chilled_tomato'},'listed_fresh_chilled_tomato'));
});
test('G2L recovery/report preserve twelve current books including G2K and calendar, without recalculation',()=>{
const {draft,book}=fixture(),original=seed(),old=JSON.parse(original.modelo_a_snapshot).salesOperations;
const recovered=JSON.parse(JSON.stringify(draft)),store=JSON.parse(recovered.modelo_a_snapshot).salesOperations;
assert.equal(Object.keys(old).length,12);for(const [id,value] of Object.entries(old)){assert.deepEqual(store[id],value);assert.equal(salesCurrent({...recovered,context_opportunity:id},value),true,id);}
assert.equal(salesCurrent(recovered,salesBook(recovered)),true);assert.equal(book.result.periods[0].fields['07'],'800.00');assert.equal(book.result.periods[0].fields['05'],'200.00');
const report=JSON.stringify(createProjectDossierReport(recovered,{selectedSections:new Set(['finance'])}));
for(const token of ['800.00','200.00','opportunity:321','Manica','2026-09','MZN','AnexoI/2022','Outros tractores',annexIVersion,...book.rows.map(r=>r.annexIItem)])assert.ok(report.includes(token),token);
for(const token of ['pharma_manufacturing_inputs','fundraising_public','production_forestry_opted'])assert.equal(report.includes(token),false);
const changed={...book,rows:book.rows.map((r,i)=>i===8?{...r,annexIOnly:false}:r)};assert.equal(salesCurrent(draft,changed),false);assert.deepEqual(changed.result,book.result);
assert.deepEqual(recovered.selection_labels,original.selection_labels);assert.equal(recovered.currency,original.currency);
});
if(process.env.IVA_G2L_OUT)fs.writeFileSync(process.env.IVA_G2L_OUT,JSON.stringify(fixture().draft,null,2));
+28
View File
@@ -0,0 +1,28 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import fs from 'node:fs';
import {operationTreatments,newSalesOperation,evaluateSalesOperation,recordSales,saveSalesBook,salesBook,salesCurrent} from '../../resources/js/lib/iva-operations.ts';
import {createProjectDossierReport} from '../../resources/js/lib/project-dossier-report.ts';
const ids=['public_security','official_military_supplies','sisa_subject_operation','exempt_activity_asset_sale','no_deduction_right_asset_sale','excluded_deduction_asset_sale'];
function seed(){return JSON.parse(fs.readFileSync(new URL('./fixtures/iva-services-nature.json',import.meta.url),'utf8'));}
function fixture(){const draft=seed();draft.context_opportunity='opportunity:316';draft.project_title='SYNTHETIC QA — G2G social';
let book={currency:'MZN',rows:ids.map((id,i)=>({...newSalesOperation(`g2g-${i}`,'2026-08','MZN'),description:`SYNTHETIC QA ${id}`,establishment:'SYNTHETIC QA equipamento Manica',amount:'100',basis:i%2?'included':'net',treatment:id,confirmed:operationTreatments.find(t=>t.id===id).conditions.map((_,n)=>n),evidence:'SYNTHETIC QA — natureza, entidade, reconhecimento e condições cumulativas pressupostos documentados; sem certificação'})),periods:[{period:'2026-08',complete:true}]};book=recordSales(draft,book);draft.modelo_a_snapshot=saveSalesBook(draft,book);return {draft,book};}
test('G2G four branches with six conditional treatments require their own operation and eligibility conditions',()=>{
const {book}=fixture();for(const row of book.rows){const rule=operationTreatments.find(t=>t.id===row.treatment),r=evaluateSalesOperation(row,'MZN');assert.equal(r.field,'07');assert.equal(r.net,'100.00');assert.equal(r.vat,'0.00');assert.equal(r.gross,'100.00');assert.match(r.article,/9\((2|11|12)\)/);
assert.ok(rule.conditions.length>=3);
for(const missing of row.confirmed)assert.equal(evaluateSalesOperation({...row,confirmed:row.confirmed.filter(n=>n!==missing)},'MZN').vat,null);
assert.equal(evaluateSalesOperation({...row,evidence:''},'MZN').vat,null); assert.equal(evaluateSalesOperation({...row,period:'2025-08'},'MZN').vat,null); assert.equal(evaluateSalesOperation(row,'USD').vat,null);
}
assert.equal(book.result.periods[0].fields['07'],'600.00');assert.equal(book.result.periods[0].fields['05'],'0.00');assert.ok(book.result.rows.every(r=>r.reason.includes('sem direito')));
});
test('new conditional context round-trips and reports only its operations, preserving seven accepted books without recalculation',()=>{
const {draft,book}=fixture(),original=seed();const old=JSON.parse(original.modelo_a_snapshot).salesOperations;
const recovered=JSON.parse(JSON.stringify(draft)),store=JSON.parse(recovered.modelo_a_snapshot).salesOperations;
for(const id of ['opportunity:309','opportunity:310','opportunity:311','opportunity:312','opportunity:313','opportunity:314','opportunity:315']){assert.deepEqual(store[id],old[id]);assert.equal(salesCurrent({...recovered,context_opportunity:id},store[id]),true);}
assert.equal(salesCurrent(recovered,salesBook(recovered)),true);
const model=JSON.stringify(createProjectDossierReport(recovered,{selectedSections:new Set(['finance'])}));
for(const token of [...ids,'600.00','opportunity:316','Manica','2026-08','MZN'])assert.ok(model.includes(token),token);
for(const token of ['financial_stamp','patient_transport','social_assistance_public','statutory_membership','author_rights','industrial_feed','special_tax_games'])assert.equal(model.includes(token),false);
assert.equal(book.result.rows.length,6);assert.equal(draft.currency,original.currency);assert.deepEqual(draft.selection_labels,original.selection_labels);
});
if(process.env.IVA_G2G_OUT)fs.writeFileSync(process.env.IVA_G2G_OUT,JSON.stringify(fixture().draft,null,2));
+28
View File
@@ -0,0 +1,28 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import fs from 'node:fs';
import {operationTreatments,newSalesOperation,evaluateSalesOperation,recordSales,saveSalesBook,salesBook,salesCurrent} from '../../resources/js/lib/iva-operations.ts';
import {createProjectDossierReport} from '../../resources/js/lib/project-dossier-report.ts';
const ids=['cultural_visits_public','cultural_visits_nonprofit','religious_personnel_public','religious_personnel_nonprofit','statutory_membership'];
function seed(){return JSON.parse(fs.readFileSync(new URL('./fixtures/iva-social.json',import.meta.url),'utf8'));}
function fixture(){const draft=seed();draft.context_opportunity='opportunity:312';draft.project_title='SYNTHETIC QA — G2C social';
let book={currency:'MZN',rows:ids.map((id,i)=>({...newSalesOperation(`g2c-${i}`,'2026-04','MZN'),description:`SYNTHETIC QA ${id}`,establishment:'SYNTHETIC QA equipamento Manica',amount:'100',basis:i%2?'included':'net',treatment:id,confirmed:operationTreatments.find(t=>t.id===id).conditions.map((_,n)=>n),evidence:'SYNTHETIC QA — natureza, entidade, reconhecimento e condições cumulativas pressupostos documentados; sem certificação'})),periods:[{period:'2026-04',complete:true}]};book=recordSales(draft,book);draft.modelo_a_snapshot=saveSalesBook(draft,book);return {draft,book};}
test('G2C three branches have five entity-specific treatments and cumulative nonprofit conditions',()=>{
const {book}=fixture();for(const row of book.rows){const rule=operationTreatments.find(t=>t.id===row.treatment),r=evaluateSalesOperation(row,'MZN');assert.equal(r.field,'07');assert.equal(r.net,'100.00');assert.equal(r.vat,'0.00');assert.equal(r.gross,'100.00');assert.match(r.article,/10\(/);
assert.ok(rule.conditions.length>=4); if(row.treatment.endsWith('_nonprofit')||row.treatment==='statutory_membership')assert.ok(rule.conditions.length>=7);
for(const missing of row.confirmed)assert.equal(evaluateSalesOperation({...row,confirmed:row.confirmed.filter(n=>n!==missing)},'MZN').vat,null);
assert.equal(evaluateSalesOperation({...row,evidence:''},'MZN').vat,null); assert.equal(evaluateSalesOperation({...row,period:'2025-04'},'MZN').vat,null); assert.equal(evaluateSalesOperation(row,'USD').vat,null);
}
assert.equal(book.result.periods[0].fields['07'],'500.00');
});
test('new cultural context round-trips and reports only its operations, preserving three accepted books without recalculation',()=>{
const {draft,book}=fixture(),original=seed();const old=JSON.parse(original.modelo_a_snapshot).salesOperations;
const recovered=JSON.parse(JSON.stringify(draft)),store=JSON.parse(recovered.modelo_a_snapshot).salesOperations;
for(const id of ['opportunity:309','opportunity:310','opportunity:311']){assert.deepEqual(store[id],old[id]);assert.equal(salesCurrent({...recovered,context_opportunity:id},store[id]),true);}
assert.equal(salesCurrent(recovered,salesBook(recovered)),true);
const model=JSON.stringify(createProjectDossierReport(recovered,{selectedSections:new Set(['finance'])}));
for(const token of [...ids,'500.00','opportunity:312','Manica','2026-04','MZN'])assert.ok(model.includes(token),token);
for(const token of ['financial_stamp','patient_transport','social_assistance_public'])assert.equal(model.includes(token),false);
assert.equal(book.result.rows.length,5);assert.equal(draft.currency,original.currency);assert.deepEqual(draft.selection_labels,original.selection_labels);
});
if(process.env.IVA_G2C_OUT)fs.writeFileSync(process.env.IVA_G2C_OUT,JSON.stringify(fixture().draft,null,2));
+33
View File
@@ -0,0 +1,33 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
import { directExportTreatments } from '../../resources/js/lib/iva-export-operations.ts';
import { newSalesOperation, evaluateSalesOperation, recordSales, saveSalesBook, salesBook, salesCurrent } from '../../resources/js/lib/iva-operations.ts';
import { createProjectDossierReport } from '../../resources/js/lib/project-dossier-report.ts';
const frozen=JSON.parse(fs.readFileSync(new URL('./fixtures/iva-g3-inputs.json',import.meta.url),'utf8'));
function row(rule,index=0){return {...newSalesOperation(`g4a-${index}`,'2026-11','MZN'),description:`SYNTHETIC QA — ${rule.label}`,establishment:'SYNTHETIC QA estabelecimento',amount:'100',basis:index%2?'included':'net',treatment:rule.id,confirmed:rule.conditions.map((_,i)=>i),evidence:'SYNTHETIC QA — intervenientes,origem/destino e ligação descritos como pressupostos da projecção; não certificação documental'};}
function fixture(){const draft={...structuredClone(frozen),context_opportunity:'opportunity:323',project_title:'SYNTHETIC QA — G4A / Exportações directas'};const book=recordSales(draft,{currency:'MZN',rows:directExportTreatments.map(row),periods:[{period:'2026-11',complete:true}]});draft.modelo_a_snapshot=saveSalesBook(draft,book);return {draft,book};}
test('five autonomous article13 rules classify field05 only after their own facts and evidence are determined',()=>{
assert.equal(directExportTreatments.length,5);
for(const rule of directExportTreatments){const input=row(rule),result=evaluateSalesOperation(input,'MZN');assert.equal(result.field,'05');assert.equal(result.net,'100.00');assert.equal(result.vat,'0.00');assert.equal(result.gross,'100.00');assert.match(result.source,/13\(1\)/);
for(const missing of input.confirmed){const r=evaluateSalesOperation({...input,confirmed:input.confirmed.filter(i=>i!==missing)},'MZN');assert.equal(r.status,'indeterminate');assert.equal(r.vat,null);}
for(const patch of [{amount:''},{basis:''},{evidence:''},{description:''},{establishment:''},{sourceCurrency:'USD'},{period:'2025-11'}])assert.equal(evaluateSalesOperation({...input,...patch},'MZN').vat,null);
assert.equal(evaluateSalesOperation({...input,amount:'0'},'MZN').net,'0.00');
}
assert.match(directExportTreatments[0].conditions[1],/Caminhos de Ferro de Moçambique/);
assert.match(directExportTreatments[1].conditions[2],/nacionalidade/);
assert.match(directExportTreatments[2].conditions[3],/não estabelecido/);
assert.match(directExportTreatments[3].conditions[2],/Banco de Moçambique/);
assert.match(directExportTreatments[4].conditions[2],/afectação/);
});
test('missing evidence leaves period indeterminate and recalculation preserves the previous result',()=>{
const {draft,book}=fixture();const next=recordSales(draft,{...book,rows:book.rows.map((r,i)=>i===2?{...r,evidence:''}:r)});assert.equal(next.result.periods[0].fields['05'],null);assert.deepEqual(next.history.at(-1),book.result);
assert.equal(book.result.periods[0].fields['05'],'500.00');assert.equal(book.result.periods[0].fields['01'],'0.00');
});
test('snapshot/report retain context and sources while all14 delivered books stay byte-equivalent and current',()=>{
const {draft,book}=fixture();assert.equal(salesCurrent(draft,book),true);assert.deepEqual(salesBook(JSON.parse(JSON.stringify(draft))),JSON.parse(JSON.stringify(book)));
const before=JSON.parse(frozen.modelo_a_snapshot).salesOperations,after=JSON.parse(draft.modelo_a_snapshot).salesOperations;assert.equal(Object.keys(before).length,14);
for(const [context,original]of Object.entries(before)){assert.deepEqual(after[context],original);assert.equal(salesCurrent({...draft,context_opportunity:context},after[context]),true);}
const model=createProjectDossierReport(draft,{selectedSections:new Set(['finance']),version:'QA G4A'});for(const value of ['500.00','opportunity:323','Manica','2026-11','MZN','13(1)(o)','13(1)(p)','13(1)(q)','13(1)(r)','13(1)(t)'])assert.ok(JSON.stringify(model).includes(value),value);
if(process.env.IVA_G4A_CALCULATED)fs.writeFileSync(process.env.IVA_G4A_CALCULATED,JSON.stringify(draft));
});
@@ -0,0 +1,36 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
import { exportServiceTreatments } from '../../resources/js/lib/iva-export-services.ts';
import { newSalesOperation,operationTreatments,evaluateSalesOperation,referenceExportOperation,recordSales,saveSalesBook,salesBook,salesCurrent } from '../../resources/js/lib/iva-operations.ts';
import { createProjectDossierReport } from '../../resources/js/lib/project-dossier-report.ts';
const frozen=JSON.parse(fs.readFileSync(new URL('./fixtures/iva-g4b-inputs.json',import.meta.url),'utf8'));
const row=(rule,i=0)=>({...newSalesOperation(`g4c-${i}`,'2026-12','MZN'),description:`SYNTHETIC QA — ${rule.label}`,establishment:'SYNTHETIC QA estabelecimento',amount:'100',basis:i%2?'included':'net',treatment:rule.id,confirmed:rule.conditions.map((_,n)=>n),evidence:'SYNTHETIC QA — documento/pressuposto externo identifica bens,regime/localização,mandante e ligação do serviço;operação do intermediário localizada emMoçambique;sem certificação'});
function fixture(){
const draft={...structuredClone(frozen),context_opportunity:'opportunity:325',project_title:'SYNTHETIC QA — G4C / Serviços ligados'};
const goods={...row(operationTreatments.find(r=>r.id==='export_goods'),9),id:'g4c-goods',description:'SYNTHETIC QA — mercadorias expedidas pelo vendedor',amount:'1000'};
const services=exportServiceTreatments.map(row);services[1]=referenceExportOperation(services[1],goods);services[1].confirmed=exportServiceTreatments[1].conditions.map((_,i)=>i);
const book=recordSales(draft,{currency:'MZN',rows:[goods,...services],periods:[{period:'2026-12',complete:true}]});draft.modelo_a_snapshot=saveSalesBook(draft,book);return{draft,book};
}
test('three services require each legal condition,local service scope and evidence;no automatic classification from client or sector',()=>{
assert.equal(exportServiceTreatments.length,3);assert.match(exportServiceTreatments[0].conditions[2],/admissão temporária/);assert.match(exportServiceTreatments[0].conditions[3],/artigo9/);assert.match(exportServiceTreatments[1].conditions[2],/artigo9/);assert.match(exportServiceTreatments[2].conditions[1],/não actuação em nome próprio/);
for(const [i,rule]of exportServiceTreatments.entries()){const input=row(rule,i);assert.equal(evaluateSalesOperation(input,'MZN').field,'05');assert.equal(evaluateSalesOperation(input,'MZN').vat,'0.00');for(const missing of input.confirmed)assert.equal(evaluateSalesOperation({...input,confirmed:input.confirmed.filter(n=>n!==missing)},'MZN').vat,null);for(const patch of [{amount:''},{evidence:''},{sourceCurrency:'USD'},{period:'2027-01'},{basis:''}])assert.equal(evaluateSalesOperation({...input,...patch},'MZN').vat,null);}
});
test('reference reuse keeps service price/identity/evidence and requires deliberate confirmation of new relationship',()=>{
const service=row(exportServiceTreatments[1]),related={...row(operationTreatments.find(r=>r.id==='export_goods'),8),amount:'1000'},linked=referenceExportOperation(service,related);
assert.deepEqual(linked.relatedExport,{id:related.id,description:related.description,treatment:related.treatment});assert.deepEqual(linked.confirmed,[]);
for(const field of ['id','amount','basis','period','description','evidence','establishment','sourceAmount','sourcePeriod','sourceCurrency','source'])assert.deepEqual(linked[field],service[field],field);
assert.equal(linked.amount,'100');assert.equal(evaluateSalesOperation(linked,'MZN').vat,null);assert.throws(()=>referenceExportOperation(service,service));assert.throws(()=>referenceExportOperation(related,service));
});
test('deleted/changed linked operation blocks current calculation,keeps history and requires explicit reference update',()=>{
const{draft,book}=fixture();assert.equal(book.result.periods[0].fields['05'],'1300.00');
for(const rows of [book.rows.filter(r=>r.id!=='g4c-goods'),book.rows.map(r=>r.id==='g4c-goods'?{...r,description:'Changed goods'}:r)]){const changed=recordSales(draft,{...book,rows});assert.equal(changed.result.rows.find(r=>r.id==='g4c-1').vat,null);assert.match(changed.result.rows.find(r=>r.id==='g4c-1').reason,/removida ou alterada/);assert.equal(changed.result.periods[0].fields['05'],null);assert.deepEqual(changed.history.at(-1),book.result);assert.equal(changed.rows.find(r=>r.id==='g4c-1').amount,'100');}
const changedGoods={...book.rows[0],description:'Reviewed goods'};const linked=referenceExportOperation(book.rows[2],changedGoods);linked.confirmed=exportServiceTreatments[1].conditions.map((_,i)=>i);const next=recordSales(draft,{...book,rows:[changedGoods,book.rows[1],linked,book.rows[3]]});assert.equal(next.result.periods[0].fields['05'],'1300.00');
const invalid=recordSales(draft,{...book,rows:book.rows.map(r=>r.id==='g4c-1'?{...r,relatedExport:{id:r.id,description:r.description,treatment:r.treatment}}:r)});assert.equal(invalid.result.periods[0].fields['05'],null);
});
test('stored service reference survives report/recovery;all16 prior books remain unchanged/current without recalculation',()=>{
const{draft,book}=fixture();assert.ok(salesCurrent(draft,book));assert.deepEqual(salesBook(JSON.parse(JSON.stringify(draft))),JSON.parse(JSON.stringify(book)));
const before=JSON.parse(frozen.modelo_a_snapshot).salesOperations,after=JSON.parse(draft.modelo_a_snapshot).salesOperations;assert.equal(Object.keys(before).length,16);for(const[context,original]of Object.entries(before)){assert.deepEqual(after[context],original);assert.ok(salesCurrent({...draft,context_opportunity:context},after[context]));}
const report=JSON.stringify(createProjectDossierReport(draft,{selectedSections:new Set(['finance']),version:'QA G4C'}));for(const token of ['opportunity:325','Manica','2026-12','1300.00','13(1)(m)','13(1)(n)','13(1)(s)','g4c-goods','Operação relacionada'])assert.ok(report.includes(token),token);
if(process.env.IVA_G4C_CALCULATED)fs.writeFileSync(process.env.IVA_G4C_CALCULATED,JSON.stringify(draft));
});
+27
View File
@@ -0,0 +1,27 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import fs from 'node:fs';
import {operationTreatments,newSalesOperation,evaluateSalesOperation,recordSales,saveSalesBook,salesBook,salesCurrent} from '../../resources/js/lib/iva-operations.ts';
import {createProjectDossierReport} from '../../resources/js/lib/project-dossier-report.ts';
const seed=()=>JSON.parse(fs.readFileSync(new URL('./fixtures/iva-production.json',import.meta.url),'utf8'));
function fixture(){const draft=seed();draft.context_opportunity='opportunity:319';draft.project_title='SYNTHETIC QA G2J fundraising';
let book={currency:'MZN',rows:['fundraising_public','fundraising_nonprofit'].map((id,i)=>({...newSalesOperation(`g2j-${i}`,'2026-11','MZN'),description:`SYNTHETIC QA ${id}`,establishment:'SYNTHETIC QA Manica',amount:'100',basis:i?'included':'net',treatment:id,confirmed:operationTreatments.find(t=>t.id===id).conditions.map((_,n)=>n),evidence:'SYNTHETIC QA: entidade, actividade habitual isenta, proveito exclusivo e total anual expressamente pressupostos',fundraiser:{entityReference:`SYNTHETIC-ENTITY-${i}`,annualEvents:i?'8':'1',eventNumber:i?'8':'1',activity:'social_assistance'}})),periods:[{period:'2026-11',complete:true}]};book=recordSales(draft,book);draft.modelo_a_snapshot=saveSalesBook(draft,book);return {draft,book};}
test('one fundraising branch: public/nonprofit, eighth admitted, ninth/unknown/activity mismatch indeterminate',()=>{
const {draft,book}=fixture();assert.equal(book.result.periods[0].fields['07'],'200.00');
for(const row of book.rows){assert.equal(evaluateSalesOperation(row,'MZN').vat,'0.00');for(const n of row.confirmed)assert.equal(evaluateSalesOperation({...row,confirmed:row.confirmed.filter(i=>i!==n)},'MZN').vat,null);
for(const patch of [{annualEvents:'9'},{annualEvents:''},{annualEvents:'0'},{eventNumber:'9'},{eventNumber:'2',annualEvents:'1'},{entityReference:''},{activity:'religious_personnel'},{activity:''}])assert.equal(evaluateSalesOperation({...row,fundraiser:{...row.fundraiser,...patch}},'MZN').vat,null);
assert.equal(evaluateSalesOperation({...row,evidence:''},'MZN').vat,null);
}
const nonprofit=book.rows[1];assert.equal(evaluateSalesOperation({...nonprofit,fundraiser:{...nonprofit.fundraiser,activity:'health_public'}},'MZN').vat,null);
const conflicting={...book,rows:book.rows.map(r=>({...r,fundraiser:{...r.fundraiser,entityReference:'SAME'}}))};assert.ok(recordSales(draft,conflicting).result.rows.every(r=>r.vat===null));
const sameEvent={...book,rows:[book.rows[0],{...book.rows[0],id:'second-sale'}]};assert.equal(recordSales(draft,sameEvent).result.periods[0].fields['07'],'200.00');
});
test('fundraising context reports annual data preserving ten books; only changed G2I calendar version becomes historical',()=>{
const {draft,book}=fixture(),old=JSON.parse(seed().modelo_a_snapshot).salesOperations,store=JSON.parse(draft.modelo_a_snapshot).salesOperations;
for(const [id,value] of Object.entries(old)){assert.deepEqual(store[id],value);assert.equal(salesCurrent({...draft,context_opportunity:id},value),id!=='opportunity:318');}
assert.equal(Object.keys(old).length,10);assert.equal(salesCurrent(draft,salesBook(draft)),true);
const model=JSON.stringify(createProjectDossierReport(draft,{selectedSections:new Set(['finance'])}));
for(const token of ['fundraising_public','fundraising_nonprofit','200.00','SYNTHETIC-ENTITY-1','2026-11','opportunity:319','Manica','total anual declarado 8'])assert.ok(model.includes(token),token);
assert.equal(model.includes('production_forestry_opted'),false);assert.equal(book.result.rows.length,2);
});
if(process.env.IVA_G2J_OUT)fs.writeFileSync(process.env.IVA_G2J_OUT,JSON.stringify(fixture().draft,null,2));
+22
View File
@@ -0,0 +1,22 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import fs from 'node:fs';
import {operationTreatments,newSalesOperation,evaluateSalesOperation,recordSales,saveSalesBook,salesBook,salesCurrent} from '../../resources/js/lib/iva-operations.ts';
import {createProjectDossierReport} from '../../resources/js/lib/project-dossier-report.ts';
const ids=['financial_stamp','insurance_stamp','public_waste','public_funeral'];
function fixture(){const draft={purpose:'simulate_only',currency:'MZN',context_opportunity:'opportunity:310',project_title:'SYNTHETIC QA — G1 serviços isentos',province_id:'cf5e81f1-ffbc-535d-b1b6-b44b445c4421',selection_labels:{province_id:'Manica'}};
let book={currency:'MZN',rows:ids.map((id,i)=>({...newSalesOperation(`g1-${i}`,'2026-01','MZN'),description:`SYNTHETIC QA ${id}`,establishment:'SYNTHETIC QA estabelecimento',amount:'100',basis:'net',treatment:id,confirmed:[0,1],evidence:'SYNTHETIC QA — condições documentadas pressupostas, sem certificação'})),periods:[{period:'2026-01',complete:true}]};book=recordSales(draft,book);draft.modelo_a_snapshot=saveSalesBook(draft,book);return {draft,book};}
test('G1 four documented operations use the same conditions and persistence, with independent applicability',()=>{
const {draft,book}=fixture();for(const row of book.rows){const r=evaluateSalesOperation(row,'MZN');assert.equal(r.vat,'0.00');assert.equal(r.field,'07');assert.match(r.article,/9\(/);assert.match(r.source,/Lei22/);assert.equal(evaluateSalesOperation({...row,confirmed:[0]},'MZN').vat,null);assert.equal(evaluateSalesOperation({...row,evidence:''},'MZN').vat,null);}
assert.equal(book.result.periods[0].fields['07'],'400.00');const recovered=JSON.parse(JSON.stringify(draft));assert.equal(salesCurrent(recovered,salesBook(recovered)),true);assert.match(JSON.stringify(createProjectDossierReport(recovered,{selectedSections:new Set(['finance'])})),/400\.00/);
assert.equal(salesCurrent({...recovered,currency:'USD'},salesBook(recovered)),false);
assert.equal(salesCurrent({...recovered,context_opportunity:'opportunity:309'},salesBook(recovered)),false);
const rule=operationTreatments.find(t=>t.id==='financial_stamp');const source=rule.source;
try{rule.source+=' — changed source';assert.equal(salesCurrent(recovered,salesBook(recovered)),false);}finally{rule.source=source;}
});
test('adding independent catalogue rules does not invalidate or recalculate accepted rational snapshots',()=>{
const draft=JSON.parse(fs.readFileSync(new URL('./fixtures/iva-rational.json',import.meta.url),'utf8'));const original=draft.modelo_a_snapshot;assert.equal(salesCurrent(draft,salesBook(draft)),true);assert.equal(draft.modelo_a_snapshot,original);assert.equal(operationTreatments.filter(t=>ids.includes(t.id)).length,4);
operationTreatments.push({...operationTreatments[0],id:'synthetic_future_independent'});
try{assert.equal(salesCurrent(draft,salesBook(draft)),true);assert.equal(draft.modelo_a_snapshot,original);}finally{operationTreatments.pop();}
});
if(process.env.IVA_G1_OUT)fs.writeFileSync(process.env.IVA_G1_OUT,JSON.stringify(fixture().draft,null,2));
+32
View File
@@ -0,0 +1,32 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import fs from 'node:fs';
import {operationTreatments,newSalesOperation,evaluateSalesOperation,recordSales,saveSalesBook,salesBook,salesCurrent} from '../../resources/js/lib/iva-operations.ts';
import {createProjectDossierReport} from '../../resources/js/lib/project-dossier-report.ts';
const ids=['health_assistive','human_materials','patient_transport','mosquito_nets','medicines'];
export function healthFixture(){
const draft=JSON.parse(fs.readFileSync(new URL('./fixtures/iva-services.json',import.meta.url),'utf8'));
draft.context_opportunity='opportunity:309';draft.project_title='SYNTHETIC QA — G2A saúde';
let book={currency:'MZN',rows:ids.map((id,i)=>({...newSalesOperation(`g2a-${i}`,'2026-02','MZN'),description:`SYNTHETIC QA ${id}`,establishment:'SYNTHETIC QA estabelecimento Manica',amount:'100',basis:i%2?'included':'net',treatment:id,confirmed:operationTreatments.find(t=>t.id===id).conditions.map((_,n)=>n),evidence:'SYNTHETIC QA — natureza, destino e autorização quando aplicável pressupostos documentados; sem certificação'})),periods:[{period:'2026-02',complete:true}]};
book=recordSales(draft,book);draft.modelo_a_snapshot=saveSalesBook(draft,book);return {draft,book};
}
test('G2A five health branches require their own nature, location, purpose and authorization, not the health sector',()=>{
const {book}=healthFixture();
for(const row of book.rows){const r=evaluateSalesOperation(row,'MZN');assert.equal(r.field,'07');assert.equal(r.net,'100.00');assert.equal(r.vat,'0.00');assert.equal(r.gross,'100.00');assert.match(r.source,/1426\(267\)/);
const count=operationTreatments.find(t=>t.id===row.treatment).conditions.length;
for(let missing=0;missing<count;missing++)assert.equal(evaluateSalesOperation({...row,confirmed:row.confirmed.filter(n=>n!==missing)},'MZN').vat,null);
assert.equal(evaluateSalesOperation({...row,evidence:''},'MZN').vat,null);
}
assert.equal(book.result.periods[0].fields['07'],'500.00');
});
test('G2A reuses saved dossier data, retains G1 unchanged, and reports recovered context without recalculating accepted treatments',()=>{
const original=JSON.parse(fs.readFileSync(new URL('./fixtures/iva-services.json',import.meta.url),'utf8'));
const before=JSON.parse(original.modelo_a_snapshot).salesOperations['opportunity:310'];
const {draft}=healthFixture();const recovered=JSON.parse(JSON.stringify(draft));assert.equal(salesCurrent(recovered,salesBook(recovered)),true);
assert.deepEqual(JSON.parse(recovered.modelo_a_snapshot).salesOperations['opportunity:310'],before);
const model=JSON.stringify(createProjectDossierReport(recovered,{selectedSections:new Set(['finance'])}));
for(const token of [...ids,'500.00','opportunity:309','Manica','MZN','2026-02'])assert.ok(model.includes(token),token);
assert.equal(model.includes('financial_stamp'),false);
assert.equal(draft.province_id,original.province_id);assert.deepEqual(draft.selection_labels,original.selection_labels);
});
if(process.env.IVA_G2A_OUT)fs.writeFileSync(process.env.IVA_G2A_OUT,JSON.stringify(healthFixture().draft,null,2));
@@ -0,0 +1,26 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
import { internationalAssetTreatments } from '../../resources/js/lib/iva-international-assets.ts';
import { newSalesOperation,evaluateSalesOperation,recordSales,saveSalesBook,salesBook,salesCurrent } from '../../resources/js/lib/iva-operations.ts';
import { createProjectDossierReport } from '../../resources/js/lib/project-dossier-report.ts';
const frozen=JSON.parse(fs.readFileSync(new URL('./fixtures/iva-g4a-inputs.json',import.meta.url),'utf8'));
const row=(rule,i)=>({...newSalesOperation(`g4b-${i}`,'2026-12','MZN'),description:`SYNTHETIC QA — ${rule.label}`,establishment:'SYNTHETIC QA estabelecimento',amount:'100',basis:i%2?'included':'net',treatment:rule.id,confirmed:rule.conditions.map((_,n)=>n),evidence:'SYNTHETIC QA:embarcação/avião,operador,utilização e ligação da operação expressamente pressupostos;sem certificação de matrícula ou documentos'});
function fixture(){const draft={...structuredClone(frozen),context_opportunity:'opportunity:324',project_title:'SYNTHETIC QA — G4B / Embarcações e aviões'};const book=recordSales(draft,{currency:'MZN',rows:internationalAssetTreatments.map(row),periods:[{period:'2026-12',complete:true}]});draft.modelo_a_snapshot=saveSalesBook(draft,book);return{draft,book};}
test('three branches/four treatments require eligible asset and actual operation; all missing conditions block zero-VAT classification',()=>{
assert.equal(internationalAssetTreatments.length,4);
assert.deepEqual(internationalAssetTreatments.map(r=>r.article),['CIVA arts.13(1)(f),19(1)(b)(i)','CIVA arts.13(1)(g),19(1)(b)(i)','CIVA arts.13(1)(i),19(1)(b)(i)','CIVA arts.13(1)(i),19(1)(b)(i)']);
for(const [i,rule]of internationalAssetTreatments.entries()){const input=row(rule,i);assert.equal(evaluateSalesOperation(input,'MZN').vat,'0.00');assert.equal(evaluateSalesOperation(input,'MZN').field,'05');for(const missing of input.confirmed){const r=evaluateSalesOperation({...input,confirmed:input.confirmed.filter(n=>n!==missing)},'MZN');assert.equal(r.vat,null);assert.equal(r.status,'indeterminate');}
for(const patch of [{evidence:''},{amount:''},{basis:''},{sourceCurrency:'USD'},{period:'2027-01'},{establishment:''}])assert.equal(evaluateSalesOperation({...input,...patch},'MZN').vat,null);
}
assert.match(internationalAssetTreatments[0].conditions[1],/alto mar/);assert.match(internationalAssetTreatments[0].conditions[1],/pesca costeira/);assert.match(internationalAssetTreatments[1].conditions[1],/principalmente/);assert.match(internationalAssetTreatments[1].conditions[2],/aluguer autónomo/);assert.match(internationalAssetTreatments[2].conditions[3],/distinto/);
});
test('unknown direct link leaves totals indeterminate and preserves the last result without recalculation of previous books',()=>{
const {draft,book}=fixture();assert.equal(book.result.periods[0].fields['05'],'400.00');const changed=recordSales(draft,{...book,rows:book.rows.map((r,i)=>i===2?{...r,confirmed:r.confirmed.filter(n=>n!==2)}:r)});assert.equal(changed.result.periods[0].fields['05'],null);assert.deepEqual(changed.history.at(-1),book.result);assert.equal(evaluateSalesOperation({...book.rows[0],amount:'0'},'MZN').net,'0.00');
});
test('stored context and report preserve sources/values and all15 delivered books remain current without recalculation',()=>{
const {draft,book}=fixture();assert.ok(salesCurrent(draft,book));assert.deepEqual(salesBook(JSON.parse(JSON.stringify(draft))),JSON.parse(JSON.stringify(book)));
const before=JSON.parse(frozen.modelo_a_snapshot).salesOperations,after=JSON.parse(draft.modelo_a_snapshot).salesOperations;assert.equal(Object.keys(before).length,15);for(const [context,original]of Object.entries(before)){assert.deepEqual(after[context],original);assert.ok(salesCurrent({...draft,context_opportunity:context},after[context]));}
const report=JSON.stringify(createProjectDossierReport(draft,{selectedSections:new Set(['finance']),version:'QA G4B'}));for(const token of ['opportunity:324','Manica','2026-12','400.00','13(1)(f)','13(1)(g)','13(1)(i)'])assert.ok(report.includes(token),token);
if(process.env.IVA_G4B_CALCULATED)fs.writeFileSync(process.env.IVA_G4B_CALCULATED,JSON.stringify(draft));
});
+40
View File
@@ -0,0 +1,40 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import fs from 'node:fs';
import {l1DeltaFixture} from './fixtures/iva-l1-delta-fixture.mjs';
import {calculateSales,evaluateSalesOperation,modeloA06Correspondence,salesBook,salesCurrent,saveSalesBook} from '../../resources/js/lib/iva-operations.ts';
import {calculateAcquisitions,saveAcquisitionBook} from '../../resources/js/lib/iva-acquisitions.ts';
import {addFractions,decimalFraction,fraction,fractionLabel,fractionPresentation} from '../../resources/js/lib/fiscal-rational.ts';
import {createProjectDossierReport} from '../../resources/js/lib/project-dossier-report.ts';
test('periodic included5% retains exact rational amounts; only presentation is rounded',()=>{
const {book}=l1DeltaFixture(),r=book.result.rows[0];
assert.deepEqual(r.exact.net,{numerator:'20',denominator:'21'});assert.deepEqual(r.exact.vat,{numerator:'1',denominator:'21'});
assert.equal(r.net,'0.952381');assert.equal(r.vat,'0.047619');assert.equal(r.status,'calculated');assert.match(r.reason,/apresentação técnica/);
assert.deepEqual(addFractions([r.exact.net,r.exact.vat]),r.exact.gross);
assert.deepEqual(book.result.rows[1].exact.vat,{numerator:'100',denominator:'21'});
});
test('aggregation uses exact fractions, not21 rounded values',()=>{
const {draft,book}=l1DeltaFixture();book.rows=Array.from({length:21},(_,i)=>({...book.rows[0],id:`q${i}`}));const r=calculateSales(draft,book);
assert.equal(r.rows.every(row=>row.vat==='0.047619'),true);assert.equal(r.periods[0].fields['04'],'1.00');assert.deepEqual(r.periods[0].exactFields['04'],{numerator:'1',denominator:'1'});assert.equal(r.periods[0].fields['03'],'20.00');
});
test('new version round trips by opportunity, keeping accepted first snapshot untouched',()=>{
const accepted=JSON.parse(fs.readFileSync(new URL('./fixtures/iva-operations.json',import.meta.url),'utf8'));const original=JSON.parse(accepted.modelo_a_snapshot).salesOperations['opportunity:309'];
const {draft,book}=l1DeltaFixture();const saved=JSON.parse(JSON.stringify({...draft,modelo_a_snapshot:saveSalesBook(draft,book)}));
assert.deepEqual(JSON.parse(saved.modelo_a_snapshot).salesOperations['opportunity:309'],original);assert.equal(salesCurrent(saved,salesBook(saved)),true);assert.deepEqual(salesBook(saved).result.rows[2].exact,book.result.rows[2].exact);
});
test('conditional14-18 and report carry exact precision rather than rounded line amounts',()=>{
const {draft,book}=l1DeltaFixture();const a={currency:'MZN',rows:[],periods:['2026-01','2026-02','2026-03','2026-04'].map(period=>({period,complete:true,absent:['03','04','05','06','07','11','12','13']}))};
const result=calculateAcquisitions(draft,a);assert.equal(fractionLabel(result.periods[0].exactFields['17']),'5051/1050');assert.equal(result.periods[0].fields['17'],'4.810476');
a.result=result;draft.modelo_a_snapshot=saveAcquisitionBook(draft,a);const report=JSON.stringify(createProjectDossierReport(draft,{selectedSections:new Set(['finance'])}));assert.match(report,/5051\/1050/);assert.match(report,/20\/21/);assert.match(report,/opportunity:310/);
assert.match(report,/apresentação técnica/);assert.equal(book.result.rows.length,3);
});
test('missing inputs still block only the affected result; invalid fractions do not become zero',()=>{
const {book}=l1DeltaFixture();assert.equal(evaluateSalesOperation({...book.rows[0],amount:''},'MZN').vat,null);
assert.equal(evaluateSalesOperation({...book.rows[0],basis:''},'MZN').vat,null);assert.equal(evaluateSalesOperation({...book.rows[0],amount:'0'},'MZN').vat,'0.00');
const {draft}=l1DeltaFixture();book.rows[0].sourceAmount='1';const stale=calculateSales(draft,book).rows[0];assert.equal(stale.vat,null);assert.equal(stale.exact,undefined);
assert.throws(()=>fractionPresentation({numerator:'1',denominator:'0'}));assert.equal(fractionPresentation(fraction(1n,21n)).approximate,true);assert.equal(fractionPresentation(decimalFraction('105')).approximate,false);
});
test('form06 is not automatically inferred from a foreign operation or old stock instructions',()=>{
const {book}=l1DeltaFixture();const r=evaluateSalesOperation({...book.rows[0],treatment:'foreign_operation'},'MZN');assert.equal(r.field,null);assert.equal(r.vat,null);assert.match(modeloA06Correspondence,/existências/);assert.match(modeloA06Correspondence,/separe05\/06/);
});
if(process.env.IVA_L1_DELTA_OUT)fs.writeFileSync(process.env.IVA_L1_DELTA_OUT,JSON.stringify(l1DeltaFixture().draft,null,2));
+28
View File
@@ -0,0 +1,28 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import fs from 'node:fs';
import {operationTreatments,newSalesOperation,evaluateSalesOperation,recordSales,saveSalesBook,salesBook,salesCurrent} from '../../resources/js/lib/iva-operations.ts';
import {createProjectDossierReport} from '../../resources/js/lib/project-dossier-report.ts';
const ids=['listed_maize', 'listed_maize_flour', 'listed_rice', 'listed_bread', 'listed_iodised_salt', 'listed_infant_powdered_milk', 'listed_wheat', 'listed_wheat_flour', 'listed_fresh_chilled_tomato', 'listed_potato', 'listed_onion', 'listed_frozen_horse_mackerel', 'listed_lighting_kerosene', 'listed_domestic_lpg', 'listed_jet_fuel', 'listed_eligible_bicycles', 'listed_condoms', 'listed_insecticides'];
function seed(){return JSON.parse(fs.readFileSync(new URL('./fixtures/iva-conditional.json',import.meta.url),'utf8'));}
function fixture(){const draft=seed();draft.context_opportunity='opportunity:317';draft.project_title='SYNTHETIC QA — G2H social';
let book={currency:'MZN',rows:ids.map((id,i)=>({...newSalesOperation(`g2h-${i}`,'2026-09','MZN'),description:`SYNTHETIC QA ${id}`,establishment:'SYNTHETIC QA equipamento Manica',amount:'100',basis:i%2?'included':'net',treatment:id,confirmed:operationTreatments.find(t=>t.id===id).conditions.map((_,n)=>n),evidence:'SYNTHETIC QA — natureza, entidade, reconhecimento e condições cumulativas pressupostos documentados; sem certificação'})),periods:[{period:'2026-09',complete:true}]};book=recordSales(draft,book);draft.modelo_a_snapshot=saveSalesBook(draft,book);return {draft,book};}
test('G2H one branch with eighteen specifically enumerated products require their own operation and eligibility conditions',()=>{
const {book}=fixture();for(const row of book.rows){const rule=operationTreatments.find(t=>t.id===row.treatment),r=evaluateSalesOperation(row,'MZN');assert.equal(r.field,'05');assert.equal(r.net,'100.00');assert.equal(r.vat,'0.00');assert.equal(r.gross,'100.00');assert.match(r.article,/9\(10\)/);
assert.ok(rule.conditions.length>=3);
for(const missing of row.confirmed)assert.equal(evaluateSalesOperation({...row,confirmed:row.confirmed.filter(n=>n!==missing)},'MZN').vat,null);
assert.equal(evaluateSalesOperation({...row,evidence:''},'MZN').vat,null);assert.equal(evaluateSalesOperation({...row,treatment:'listed_banana'},'MZN').vat,null); assert.equal(evaluateSalesOperation({...row,period:'2025-09'},'MZN').vat,null); assert.equal(evaluateSalesOperation(row,'USD').vat,null);
}
assert.equal(book.result.periods[0].fields['07'],'0.00');assert.equal(book.result.periods[0].fields['05'],'1800.00');assert.ok(book.result.rows.every(r=>r.reason.includes('com direito')));
});
test('new listed-goods context round-trips and reports only its operations, preserving eight accepted books without recalculation',()=>{
const {draft,book}=fixture(),original=seed();const old=JSON.parse(original.modelo_a_snapshot).salesOperations;
const recovered=JSON.parse(JSON.stringify(draft)),store=JSON.parse(recovered.modelo_a_snapshot).salesOperations;
for(const id of ['opportunity:309','opportunity:310','opportunity:311','opportunity:312','opportunity:313','opportunity:314','opportunity:315','opportunity:316']){assert.deepEqual(store[id],old[id]);assert.equal(salesCurrent({...recovered,context_opportunity:id},store[id]),true);}
assert.equal(salesCurrent(recovered,salesBook(recovered)),true);
const model=JSON.stringify(createProjectDossierReport(recovered,{selectedSections:new Set(['finance'])}));
for(const token of [...ids,'1800.00','opportunity:317','Manica','2026-09','MZN'])assert.ok(model.includes(token),token);
for(const token of ['financial_stamp','patient_transport','social_assistance_public','statutory_membership','author_rights','industrial_feed','special_tax_games','public_security'])assert.equal(model.includes(token),false);
assert.equal(book.result.rows.length,18);assert.equal(draft.currency,original.currency);assert.deepEqual(draft.selection_labels,original.selection_labels);
});
if(process.env.IVA_G2H_OUT)fs.writeFileSync(process.env.IVA_G2H_OUT,JSON.stringify(fixture().draft,null,2));
@@ -0,0 +1,49 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
import { onboardSupplyTreatments, supplyCategories, onboardSupplyIssue } from '../../resources/js/lib/iva-onboard-supplies.ts';
import { newSalesOperation, evaluateSalesOperation, recordSales, saveSalesBook, salesBook, salesCurrent } from '../../resources/js/lib/iva-operations.ts';
import { createProjectDossierReport } from '../../resources/js/lib/project-dossier-report.ts';
const frozen=JSON.parse(fs.readFileSync(new URL('./fixtures/iva-g4c-inputs.json',import.meta.url),'utf8'));
const positive=['provisions','fuel','beverages','cargo_products'];
const row=(rule,i)=>({...newSalesOperation(`g4d-${i}`,'2026-12','MZN'),description:`SYNTHETIC QA — ${rule.label}`,establishment:'SYNTHETIC QA estabelecimento',amount:'100',basis:i%2?'included':'net',treatment:rule.id,supplyCategory:positive[i],confirmed:rule.conditions.map((_,n)=>n),evidence:'SYNTHETIC QA — documento/pressuposto identifica bens postos a bordo, destino, embarcação/avião e actividade do operador; projecção, sem certificar despacho nem restituição'});
function fixture(){
const draft={...structuredClone(frozen),context_opportunity:'opportunity:326',project_title:'SYNTHETIC QA — G4D / Abastecimentos a bordo'};
const book=recordSales(draft,{currency:'MZN',rows:onboardSupplyTreatments.map(row),periods:[{period:'2026-12',complete:true}]});draft.modelo_a_snapshot=saveSalesBook(draft,book);return{draft,book};
}
test('four supply branches require each legal condition and identification; values with/without included VAT use existing motor',()=>{
assert.equal(onboardSupplyTreatments.length,4);
for(const[i,rule]of onboardSupplyTreatments.entries()){
const input=row(rule,i),result=evaluateSalesOperation(input,'MZN');assert.equal(result.field,'05');assert.equal(result.vat,'0.00');assert.equal(result.net,'100.00');assert.equal(result.gross,'100.00');
for(const missing of input.confirmed)assert.equal(evaluateSalesOperation({...input,confirmed:input.confirmed.filter(n=>n!==missing)},'MZN').vat,null);
for(const patch of [{amount:''},{evidence:''},{sourceCurrency:'USD'},{period:'2027-01'},{basis:''},{description:''},{establishment:''}])assert.equal(evaluateSalesOperation({...input,...patch},'MZN').vat,null);
}
});
test('article13 categories and exclusions are distinct: beverages do not cause automatic exemption or deduction',()=>{
for(const[i,rule]of onboardSupplyTreatments.entries())for(const[category]of supplyCategories){
const result=evaluateSalesOperation({...row(rule,i),supplyCategory:category},'MZN');
const excluded=i===1&&(category==='provisions'||category==='beverages'),refund=category==='beverages'&&(i===0||i===3);
if(excluded||refund){assert.equal(result.vat,null);assert.equal(result.net,null);assert.equal(result.field,null);assert.equal(result.rate,null);assert.match(result.reason,excluded?/excluídas/:/dedução ou restituição/);}
else assert.equal(result.vat,'0.00');
}
assert.match(onboardSupplyIssue('onboard_international_aircraft','beverages'),/20\(1\)\(d\)/);
assert.equal(onboardSupplyIssue('onboard_departing_warship','beverages'),null); // 13(2) lists c/d/h, not e.
for(const category of [undefined,'',null,'unknown'])for(const rule of onboardSupplyTreatments){const result=evaluateSalesOperation({...row(rule,0),supplyCategory:category},'MZN');assert.equal(result.vat,null);assert.match(result.reason,/Identifique a natureza/);}
});
test('changing category preserves price and historical result; unresolved beverage/provisions never turn into zero totals',()=>{
const{draft,book}=fixture();assert.equal(book.result.periods[0].fields['05'],'400.00');
for(const[index,category]of [[0,'beverages'],[1,'provisions'],[3,'']]){
const changed=recordSales(draft,{...book,rows:book.rows.map((r,i)=>i===index?{...r,supplyCategory:category,confirmed:[]}:r)});
assert.equal(changed.rows[index].amount,'100');assert.equal(changed.rows[index].sourceCurrency,'MZN');assert.equal(changed.rows[index].period,'2026-12');
assert.equal(changed.result.periods[0].fields['05'],null);assert.deepEqual(changed.history.at(-1),book.result);
const edited={...draft,modelo_a_snapshot:saveSalesBook(draft,{...book,rows:changed.rows})};assert.equal(salesCurrent(edited,salesBook(edited)),false);
}
});
test('QA snapshot and report retain category/context/source; all17 prior books stay identical/current without recalculation',()=>{
const{draft,book}=fixture();assert.ok(salesCurrent(draft,book));assert.deepEqual(salesBook(JSON.parse(JSON.stringify(draft))),JSON.parse(JSON.stringify(book)));
const before=JSON.parse(frozen.modelo_a_snapshot).salesOperations,after=JSON.parse(draft.modelo_a_snapshot).salesOperations;assert.equal(Object.keys(before).length,17);
for(const[context,original]of Object.entries(before)){assert.deepEqual(after[context],original);assert.ok(salesCurrent({...draft,context_opportunity:context},after[context]));}
const report=JSON.stringify(createProjectDossierReport(draft,{selectedSections:new Set(['finance']),version:'QA G4D'}));
for(const token of ['opportunity:326','Manica','2026-12','400.00','13(1)(c)','13(1)(d)','13(1)(e)','13(1)(h)','Natureza do abastecimento','Bebidas como provisões','QA G4D'])assert.ok(report.includes(token),token);
if(process.env.IVA_G4D_CALCULATED)fs.writeFileSync(process.env.IVA_G4D_CALCULATED,JSON.stringify(draft));
});

Some files were not shown because too many files have changed in this diff Show More