Prepare joint P104 delivery with explicit partial branch coverage

This commit is contained in:
2026-10-25 11:02:30 +02:00
parent 7b6a95a718
commit fab72d2e0c
2 changed files with 207 additions and 0 deletions
@@ -0,0 +1,176 @@
{
"status": "prepared_awaiting_fresh_preflight_backup_restore",
"candidate": "7b6a95a7181be5af622b0b665a31010ce93d6d5c",
"accepted_candidates": [
"7b6a95a7"
],
"base_installed": "a665ee9c974adb48706027e66fdd71b773d7358c",
"coverage_complete_branches": {
"AUD-SIM-L1-P104": "Procedimento operacional daTempo25/10:compra/venda segundo natureza/perspectiva;média comercial de referênciaBM na submissão;fonte,boletim,taxa,sentido,original/convertido e histórico conservados;excepções fiscais identificadas.Sem activarIVA/dedução/base de outros livros."
},
"branch_count_complete": 1,
"coverage_partial_branches": {
"AUD-SIM-L1-P084": "PedidoMF/AT→apresentado→decisão com despacho privado,número/data/emitente/âmbito→formulário com despacho;interesse público/fins sociais;correspondência específica do formulário não é presumida.",
"AUD-SIM-L1-P085": "Mesmo acompanhamento operacional com finalidade de atenuar calamidades e aquisição;sem extensão automática à importação;correspondência de formulário permanece parcial.",
"AUD-SIM-L1-P058": "Três percursos de veículos no regresso63:isenção/80%/separado50%;sem transplantarP059;bagagem/outros bens e remissão57(2)b por concluir;180dias exactos indeterminados."
},
"coverage_label": "ApenasP104 conta como novo ramo entregue;P058/P084/P085 continuam pendentes com cobertura parcial explícita.",
"runtime_delta": [
{
"path": "app/Http/Controllers/Api/V1/SimulationOfferDocumentController.php",
"sha256_LF": "b7359dcd66fa01e76d55ad729615f7cd4f0eb45ed88ec7b32d7997b8cfcb89c9"
},
{
"path": "app/Http/Middleware/EnsureSimulationRecoveryCookie.php",
"sha256_LF": "d10c2f54772233fcffe4f8f24c62a2282537bff1085d43ca7c1e8774070f5316"
},
{
"path": "resources/js/components/simulation-currency-events.tsx",
"sha256_LF": "4c81d2cd7e6835ee8102a8323991b494d8b52a21198a816c9f93f973c0da55b6"
},
{
"path": "resources/js/components/simulation-fx-selection.tsx",
"sha256_LF": "39bb6d87d404745b0b66349bc11626545a3672ae27321ce9b4658416592059bf"
},
{
"path": "resources/js/components/simulation-monthly-iva.tsx",
"sha256_LF": "b695e87089b08f987847e28413cd9bacca12b25f1171db4915f4a5dd082f5180"
},
{
"path": "resources/js/components/simulation-offer-preparations.tsx",
"sha256_LF": "9e70725e707ff4236f8edbaa965cb72d42407e010053a23f0e86bae7bbc2eaf7"
},
{
"path": "resources/js/components/simulation-offer-workflow.tsx",
"sha256_LF": "4cf2354d01b1f6c60598f1a495ee02946c5e565434078c61928ec7d13fe43cc6"
},
{
"path": "resources/js/components/simulation-returnees.tsx",
"sha256_LF": "a8b457344ec93d0db6d7a169b2f0b77dacb916b4943324a19b2580a893191cd4"
},
{
"path": "resources/js/components/simulation-travel-events.tsx",
"sha256_LF": "d5690d7abbb2b70653ec6cb42e75260347e7190c5d3a474983e6fd318d0606c4"
},
{
"path": "resources/js/lib/iva-currency-events.ts",
"sha256_LF": "cc9f2045d302d7987310da4006cc250fc5c99a27397918d166d649bfc32fab08"
},
{
"path": "resources/js/lib/iva-fx-selection.ts",
"sha256_LF": "9aa07ad443bc777b80510a3b5bd6aff9ddb9814d2450f3c690e531e74d71d998"
},
{
"path": "resources/js/lib/iva-offer-package.ts",
"sha256_LF": "240b274933e669a8c6def3b2324507c421bcd90ccbca82b58f6aab72cdeba5f5"
},
{
"path": "resources/js/lib/iva-offer-preparations.ts",
"sha256_LF": "b57abb97295493d0a9c3bb48941a7bb250f4fbec367a8b575afdbb14c32d1751"
},
{
"path": "resources/js/lib/iva-offer-workflow.ts",
"sha256_LF": "6ee9df722441639ab674b2457e5e9a075dc6ef326eab718d20295572297d5f86"
},
{
"path": "resources/js/lib/iva-returnees.ts",
"sha256_LF": "f91988669672e92527dba7e374fadebe71973f58a8459181d01e1684f10aab25"
},
{
"path": "resources/js/lib/project-dossier.ts",
"sha256_LF": "fc54a64b0e7bc218f30031355497c1ad98c84e5f2faf51945d5aa70e8f115864"
},
{
"path": "routes/api.php",
"sha256_LF": "f0b1b2b6943d23d27d54f6ffc58fd5caca46760ecec97a6da85faf477e5fef4e"
}
],
"documentary_delta": [
{
"path": "docs/investmoz/simulations/source-archive/Decreto-27-2026-BR123.pdf",
"sha256": "26249c3fa58f149c81de36e99d1aac2819a4771379d9e8833159660dabf539bb",
"state": "original archived;no automatic import,publication or fiscal activation"
},
{
"path": "docs/investmoz/simulations/source-archive/Decreto-37-2023-BR124.pdf",
"sha256": "7e680b191481faa0e2e9057fa5053587eb2a29d1d8c819e0eb9f02814255a04c",
"state": "original archived;no automatic import,publication or fiscal activation"
},
{
"path": "docs/investmoz/simulations/source-archive/Lei-17-2022-BR251-exemplar-MCNet5.pdf",
"sha256": "14eb34f0af91a8f5cb1770c7b52d6ff839c6818302d1ed96d79afbfb9fe999d4",
"state": "original archived;no automatic import,publication or fiscal activation"
},
{
"path": "docs/investmoz/simulations/source-archive/Lei-17-2022-IPP-BR250-Parlamento.pdf",
"sha256": "978cd22403ffd336a631704ecd7a5bbd814a427c815b9acdaca5515591dd9e2a",
"state": "original archived;no automatic import,publication or fiscal activation"
}
],
"compiled_delta_markers_expected": [
"submissionDate",
"bulletinPerspective",
"fxSelection",
"scopeConfirmed",
"formDecisionHash",
"returneeImports",
"ownershipAssessment",
"Pedido → decisão → formulário com despacho",
"Conferir selecção e impacto",
"Confirmar selecção nesta linha",
"Recuperar anexos privados desta gravação",
"Preparar formulário com despacho associado",
"Regresso definitivo — veículos (P058, cobertura parcial)",
"Sem cálculo de IVA ou dedução",
"Continuidade do trabalho fiscal:",
"sem calcular IVA devido ou dedução",
"Cobertura digital deste incremento:",
"Não representa cobertura digital integral"
],
"counts_before": {
"delivered": 127,
"QA": 1,
"functional_pending": 4,
"documentary": 1,
"total": 133
},
"counts_current": {
"delivered": 127,
"QA": 1,
"functional_pending": 4,
"documentary": 1,
"total": 133
},
"counts_after_delivery": {
"delivered": 128,
"QA": 0,
"functional_pending": 4,
"documentary": 1,
"total": 133
},
"QA_proofs_reused": [
"iva-l1-tempo-offers-fx-qa-20261025.json"
],
"authorization": "Tempo25/10 pede entrega conjunta da candidata7b6a95a7,separandoP104concluído deP058/P084/P085parciais;preservar históricos/conferir sódelta.",
"preservation": "127fechos/dados/configuração/permissões/originais/relações/históricos conservados;nenhuma perda confirmada;provasQA75frontend/API2/37,types/build/UI reutilizadas.",
"limitations_balance": [
"P104 é procedimento operacional da Tempo,não atribuição àLei2/2006 de uma regra cambial não demonstrada;excepção fiscal identificada por disposição/âmbito/taxa/data",
"Não activa cálculo de IVA,dedução ou reavaliação de livros anteriores;conversão reutiliza aritmética existente a seis casas decimais,sem nova regra de arredondamento fiscal",
"P084/P085 não são fechados por este avanço;ZIP contém preparação e anexos,não recibo de submissão nem formulário oficial inventado",
"Anexos privados reutilizamdocuments/scan existente;sem migração;pendente de scan impede descarga,sem criar certificado fiscal",
"P058 é parcial;bagagem e remissões por concluir;sem extensão das condiçõesP059",
"Formais digitais e cálculo fiscal de viagens/eventos mantêm limitações aceites;bebidasL2/L3,Estatísticas/IAadiadas;L1aberto"
],
"remaining_ids": [
"P047",
"P058",
"P084",
"P085",
"P001"
],
"P104_closure": "operational_scope_defined_by_Tempo_only",
"P084_P085_closure": false,
"P058_closure": false,
"L1": "open",
"containment": "l1-tempo-offers-fx-readonly-rollback-20261025.patch verified without applying;retains readers/history/downloads and unrelated branches;previous release retained"
}
@@ -0,0 +1,31 @@
--- a/resources/js/lib/iva-currency-events.ts
+++ b/resources/js/lib/iva-currency-events.ts
@@ -99,5 +99,5 @@
}
function key(draft:Record<string,unknown>,book:CurrencyEventBook):string{return JSON.stringify({version:currencyEventVersion,scope:acquisitionScope(draft),location:draft.selection_labels??{},rows:book.rows});}
export function currencyEventCurrent(draft:Record<string,unknown>,book:CurrencyEventBook):boolean{return!!book.result&&book.result.sourceKey===key(draft,book);}
-export function recordCurrencyEvents(draft:Record<string,unknown>,book:CurrencyEventBook):CurrencyEventBook{if(!book.rows.length||new Set(book.rows.map(r=>r.id)).size!==book.rows.length)throw new Error('Indique operações com identidades distintas;originais conservados.');const result:CurrencyEventCalculation={version:currencyEventVersion,revision:(book.result?.revision??0)+1,calculatedAt:new Date().toISOString(),opportunity:acquisitionScope(draft),location:JSON.stringify(draft.selection_labels??{}),sourceKey:key(draft,book),source:currencyEventSource,inputs:structuredClone(book.rows),rows:book.rows.map(evaluateCurrencyEvent)};const next={...book,result,history:[...(book.history??[]),...(book.result?[book.result]:[])]};saveCurrencyEventBook(draft,next);return next;}
+export function recordCurrencyEvents(draft:Record<string,unknown>,book:CurrencyEventBook):CurrencyEventBook{if(book.rows.some(row=>row.treatment==='foreign_scenario'&&row.fxSelection))throw new Error('Novas versões operacionaisP104 temporariamente suspensas;históricos e outros eventos conservados.');if(!book.rows.length||new Set(book.rows.map(r=>r.id)).size!==book.rows.length)throw new Error('Indique operações com identidades distintas;originais conservados.');const result:CurrencyEventCalculation={version:currencyEventVersion,revision:(book.result?.revision??0)+1,calculatedAt:new Date().toISOString(),opportunity:acquisitionScope(draft),location:JSON.stringify(draft.selection_labels??{}),sourceKey:key(draft,book),source:currencyEventSource,inputs:structuredClone(book.rows),rows:book.rows.map(evaluateCurrencyEvent)};const next={...book,result,history:[...(book.history??[]),...(book.result?[book.result]:[])]};saveCurrencyEventBook(draft,next);return next;}
export function currencyEventReportRows(draft:Record<string,unknown>):Array<[string,string,string,string]>{try{const book=currencyEventBook(draft),r=book.result;if(!r)return[];return r.inputs.map((row,i):[string,string,string,string]=>{if(row.treatment==='foreign_scenario'&&row.fxSelection)return['IVA mensal',`P104 — ${row.period} — ${row.id}`,`${row.description};${r.rows[i].reason};Original:${row.amount} ${row.sourceCurrency};Convertido:${r.rows[i].scenarioAmount??'Indeterminado'} MZN`,`${r.opportunity};${currencyEventCurrent(draft,book)?'Resultado actual':'Entradas alteradas;resultado histórico conservado'};versão${r.revision};${r.calculatedAt};documento:${row.documentRef},${row.documentDate};âmbito:${row.scope};boletim:${row.fxSelection.bulletinRef};fonte:${row.fxSelection.source};natureza:${row.fxSelection.nature};perspectiva:${row.fxSelection.bulletinPerspective};relação:${row.fxSelection.relation};taxa:${row.fxRate};data:${row.fxDate};sentido:${row.fxDirection};regra/excepção:${row.fxRuleRef};sem base/IVA/dedução activados.`];return['IVA mensal',`${currencyEventTreatments.find(t=>t.id===row.treatment)?.branch??'Evento'} — ${row.period} — ${row.id}`,`${row.description};${r.rows[i].reason};facto gerador:${r.rows[i].eventDate??'Indeterminado/não apurado'};parcelas:${r.rows[i].dueEvents.map(p=>p.date+': '+(p.amount??'Montante indeterminado')+' '+row.currency+' ('+p.reason+')').join('; ')||'Nenhuma apurada'};restante pendente:${r.rows[i].status==='indeterminate'?'Indeterminado':r.rows[i].remainingPending?'Sim':'Não'};${row.treatment==='foreign_scenario'&&r.rows[i].status==='determined'?'conversão operacional':'cenário condicionado'}:${r.rows[i].scenarioAmount??'Indeterminado'};base/IVA:Indeterminados`,`${r.opportunity};${r.location};${currencyEventCurrent(draft,book)?'Resultado actual':'Entradas alteradas;resultado histórico conservado'};versão${r.revision};${r.calculatedAt};${r.source};${row.origin};documento ${row.documentRef},${row.documentDate};ambito ${row.scope};${row.treatment==='foreign_scenario'?`origem ${row.amount} ${row.sourceCurrency};taxa ${row.fxRate},${row.fxDirection},${row.fxDate};fonte ${row.fxSource};pressuposto ${row.fxRuleRef}`:`evento ${row.eventDate},${row.eventRef};outra data ${row.otherDate};conferencia ${row.reviewDate};factura ${row.invoiceRequired},${row.invoiceState},${row.invoiceDate},${row.invoiceRef};prazo ${row.legalDeadline},${row.deadlineRef};recebimento ${row.paymentState},${row.paymentDate},${row.paymentAmount},${row.paymentRef};total do ambito ${row.amount} ${row.currency}`};fundamento ${row.evidence};sem nova dedução/campo11/IVA ou activação cambial nos livros anteriores.`];});}catch{return[['IVA mensal','Moeda/eventos','Dados não recuperáveis','Originais preservados;sem substituição porzero.']];}}
--- a/resources/js/lib/iva-offer-workflow.ts
+++ b/resources/js/lib/iva-offer-workflow.ts
@@ -8,7 +8,7 @@
export function offerWrittenRequest(row:OfferPreparation,w:OfferWorkflow):string{return`Ao ${w.recipient}\nAssunto:Pedido de isenção — ${row.branch}\nEntidade/destinatário:${row.beneficiary}\nFinalidade:${row.purpose}\n${row.branch==='P084'?'Justificação do interesse público/fins sociais:'+row.evidence:'Calamidade:'+row.disaster+';finalidade humanitária:'+row.humanitarianPurpose}\nBens:${row.description}\nOperação:${row.operation};período:${row.period};valor de referência:${row.amount} ${row.currency}\nDocumentos:${row.availableDocuments||row.documentRef}\n${w.writtenRequest}\nPreparação InvesteMoz;a apresentação ocorre fora do portal. Não constitui concessão.`;}
export function offerWorkflowApplied(row:OfferPreparation):{applied:boolean;reason:string}{const w=row.workflow,r=row.request;if(!w||!r||r.state!=='granted')return{applied:false,reason:'Sem despacho de deferimento registado;mantém-se hipótese condicionada.'};if(!r.decisionRef.trim()||!validDate(r.decisionOn)||!w.decisionIssuer.trim()||!offerAttachmentValid(w.decisionAttachment))return{applied:false,reason:'Despacho recebido incompleto:número,data,emitente e anexo por registar.'};if(w.scopeConfirmed!=='yes'||w.scopeKey!==offerScopeKey(row))return{applied:false,reason:'Correspondência desta linha ao âmbito do despacho não confirmada ou dados alterados;sem extensão automática.'};if((!r.operationScope?.trim()&&r.operation&&r.operation!==row.operation)||(!r.periodScope?.trim()&&/^\d{4}-\d{2}$/.test(row.period)&&(row.period<r.periodFrom.slice(0,7)||row.period>r.periodTo.slice(0,7))))return{applied:false,reason:'A operação ou o período desta linha está fora do âmbito expresso do despacho;sem extensão automática.'};const conditions=row.branch==='P084'?[row.nationalInstitution,row.publicSocialInstitution,row.goodsSuitable,row.publicInterestUse]:[row.mitigation];if(conditions.some(v=>v!=='yes')||!row.description||!row.beneficiary||!row.purpose||!row.operation||(row.branch==='P085'&&(row.operation!=='acquisition'||!row.disaster||!row.humanitarianPurpose)))return{applied:false,reason:'Condições próprias do tratamento por demonstrar;despacho não alarga o fundamento legal.'};return{applied:true,reason:`Tratamento deferido apenas nesta linha:${r.goods};${r.operationScope||r.operation};${r.periodScope||r.periodFrom+' a '+r.periodTo};condições:${r.conditions}. Despacho${r.decisionRef},${r.decisionOn},${w.decisionIssuer}. Sem extensão às restantes linhas,períodos ou oportunidades;sem dedução automática.`};}
function validDate(v:string){const d=new Date(v+'T00:00:00Z');return /^\d{4}-\d{2}-\d{2}$/.test(v)&&Number.isFinite(d.getTime())&&d.toISOString().slice(0,10)===v;}
-export function recordOfferWorkflow(row:OfferPreparation,stage:'request'|'presented'|'decision'|'form'):OfferPreparation{
+export function recordOfferWorkflow(row:OfferPreparation,stage:'request'|'presented'|'decision'|'form'):OfferPreparation{throw new Error('Novos estados do percurso de ofertas temporariamente suspensos;rascunhos,anexos e históricos conservados.');
const w=structuredClone(row.workflow??emptyOfferWorkflow()),r=structuredClone(row.request);if(!r)throw Error('Prepare primeiro o pedido.');
if(!w.recipient.trim()||!row.beneficiary.trim()||!row.description.trim()||!row.purpose.trim()||!row.operation)throw Error('Indique entidade,finalidade,bens,operação e destinatário do pedido;rascunho incompleto pode ser guardado.');
if(stage==='presented'&&(!r.reference.trim()||!validDate(r.presentedOn)||r.state!=='presented'))throw Error('Registe referência,data e estado apresentado;submissão fora do InvesteMoz.');
--- a/resources/js/lib/iva-returnees.ts
+++ b/resources/js/lib/iva-returnees.ts
@@ -41,7 +41,7 @@
}
function key(draft:Record<string,unknown>,b:ReturneeBook){return JSON.stringify({version:1,scope:acquisitionScope(draft),currency:draft.currency,location:draft.selection_labels??{},rows:b.rows});}
export function returneeCurrent(draft:Record<string,unknown>,b:ReturneeBook){return !!b.result&&b.result.sourceKey===key(draft,b);}
-export function recordReturnees(draft:Record<string,unknown>,b:ReturneeBook):ReturneeBook{
+export function recordReturnees(draft:Record<string,unknown>,b:ReturneeBook):ReturneeBook{throw new Error('Novas versões parciaisP058 temporariamente suspensas;histórico e originais conservados.');
if(!b.rows.length||new Set(b.rows.map(r=>r.id)).size!==b.rows.length)throw Error('Identifique linhas distintas;originais preservados.');
const rows=b.rows.map(r=>evaluateReturnee(r,draft.currency));for(let i=0;i<b.rows.length;i++){const r=b.rows[i];if(!['exempt','reduced'].includes(rows[i].status))continue;if(b.rows.some((peer,j)=>j!==i&&peer.beneficiary===r.beneficiary&&peer.origin===r.origin&&date(peer.importDate)&&evaluateReturnee(peer,draft.currency).status!=='not_applicable'&&(peer.importDate<=r.importDate?r.importDate<years(peer.importDate,5):peer.importDate<years(r.importDate,5))))rows[i]={...rows[i],status:'indeterminate',importVat:null,reason:'Mais de uma linha usa o mesmo direito de veículo em cinco anos;conferir o conjunto e histórico externo,sem dupla utilização.'};}
const result:Result={revision:(b.result?.revision??0)+1,calculatedAt:new Date().toISOString(),sourceKey:key(draft,b),inputs:structuredClone(b.rows),rows};const next={...b,result,history:[...(b.history??[]),...(b.result?[b.result]:[])]};saveReturneeBook(draft,next);return next;