Teren-app/app/Services/Import/Handlers/ActivityHandler.php
Simon Pocrnjič dea7432deb changes
2025-12-26 22:39:58 +01:00

172 lines
5.4 KiB
PHP

<?php
namespace App\Services\Import\Handlers;
use App\Models\Activity;
use App\Models\Import;
use App\Services\Import\DateNormalizer;
use App\Services\Import\BaseEntityHandler;
class ActivityHandler extends BaseEntityHandler
{
public function getEntityClass(): string
{
return Activity::class;
}
/**
* Override validate to skip validation if note is empty.
* Handles both single values and arrays.
*/
public function validate(array $mapped): array
{
$note = $mapped['note'] ?? null;
// If array, check if all values are empty
if (is_array($note)) {
$hasValue = false;
foreach ($note as $n) {
if (!empty($n) && trim((string)$n) !== '') {
$hasValue = true;
break;
}
}
if (!$hasValue) {
return ['valid' => true, 'errors' => []];
}
// Skip parent validation for arrays - we'll validate in process()
return ['valid' => true, 'errors' => []];
}
// Single value - check if empty
if (empty($note) || trim((string)$note) === '') {
return ['valid' => true, 'errors' => []];
}
return parent::validate($mapped);
}
public function resolve(array $mapped, array $context = []): mixed
{
// Activities typically don't have a unique reference for deduplication
// Override this method if you have specific deduplication logic
return null;
}
public function process(Import $import, array $mapped, array $raw, array $context = []): array
{
// Handle multiple activities if note is an array
$notes = $mapped['note'] ?? null;
// If single value, convert to array for uniform processing
if (!is_array($notes)) {
$notes = [$notes];
}
$results = [];
$insertedCount = 0;
$skippedCount = 0;
// Get context IDs once
$clientCaseId = $mapped['client_case_id'] ?? $context['contract']['entity']?->client_case_id ?? null;
$contractId = $mapped['contract_id'] ?? $context['contract']['entity']?->id ?? null;
foreach ($notes as $note) {
// Skip if note is empty
if (empty($note) || trim((string)$note) === '') {
$skippedCount++;
continue;
}
// Require at least client_case_id or contract_id based on options
$requireCase = $this->getOption('require_client_case', false);
$requireContract = $this->getOption('require_contract', false);
if ($requireCase && ! $clientCaseId) {
$skippedCount++;
continue;
}
if ($requireContract && ! $contractId) {
$skippedCount++;
continue;
}
// Build activity payload for this note
$payload = ['note' => $note];
$payload['client_case_id'] = $clientCaseId;
$payload['contract_id'] = $contractId;
// Set action_id and decision_id from template meta if not in mapped data
if (!isset($mapped['action_id'])) {
$payload['action_id'] = $import->template->meta['activity_action_id'] ?? $this->getDefaultActionId();
} else {
$payload['action_id'] = $mapped['action_id'];
}
if (!isset($mapped['decision_id']) && isset($import->template->meta['activity_decision_id'])) {
$payload['decision_id'] = $import->template->meta['activity_decision_id'];
}
// Create activity
$activity = new \App\Models\Activity;
$activity->fill($payload);
$activity->save();
$results[] = $activity;
$insertedCount++;
}
if ($insertedCount === 0 && $skippedCount > 0) {
return [
'action' => 'skipped',
'message' => 'All activities empty or missing requirements',
];
}
return [
'action' => 'inserted',
'entity' => $results[0] ?? null,
'entities' => $results,
'applied_fields' => ['note', 'client_case_id', 'contract_id', 'action_id'],
'count' => $insertedCount,
];
}
protected function buildPayload(array $mapped, $model): array
{
$payload = [];
// Map activity fields
if (isset($mapped['due_date'])) {
$payload['due_date'] = DateNormalizer::toDate((string) $mapped['due_date']);
}
if (isset($mapped['amount'])) {
$payload['amount'] = is_string($mapped['amount']) ? (float) str_replace(',', '.', $mapped['amount']) : (float) $mapped['amount'];
}
if (isset($mapped['note'])) {
$payload['note'] = $mapped['note'];
}
if (isset($mapped['action_id'])) {
$payload['action_id'] = (int) $mapped['action_id'];
}
if (isset($mapped['decision_id'])) {
$payload['decision_id'] = (int) $mapped['decision_id'];
}
return $payload;
}
/**
* Get default action ID (use minimum ID from actions table).
*/
private function getDefaultActionId(): int
{
return (int) (\App\Models\Action::min('id') ?? 1);
}
}