81 lines
6.1 KiB
PHP
81 lines
6.1 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use Illuminate\Support\Facades\Validator;
|
|
|
|
final class BusinessFormSchema
|
|
{
|
|
/** @return array<string, array{step:int,pt:string,en:string,type:string,max:int,options?:array<string,string>}> */
|
|
public static function fields(): array
|
|
{
|
|
return [
|
|
'proponent_type' => ['step' => 1, 'pt' => 'Tipo de proponente', 'en' => 'Applicant type', 'type' => 'select', 'max' => 30, 'options' => ['person' => 'Pessoa / Person', 'organization' => 'Organização / Organization']],
|
|
'proponent_name' => ['step' => 1, 'pt' => 'Nome ou denominação', 'en' => 'Name', 'type' => 'text', 'max' => 200],
|
|
'tax_identifier' => ['step' => 1, 'pt' => 'NUIT ou identificador', 'en' => 'Tax identifier', 'type' => 'text', 'max' => 50],
|
|
'contact_email' => ['step' => 1, 'pt' => 'Email de contacto', 'en' => 'Contact email', 'type' => 'email', 'max' => 254],
|
|
'contact_phone' => ['step' => 1, 'pt' => 'Telefone', 'en' => 'Phone', 'type' => 'tel', 'max' => 40],
|
|
'country' => ['step' => 1, 'pt' => 'País (código de duas letras)', 'en' => 'Country (two-letter code)', 'type' => 'text', 'max' => 2],
|
|
'acting_capacity' => ['step' => 2, 'pt' => 'Qualidade em que actua', 'en' => 'Acting capacity', 'type' => 'select', 'max' => 30, 'options' => ['holder' => 'Titular / Holder', 'representative' => 'Representante / Representative']],
|
|
'declared_holder' => ['step' => 2, 'pt' => 'Titular declarado', 'en' => 'Declared holder', 'type' => 'text', 'max' => 200],
|
|
'mandate_reference' => ['step' => 2, 'pt' => 'Referência do mandato', 'en' => 'Mandate reference', 'type' => 'text', 'max' => 500],
|
|
'mandate_valid_until' => ['step' => 2, 'pt' => 'Validade do mandato', 'en' => 'Mandate expiry', 'type' => 'date', 'max' => 10],
|
|
'legitimacy_declaration' => ['step' => 2, 'pt' => 'Declaro legitimidade para esta submissão', 'en' => 'I declare authority to submit', 'type' => 'select', 'max' => 3, 'options' => ['yes' => 'Sim / Yes', 'no' => 'Não / No']],
|
|
'title' => ['step' => 3, 'pt' => 'Título proposto', 'en' => 'Proposed title', 'type' => 'text', 'max' => 200],
|
|
'description' => ['step' => 3, 'pt' => 'Descrição reservada', 'en' => 'Private description', 'type' => 'textarea', 'max' => 10000],
|
|
'declared_reason' => ['step' => 3, 'pt' => 'Motivo e objectivo', 'en' => 'Reason and objective', 'type' => 'textarea', 'max' => 2000],
|
|
'valid_until' => ['step' => 3, 'pt' => 'Validade declarada', 'en' => 'Declared expiry', 'type' => 'date', 'max' => 10],
|
|
'asking_value' => ['step' => 4, 'pt' => 'Valor pedido', 'en' => 'Asking value', 'type' => 'decimal', 'max' => 24],
|
|
'currency' => ['step' => 4, 'pt' => 'Moeda (código de três letras)', 'en' => 'Currency (three-letter code)', 'type' => 'text', 'max' => 3],
|
|
'value_nature' => ['step' => 4, 'pt' => 'Natureza do valor', 'en' => 'Value basis', 'type' => 'select', 'max' => 30, 'options' => ['asking' => 'Pedido / Asking', 'indicative' => 'Indicativo / Indicative', 'appraised' => 'Avaliado, sujeito a prova / Appraised, evidence required']],
|
|
'equity_percentage' => ['step' => 4, 'pt' => 'Participação disponível (%)', 'en' => 'Available equity (%)', 'type' => 'decimal', 'max' => 8],
|
|
'funds_use' => ['step' => 4, 'pt' => 'Utilização dos fundos', 'en' => 'Use of funds', 'type' => 'textarea', 'max' => 2000],
|
|
'location_notes' => ['step' => 5, 'pt' => 'Localização declarada (reservada)', 'en' => 'Declared location (private)', 'type' => 'textarea', 'max' => 2000],
|
|
'asset_notes' => ['step' => 6, 'pt' => 'Resumo dos activos e direitos declarados', 'en' => 'Declared assets and rights summary', 'type' => 'textarea', 'max' => 2000],
|
|
'source_reference' => ['step' => 7, 'pt' => 'Referência da fonte', 'en' => 'Source reference', 'type' => 'textarea', 'max' => 2000],
|
|
'document_reference' => ['step' => 7, 'pt' => 'Referências documentais (não são ficheiros validados)', 'en' => 'Document references (not validated files)', 'type' => 'textarea', 'max' => 2000],
|
|
];
|
|
}
|
|
|
|
/** @return array<string, array<int,string>> */
|
|
public static function rules(): array
|
|
{
|
|
$rules = [];
|
|
foreach (self::fields() as $key => $field) {
|
|
$rules['payload.'.$key] = ['nullable', 'string', 'max:'.$field['max']];
|
|
if (isset($field['options'])) {
|
|
$rules['payload.'.$key][] = 'in:'.implode(',', array_keys($field['options']));
|
|
}
|
|
}
|
|
$rules['payload.contact_email'][] = 'email';
|
|
$rules['payload.country'][] = 'regex:/^[A-Z]{2}$/';
|
|
$rules['payload.currency'][] = 'regex:/^[A-Z]{3}$/';
|
|
$rules['payload.asking_value'][] = 'regex:/^\d{1,15}(\.\d{1,4})?$/';
|
|
$rules['payload.equity_percentage'][] = 'numeric';
|
|
$rules['payload.equity_percentage'][] = 'between:0,100';
|
|
foreach (['valid_until', 'mandate_valid_until'] as $date) {
|
|
$rules['payload.'.$date][] = 'date_format:Y-m-d';
|
|
}
|
|
$rules['payload.wizard_version'] = ['nullable', 'in:1'];
|
|
$rules['payload.wizard_step'] = ['nullable', 'integer', 'between:1,8'];
|
|
$rules['payload.title'] = ['required', 'string', 'max:200'];
|
|
|
|
return $rules;
|
|
}
|
|
|
|
/** @param array<string,mixed> $payload */
|
|
public static function validateSubmission(array $payload): void
|
|
{
|
|
$rules = [];
|
|
foreach (['proponent_type', 'proponent_name', 'tax_identifier', 'contact_email', 'country', 'acting_capacity', 'declared_holder', 'location_notes'] as $field) {
|
|
$rules[$field] = ['required'];
|
|
}
|
|
$rules['legitimacy_declaration'] = ['required', 'in:yes'];
|
|
$rules['mandate_reference'] = ['required_if:acting_capacity,representative'];
|
|
$rules['mandate_valid_until'] = ['required_if:acting_capacity,representative', 'nullable', 'date_format:Y-m-d', 'after_or_equal:today'];
|
|
$rules['currency'] = ['required_with:asking_value'];
|
|
$rules['value_nature'] = ['required_with:asking_value'];
|
|
Validator::make($payload, $rules)->validate();
|
|
}
|
|
}
|