feat(iva): add conditional public official and asset-sale operations in QA
This commit is contained in:
@@ -6071,5 +6071,54 @@
|
||||
"installed-public-delta.json": "acc8b07511849899eb2523dbda007fe215c17ba41af655196770a00cfe7c452d",
|
||||
"manifest-served.json": "b92bc7b64176675274dd934bb683f09c4a4ca3c4fe690dfce06425e89a7f3e04"
|
||||
}
|
||||
},
|
||||
"iva_l1_g2_conditional_qa_20261024": {
|
||||
"candidate": "CANDIDATE_G2G",
|
||||
"base_delivered": "9a56d982",
|
||||
"base_receipt": "541ea704",
|
||||
"status": "demonstrated_QA_not_installed",
|
||||
"group": "G2G within G2",
|
||||
"branches": [
|
||||
"AUD-SIM-L1-P010",
|
||||
"AUD-SIM-L1-P027",
|
||||
"AUD-SIM-L1-P031",
|
||||
"AUD-SIM-L1-P032"
|
||||
],
|
||||
"treatments": [
|
||||
"public_security",
|
||||
"official_military_supplies",
|
||||
"sisa_subject_operation",
|
||||
"exempt_activity_asset_sale",
|
||||
"no_deduction_right_asset_sale",
|
||||
"excluded_deduction_asset_sale"
|
||||
],
|
||||
"scope": "2026/MZN;9(2)b/9(11)/9(12)d-e;19(1)/20;field07",
|
||||
"tests": {
|
||||
"frontend": 2,
|
||||
"api_tests": 1,
|
||||
"api_assertions": 16,
|
||||
"UI_to_API_to_report": true,
|
||||
"types": "passed",
|
||||
"build": "passed"
|
||||
},
|
||||
"preservation": "Seven frozen books unchanged/current without recalculation;17delivered matrix rows and all prior receipt objects unchanged",
|
||||
"counts": {
|
||||
"delivered": 24,
|
||||
"demonstrated_QA": 4,
|
||||
"functional_pending": 104,
|
||||
"documentary_pending": 1,
|
||||
"total": 133
|
||||
},
|
||||
"homologation_unchanged": true,
|
||||
"P001_blocks_independent": false,
|
||||
"L1_complete": false,
|
||||
"artifacts": {
|
||||
"api-ui-tests.xml": "512862d16b2a8d685c59519dadda4d08b500a946a158d465fc40065f381131a2",
|
||||
"conditional-model.json": "8eda14c87fa3aad0971ed79fe3bf61757c98ead626fb450d162cdaf87ce32308",
|
||||
"conditional-report.html": "ade6ad059c0350c8b1386f6a29358113e6a07ed67401a892405123956c163ef5",
|
||||
"recovered.json": "93b4f17e30a40a6de01536b62bf00d08b6d3f60d9ed4dcb697e495983c529cd5",
|
||||
"report-qa.png": "7f9e4bf3c76e258f1cf6729589ffbbadb48bae0f9c6ac543d75cee24dcc3c0f0",
|
||||
"ui-calculated.json": "bb8fa5ca332e5fc6e556984cb4a853255fbb4fb72f2b4e8c4ae3e71226bbbdb8"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
# Rastreabilidade, utilização e formação
|
||||
|
||||
## 24/10/2026 — G2G condicionado demonstrado em QA
|
||||
|
||||
**Candidata CANDIDATE_G2G; 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.
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -33,6 +33,12 @@ const culturalTreatments:OperationTreatment[] = ([false,true] as const).flatMap(
|
||||
});
|
||||
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']});
|
||||
export const operationTreatments:OperationTreatment[] = [
|
||||
{...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']},
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -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));
|
||||
Reference in New Issue
Block a user