> */ public function rules(): array { return [ 'id' => ['required', 'integer', 'exists:shopping_orders,id'], 'payment_id' => ['required', 'integer', 'exists:shopping_payments,id'], 'paid_at' => ['required', 'date', 'before_or_equal:today'], 'amount' => ['required', 'numeric', 'min:0.01', 'max:99999'], 'method' => ['required', Rule::in(array_keys(ManualPaymentService::methods()))], 'bank_reference' => ['required', 'string', 'max:255'], 'note' => ['nullable', 'string', 'max:1000'], 'send_mail' => ['nullable', 'boolean'], 'confirm_deviation' => ['nullable', 'boolean'], 'back' => ['nullable', 'string'], ]; } /** * @return array */ public function messages(): array { return [ 'bank_reference.required' => __('payment.manual_error_reference_required'), 'paid_at.before_or_equal' => __('payment.manual_error_future_date'), ]; } /** * Ein abweichender Betrag ist erlaubt (Teilzahlung, Rundungsdifferenz), * muss aber bewusst bestätigt werden — sonst wird aus einem Tippfehler * still eine falsche Buchung. */ public function withValidator(Validator $validator): void { $validator->after(function (Validator $validator): void { if ($validator->errors()->isNotEmpty()) { return; } $payment = ShoppingPayment::find($this->integer('payment_id')); if (! $payment) { return; } if ($this->amountCents() !== (int) $payment->amount && ! $this->boolean('confirm_deviation')) { $validator->errors()->add('amount', __('payment.manual_error_amount_deviation', [ 'expected' => number_format($payment->amount / 100, 2, ',', '.'), ])); } }); } /** * Erfasster Betrag in Cent (die Zahlungen werden in Cent geführt). */ public function amountCents(): int { return (int) round(((float) str_replace(',', '.', (string) $this->input('amount'))) * 100); } /** * @return array{amount_cents: int, paid_at: string, method: string, bank_reference: string, note: string|null, send_mail: bool} */ public function toServiceData(): array { return [ 'amount_cents' => $this->amountCents(), 'paid_at' => (string) $this->input('paid_at'), 'method' => (string) $this->input('method'), 'bank_reference' => trim((string) $this->input('bank_reference')), 'note' => $this->filled('note') ? trim((string) $this->input('note')) : null, 'send_mail' => $this->boolean('send_mail'), ]; } }