post('/customers/search', function () { // Require the user to be logged in global $response; $this->requirePermission('search_customers'); // Get the user object $user = (new authentication())->get_user(); // Check if the request was successful if ($user) { // Get the post data $data = json_decode(file_get_contents('php://input'), true); // Check if the pagination, search and sort parameters are set if (!isset($data['search'])) { $response->error('Missing required body parameter search', 400); } if (!isset($data['filter'])) { $response->error('Missing required body parameter filter', 400); } // Check if the search parameter is valid $allowedSearchFilters = (new economicCustomers())->allowed_search_filters_customers(); if (!in_array($data['filter'], $allowedSearchFilters)) { $response->error('Invalid search parameter', 400); } (new logs_o())->add('customers', 'global', 1, $user->id, 'SEARCH_CUSTOMERS', 'Successfully retrieved customers meeting search criteria'); // Return the list of users $response->success( (array)(new economicCustomers())->searchCustomers((string)$data['search'], (string)$data['filter']) ); } else { // Log the incident (new logs_o())->add('customers', 'global', 1, 0, 'SEARCH_CUSTOMERS', 'No user found, or invalid session'); // Return an error $response->error('Invalid session', 400); } }, [ 'search_customers' => 'Search for customers' ] ); self::get('/customers', function () { // Require the user to be logged in global $response; self::requirePermission('search_customers'); // Get the user object $user = (new authentication())->get_user(); // Check if the request was successful if ($user) { // Check if the pagination parameters are set $page = self::fromRequest('page') ?? 1; $limit = self::fromRequest('limit') ?? 100; $search = self::fromRequest('search') ?? null; $barred = self::fromRequest('barred') ?? null; // Create the economic customers object $economicCustomers = new economicCustomers(); try { $result = (object)$economicCustomers->listCustomers( (int)$page, (int)$limit, $search, $barred ); if (!isset($result->pagination) || !is_object($result->pagination) || !isset($result->pagination->results) || !is_numeric($result->pagination->results)) { throw new \RuntimeException('Malformed e-conomic customers response: missing pagination results.'); } if (!isset($result->collection) || !is_array($result->collection)) { throw new \RuntimeException('Malformed e-conomic customers response: missing customer collection.'); } } catch (\Throwable $throwable) { $upstreamMessage = self::sanitizeUpstreamErrorMessage($throwable); $searchProvided = (is_string($search) && trim($search) !== '') ? 'true' : 'false'; $context = json_encode([ 'page' => (int)$page, 'limit' => (int)$limit, 'search_provided' => $searchProvided, 'barred' => $barred, ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); (new logs_o())->add( 'customers', 'global', 1, $user->id, 'LIST_CUSTOMERS_FAILED', 'Failed to list customers from e-conomic: ' . $upstreamMessage . ' | context=' . $context ); $response->error([ 'message' => 'Failed to fetch customers from e-conomic', 'upstream_message' => $upstreamMessage, ], 502); } // Parse the pagination meta from E-conomic to the standard format used in this application $response->paginate( (int)$page, (int)$limit, (int)$result->pagination->results, $search, ['barred' => $barred] ); // Create the users object $users_o = new users_o(); $customers = self::parseFunction($result->collection, function ($customer) use ($users_o) { // Add the user id to the customer object $customer->id = null; // Update the user id if the customer is imported from E-conomic if ($users_o->isImportedFromEconomic($customer->customerNumber)) { $customer->id = $users_o->getUserIdFromEconomic($customer->customerNumber); } return $customer; }); // Log the incident (new logs_o())->add('customers', 'global', 1, $user->id, 'LIST_CUSTOMERS', 'Successfully listed customers'); // Return the list of users $response->success($customers); } else { // Log the incident (new logs_o())->add('customers', 'global', 1, 0, 'LIST_CUSTOMERS', 'No user found, or invalid session'); // Return an error $response->error('Invalid session', 400); } }, [ 'search_customers' => 'Search for customers, and list all customers if no search is provided' ] ); $this->post('/customers/import', function () { global $response; $this->requirePermission('add_user'); $user = (new authentication())->get_user(); if (!$user) { (new logs_o())->add('customers', 'global', 1, 0, 'IMPORT_CUSTOMER', 'No user found, or invalid session'); $response->error('Invalid session', 400); } $data = json_decode(file_get_contents('php://input'), true); if (!is_array($data)) { $data = []; } try { $result = (new customer_mass_import_service())->import($data); } catch (\RuntimeException $throwable) { $statusCode = (int)$throwable->getCode(); if ($statusCode < 400 || $statusCode > 599) { $statusCode = 400; } (new logs_o())->add( 'customers', 'global', 1, $user->id, 'IMPORT_CUSTOMER_FAILED', $throwable->getMessage() ); $response->error([ 'message' => $throwable->getMessage(), ], $statusCode); } (new logs_o())->add( 'customers', 'global', 1, $user->id, 'IMPORT_CUSTOMER', 'Successfully imported or created customer ' . ($result['customer_number'] ?? 'unknown') ); $response->success($result); }, [ 'add_user' => 'Add a user' ] ); } private static function parseFunction($collection, \Closure $param): array { $result = []; foreach ( $collection as $item ) { $result[] = $param($item); } return $result; } private static function sanitizeUpstreamErrorMessage(\Throwable $throwable): string { $message = trim($throwable->getMessage()); if ($message === '') { return 'Unexpected e-conomic integration error.'; } $message = preg_replace('/\s+/', ' ', $message); if (!is_string($message)) { return 'Unexpected e-conomic integration error.'; } return substr($message, 0, 500); } }