}> */ 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> */ 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 $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(); } }