get('customers', $filters); } public function products(array $filters = []): array { return $this->get('products', $filters); } public function product(int|string $id): array { return $this->get("products/{$id}"); } public function createProduct(array $data): array { return $this->send('post', 'products', $data); } /** * Bulk-create products (one CRM INSERT per call). Caller batches large * catalogs; the CRM caps each request at 500 rows. * * @param array> $products */ public function bulkCreateProducts(array $products): array { return $this->send('post', 'products/bulk', ['products' => array_values($products)]); } public function updateProduct(int|string $id, array $data): array { return $this->send('patch', "products/{$id}", $data); } public function deleteProduct(int|string $id): array { return $this->send('delete', "products/{$id}", []); } public function pushTimeline(array $data): array { return $this->post('timeline', $data); } private function client(): PendingRequest { return Http::baseUrl((string) config('crm.url')) ->withToken((string) config('crm.key')) ->acceptJson() ->asJson() ->connectTimeout(10) ->timeout(20); } private function get(string $path, array $query = []): array { return $this->handle(fn () => $this->client()->get($path, [...$query, 'owner' => $this->owner])); } private function post(string $path, array $data): array { return $this->handle(fn () => $this->client()->post($path, [...$data, 'owner' => $this->owner])); } private function send(string $method, string $path, array $data): array { return $this->handle(fn () => $this->client()->{$method}($path, [...$data, 'owner' => $this->owner])); } private function handle(callable $request): array { try { $response = $request(); } catch (ConnectionException) { throw ValidationException::withMessages([ 'crm' => ['Could not reach the CRM service. Please try again in a moment.'], ]); } if ($response->failed()) { abort($response->status() === 404 ? 404 : 502, 'CRM service error.'); } return (array) $response->json(); } }