116 lines
5.4 KiB
PHP
116 lines
5.4 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Services\SimulationFiscalQaPreview;
|
|
use App\Services\SimulationTaxParameterResolver;
|
|
use App\Services\SimulationTaxRuleExpression;
|
|
use App\Services\SimulationTaxRuleGovernance;
|
|
use App\Support\IsolatedQaDatabase;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Validator;
|
|
use Illuminate\Validation\ValidationException;
|
|
use InvalidArgumentException;
|
|
|
|
class SimulationTaxRuleGovernanceController extends Controller
|
|
{
|
|
public function qaPreview(Request $request, string $id, SimulationFiscalQaPreview $preview): JsonResponse
|
|
{
|
|
abort_unless(IsolatedQaDatabase::allowsSchemaChanges(), 404);
|
|
$key = $request->header('Idempotency-Key');
|
|
abort_unless(is_string($key) && strlen($key) >= 16 && strlen($key) <= 128, 428, 'Idempotency-Key é obrigatório.');
|
|
$input = $request->validate([
|
|
'base' => ['required', 'string', 'max:40', 'regex:/^(?:0|[1-9][0-9]*)(?:\.[0-9]+)?$/D'],
|
|
'reference_date' => ['required', 'date_format:Y-m-d'],
|
|
'currency' => ['required', 'in:MZN'],
|
|
'operation' => ['required', 'in:internal_general_net'],
|
|
]);
|
|
$result = $preview->create($request->user(), $id, $input, $key);
|
|
$simulation = $result['simulation'];
|
|
|
|
return response()->json(['data' => $simulation, 'replayed' => $result['replayed']], $result['replayed'] ? 200 : 202)
|
|
->header('Location', url('/api/v1/simulations/'.$simulation->id));
|
|
}
|
|
|
|
public function index(Request $request, SimulationTaxRuleGovernance $governance): JsonResponse
|
|
{
|
|
$filters = $request->validate([
|
|
'rule_code' => ['nullable', 'string', 'max:64'],
|
|
'component' => ['nullable', 'in:IRPC,IVA,ISPC,IRPS,INSS,RETENCOES,DIREITOS_ADUANEIROS,ICE'],
|
|
'scope_key' => ['nullable', 'string', 'max:160'],
|
|
'status' => ['nullable', 'in:draft,submitted,reviewed,rejected,approved,published,suspended,archived'],
|
|
'per_page' => ['nullable', 'integer', 'between:1,100'],
|
|
]);
|
|
|
|
return response()->json($governance->listing($request->user(), $filters));
|
|
}
|
|
|
|
public function store(Request $request, SimulationTaxRuleGovernance $governance): JsonResponse
|
|
{
|
|
$rule = $governance->create($request->user(), $this->validatedRule($request));
|
|
|
|
return response()->json($rule, 201)->header('Location', url('/api/v2/investment/admin/tax-rules/'.$rule->id));
|
|
}
|
|
|
|
public function show(Request $request, SimulationTaxRuleGovernance $governance, string $id): JsonResponse
|
|
{
|
|
return response()->json($governance->show($request->user(), $id));
|
|
}
|
|
|
|
public function update(Request $request, SimulationTaxRuleGovernance $governance, string $id): JsonResponse
|
|
{
|
|
$data = $request->validate(['version_no' => ['required', 'integer', 'min:1']]);
|
|
|
|
return response()->json($governance->update($request->user(), $id, (int) $data['version_no'], $this->validatedRule($request)));
|
|
}
|
|
|
|
public function transition(Request $request, SimulationTaxRuleGovernance $governance, string $id, string $action): JsonResponse
|
|
{
|
|
$data = $request->validate([
|
|
'version_no' => ['required', 'integer', 'min:1'],
|
|
'evidence' => ['required', 'string', 'min:20', 'max:2000'],
|
|
]);
|
|
|
|
return response()->json($governance->transition($request->user(), $id, (int) $data['version_no'], $action, $data['evidence']));
|
|
}
|
|
|
|
/** @return array<string,mixed> */
|
|
private function validatedRule(Request $request): array
|
|
{
|
|
$data = $request->validate([
|
|
'rule_code' => ['required', 'string', 'regex:/^[A-Z0-9][A-Z0-9._-]{2,63}$/'],
|
|
'rule_version' => ['required', 'integer', 'min:1'],
|
|
'component' => ['required', 'in:IRPC,IVA,ISPC,IRPS,INSS,RETENCOES,DIREITOS_ADUANEIROS,ICE'],
|
|
'scope_key' => ['required', 'string', 'min:2', 'max:160'],
|
|
'valid_from' => ['required', 'date_format:Y-m-d'],
|
|
'valid_until' => ['nullable', 'date_format:Y-m-d', 'after_or_equal:valid_from'],
|
|
'legal_source_id' => ['required', 'uuid', 'exists:investment_legal_sources,id'],
|
|
'source_sha256' => ['required', 'regex:/^[a-f0-9]{64}$/'],
|
|
'rule_definition' => ['required', 'array'],
|
|
'parameters' => ['required', 'array'],
|
|
'rounding_policy' => ['required', 'array'],
|
|
]);
|
|
foreach (['rule_definition', 'parameters', 'rounding_policy'] as $key) {
|
|
$json = json_encode($data[$key], JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE);
|
|
Validator::make(['json' => $json], ['json' => ['max:50000']])->validate();
|
|
}
|
|
|
|
if (($data['rule_definition']['language'] ?? null) === 'investmoz.tax.v1') {
|
|
try {
|
|
app(SimulationTaxRuleExpression::class)->validate($data['rule_definition']);
|
|
} catch (InvalidArgumentException $exception) {
|
|
throw ValidationException::withMessages(['rule_definition' => $exception->getMessage()]);
|
|
}
|
|
|
|
try {
|
|
app(SimulationTaxParameterResolver::class)->validateParameters($data['parameters']);
|
|
} catch (InvalidArgumentException $exception) {
|
|
throw ValidationException::withMessages(['parameters' => $exception->getMessage()]);
|
|
}
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
}
|