Authorize grouped installer after authenticated backup and isolated restore
tests / ci (push) Canceled after 0s

This commit is contained in:
2026-10-25 11:04:59 +02:00
parent fab72d2e0c
commit e38aa74920
2 changed files with 76 additions and 9 deletions
@@ -1,5 +1,5 @@
{
"status": "prepared_awaiting_fresh_preflight_backup_restore",
"status": "ready_after_fresh_authenticated_preflight_and_verified_backup_restore",
"candidate": "7b6a95a7181be5af622b0b665a31010ce93d6d5c",
"accepted_candidates": [
"7b6a95a7"
@@ -172,5 +172,70 @@
"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"
"containment": "l1-tempo-offers-fx-readonly-rollback-20261025.patch verified without applying;retains readers/history/downloads and unrelated branches;previous release retained",
"authenticated_preflight": {
"installed": {
"status": "installed",
"commit": "a665ee9c974adb48706027e66fdd71b773d7358c",
"release": "/var/www/investmoz-homologacao/releases/a665ee9c974adb48706027e66fdd71b773d7358c-67adcc0e",
"previous_release": "/var/www/investmoz-homologacao/releases/a48e9749799b7ed0ad370e23c2fda2bab06150d0-4bcb51fd",
"database_migrations": 0,
"content_imports": 0
},
"current_link": "/var/www/investmoz-homologacao/releases/a665ee9c974adb48706027e66fdd71b773d7358c-67adcc0e",
"release_revision": {
"commit": "a665ee9c974adb48706027e66fdd71b773d7358c",
"branch": "main",
"built_at": "2026-10-25T08:24:49.843479+00:00",
"manifest_sha256": "4aa78f9db6db6dcf31222b9bff45f5dfbaa0dc071225fcc3de4f0f02f0d03cd8"
},
"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-tempo-offers-fx-delivery-20261025/backup",
"target": {
"database": "teste_investidor",
"port": 5432
},
"tables": 174,
"files_verified": 369,
"dump_sha256": "15f6d2f8bee7c1b21ba02406e311d1a6e203dfe3081aa84997c3057ea19c2a73",
"files_sha256": "bb0db583f66e8f890808573a7f63d36f67242306f90cab2a3dc07e412ee6edef",
"restore_verified": false
},
"restore": {
"restore_verified": true,
"tables_verified": 174,
"container_network": "none",
"database": "l1_tempo_offers_fx_restore_20261025",
"port": 55441,
"source_dump_sha256": "15f6d2f8bee7c1b21ba02406e311d1a6e203dfe3081aa84997c3057ea19c2a73",
"active_database_writes": 0
}
}
}
@@ -1,12 +1,14 @@
--- 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.']];}}
@@ -44,7 +44,7 @@
if(!/^2026-(0[1-9]|1[0-2])$/.test(row.period)||!['projected','effective'].includes(row.origin)||date(row.documentDate)===null||![row.description,row.operationRef,row.documentRef,row.scope,row.evidence].every(v=>!!v.trim()))return stop('Identifique mês de contexto2026,operação,documento/data,âmbito e factos ou pressupostos expressos.');
if(row.factsConfirmed==='no')return stop('Os factos declarados afastam este percurso;sem isenção ou IVA zero por defeito.','not_applicable');
if(row.factsConfirmed!=='yes')return stop('Factos do percurso por esclarecer;não usar datas ou câmbio por defeito.');
- if(row.treatment==='foreign_scenario'){
+ if(row.treatment==='foreign_scenario'){if(row.fxSelection)return stop('Novas conversões operacionaisP104 temporariamente suspensas;históricos e outros eventos conservados.');
const amount=decimal(row.amount),fx=decimal(row.fxRate,8);
if(row.currency!=='MZN'||!['USD','EUR','ZAR','GBP','CNY','BRL','JPY','CHF','AUD','CAD'].includes(row.sourceCurrency)||amount===null||fx===null||fx===0n||date(row.fxDate)===null||![row.fxSource,row.fxRuleRef].every(v=>!!v.trim())||!['mzn_per_unit','units_per_mzn'].includes(row.fxDirection))return stop('Indique moeda original,valor,taxa positiva,direcção,data,fonte e regra/pressuposto expresso.Sem substituir moeda original porMZN ou reutilizar taxa de apresentação como regra fiscal.');
result.scenarioAmount=money(row.fxDirection==='mzn_per_unit'?convertScaledAmount(amount,fx,100000000n):(amount*100000000n+fx/2n)/fx);
--- a/resources/js/lib/iva-offer-workflow.ts
+++ b/resources/js/lib/iva-offer-workflow.ts
@@ -8,7 +8,7 @@