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); } }