fix: complete InvesteMoz validation and error corrections

This commit is contained in:
2026-10-29 21:47:33 +02:00
parent 63147312e2
commit daf8623441
718 changed files with 127308 additions and 20959 deletions
@@ -1,22 +1,27 @@
<?php
use App\Support\IsolatedQaDatabase;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
return new class extends Migration
{
public function up(): void
{
if (!config('investment-zone-profile.authenticated_installation')) { throw new RuntimeException('Use a ação autenticada de instalação nominal da ficha.'); }
Schema::table('investment_zones',fn(Blueprint $table)=>$table->text('editorial_draft')->nullable());
if (! config('investment-zone-profile.authenticated_installation') && ! IsolatedQaDatabase::allowsSchemaChanges()) {
throw new RuntimeException('Use a ação autenticada de instalação nominal da ficha.');
}
Schema::table('investment_zones', fn (Blueprint $table) => $table->text('editorial_draft')->nullable());
}
public function down(): void
{
if (DB::table('investment_zones')->whereNotNull('editorial_draft')->exists()
|| DB::table('investment_zone_revisions')->where('action','profile_prepared')->exists()) {
|| DB::table('investment_zone_revisions')->where('action', 'profile_prepared')->exists()) {
throw new RuntimeException('Reversão parcial compatível: preservar coluna e histórico após utilização da ficha.');
}
Schema::table('investment_zones',fn(Blueprint $table)=>$table->dropColumn('editorial_draft'));
Schema::table('investment_zones', fn (Blueprint $table) => $table->dropColumn('editorial_draft'));
}
};
@@ -1,22 +1,29 @@
<?php
use App\Support\IsolatedQaDatabase;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
return new class extends Migration
{
public function up(): void
{
if(!config('investment-zone-details.authenticated_installation')){throw new RuntimeException('Use a instalação autenticada nominal L1.');}
if(!Schema::hasColumn('investment_zones','editorial_draft') || !DB::table('migrations')->where('migration','2026_10_16_130000_add_investment_zone_editorial_draft')->exists()){throw new RuntimeException('Instale/verifique primeiro a base 130000.');}
Schema::table('investment_zones',fn(Blueprint $table)=>$table->jsonb('operational_details')->nullable());
if (! config('investment-zone-details.authenticated_installation') && ! IsolatedQaDatabase::allowsSchemaChanges()) {
throw new RuntimeException('Use a instalação autenticada nominal L1.');
}
if (! Schema::hasColumn('investment_zones', 'editorial_draft') || ! DB::table('migrations')->where('migration', '2026_10_16_130000_add_investment_zone_editorial_draft')->exists()) {
throw new RuntimeException('Instale/verifique primeiro a base 130000.');
}
Schema::table('investment_zones', fn (Blueprint $table) => $table->jsonb('operational_details')->nullable());
}
public function down(): void
{
if(DB::table('investment_zones')->whereNotNull('operational_details')->exists() || DB::table('investment_zone_revisions')->whereIn('action',['profile_prepared','published'])->exists()){
if (DB::table('investment_zones')->whereNotNull('operational_details')->exists() || DB::table('investment_zone_revisions')->whereIn('action', ['profile_prepared', 'published'])->exists()) {
throw new RuntimeException('Reversão compatível: preserve os detalhes, preparação privada e versões públicas após utilização.');
}
Schema::table('investment_zones',fn(Blueprint $table)=>$table->dropColumn('operational_details'));
Schema::table('investment_zones', fn (Blueprint $table) => $table->dropColumn('operational_details'));
}
};
@@ -1,5 +1,6 @@
<?php
use App\Support\IsolatedQaDatabase;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
@@ -8,7 +9,7 @@ return new class extends Migration
{
public function up(): void
{
if (! config('investor-context.authenticated_installation')) {
if (! config('investor-context.authenticated_installation') && ! IsolatedQaDatabase::allowsSchemaChanges()) {
throw new RuntimeException('Use a ação autenticada nominal de instalação do contexto.');
}
Schema::create('investor_navigation_preferences', function (Blueprint $t) {
@@ -1,5 +1,6 @@
<?php
use App\Support\IsolatedQaDatabase;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
@@ -9,7 +10,9 @@ return new class extends Migration
{
public function up(): void
{
if (!config('editorial.authenticated_installation')) { throw new RuntimeException('Use a instalação editorial autenticada.'); }
if (! config('editorial.authenticated_installation') && ! IsolatedQaDatabase::allowsSchemaChanges()) {
throw new RuntimeException('Use a instalação editorial autenticada.');
}
Schema::table('portal_resources', fn (Blueprint $t) => $t->jsonb('editorial_content')->nullable());
}
@@ -9,7 +9,7 @@ return new class extends Migration
public function up(): void
{
Schema::create('proactive_supply_sources', function ($t) {
$t->char('sha256',64)->primary();
$t->char('sha256', 64)->primary();
$t->text('name');
$t->text('period');
$t->text('limitations');
@@ -17,23 +17,25 @@ return new class extends Migration
$t->timestampTz('imported_at');
});
Schema::create('proactive_supply_observations', function ($t) {
$t->char('id',64)->primary();
$t->char('source_hash',64);
$t->char('id', 64)->primary();
$t->char('source_hash', 64);
$t->foreign('source_hash')->references('sha256')->on('proactive_supply_sources')->restrictOnDelete();
$t->text('sheet');
$t->integer('row_number');
$t->char('entity_key',64)->index();
foreach (['name','province','district','cae','activity','sector','source_date'] as $field) $t->text($field);
$t->char('fingerprint',64)->index();
$t->char('duplicate_of',64)->nullable();
$t->char('entity_key', 64)->index();
foreach (['name', 'province', 'district', 'cae', 'activity', 'sector', 'source_date'] as $field) {
$t->text($field);
}
$t->char('fingerprint', 64)->index();
$t->char('duplicate_of', 64)->nullable();
$t->boolean('identity_conflict')->default(false);
$t->uuid('territory_id')->nullable()->index();
$t->text('territory_resolution');
$t->index(['province','district']);
$t->unique(['source_hash','sheet','row_number']);
$t->index(['province', 'district']);
$t->unique(['source_hash', 'sheet', 'row_number']);
});
// Technical defence of the private-analysis scope, not a new business role.
foreach (['proactive_supply_sources','proactive_supply_observations'] as $table) {
foreach (['proactive_supply_sources', 'proactive_supply_observations'] as $table) {
DB::statement("ALTER TABLE {$table} ENABLE ROW LEVEL SECURITY");
DB::statement("ALTER TABLE {$table} FORCE ROW LEVEL SECURITY");
DB::statement("CREATE POLICY {$table}_private_read ON {$table} FOR SELECT USING (current_setting('app.proactive_supply_read',true)='internal' AND NULLIF(current_setting('app.actor_user_id',true),'')::bigint IS NOT NULL)");
@@ -42,7 +44,9 @@ return new class extends Migration
public function down(): void
{
if (DB::table('proactive_supply_sources')->exists()) throw new RuntimeException('Preserve imported source history before rollback.');
if (DB::table('proactive_supply_sources')->exists()) {
throw new RuntimeException('Preserve imported source history before rollback.');
}
Schema::dropIfExists('proactive_supply_observations');
Schema::dropIfExists('proactive_supply_sources');
}
+37 -34
View File
@@ -1,38 +1,41 @@
{
"rule_code": "IVA-GERAL-BASE-LIQUIDA",
"rule_version": 1,
"component": "IVA",
"scope_key": "mz.internal-general-net.mzn",
"valid_from": "2023-01-01",
"valid_until": null,
"source_sha256": "ea1b0dc6f5cf6e595f6d9a19e7042f398999e0087caef1785f6e8fac571b5f53",
"rule_definition": {
"language": "investmoz.tax.v1",
"nodes": {
"base": {"op": "input", "key": "base_tributavel"},
"rate": {"op": "parameter", "key": "iva_general_rate"},
"hundred": {"op": "literal", "value": "100"},
"product": {"op": "multiply", "args": ["base", "rate"]},
"intermediate": {"op": "divide", "args": ["product", "hundred"]}
"rule_code": "IVA-GERAL-BASE-LIQUIDA",
"rule_version": 1,
"component": "IVA",
"scope_key": "mz.internal-general-net.mzn",
"valid_from": "2023-01-01",
"valid_until": null,
"source_sha256": "ea1b0dc6f5cf6e595f6d9a19e7042f398999e0087caef1785f6e8fac571b5f53",
"rule_definition": {
"language": "investmoz.tax.v1",
"nodes": {
"base": { "op": "input", "key": "base_tributavel" },
"rate": { "op": "parameter", "key": "iva_general_rate" },
"hundred": { "op": "literal", "value": "100" },
"product": { "op": "multiply", "args": ["base", "rate"] },
"intermediate": { "op": "divide", "args": ["product", "hundred"] }
},
"result": "intermediate"
},
"result": "intermediate"
},
"parameters": {
"IVA_GENERAL_RATE": {
"value": "16",
"unit": "percent",
"conditions": {"operation": "internal_general_net", "currency": "MZN"}
"parameters": {
"IVA_GENERAL_RATE": {
"value": "16",
"unit": "percent",
"conditions": {
"operation": "internal_general_net",
"currency": "MZN"
}
}
},
"rounding_policy": {
"status": "not_applied",
"precision": "exact_decimal",
"method": "none",
"ties": "not_applicable_without_rounding",
"aggregation": "single_declared_taxable_base",
"purpose": "operation_tax_not_payment",
"evidence": "Orientação expressa Tempo: calcular este lote IVA sem arredondamento automático; ficha v1.2",
"coverage_start": "2026-01-01",
"coverage_end": "2026-12-31"
}
},
"rounding_policy": {
"status": "not_applied",
"precision": "exact_decimal",
"method": "none",
"ties": "not_applicable_without_rounding",
"aggregation": "single_declared_taxable_base",
"purpose": "operation_tax_not_payment",
"evidence": "Orientação expressa Tempo: calcular este lote IVA sem arredondamento automático; ficha v1.2",
"coverage_start": "2026-01-01",
"coverage_end": "2026-12-31"
}
}