doGetById([$this->subscriptionRepsitory, 'fetchByVenta'], $id, "No existe toku_id para Venta {$id}"); } public function getByExternalId(string $id): array { return $this->doGetById([$this->subscriptionRepsitory, 'fetchByTokuId'], $id, "No existe Subscription para toku_id {$id}"); } public function get(string $id): array { $request_uri = "/subscriptions/{$id}"; return $this->sendGet($request_uri, [200], [401, 404, 422]); } public function add(array $data, ?string $accountKey = null): bool { $request_uri = '/subscriptions'; return $this->sendAdd($request_uri, $data, [200, 201], [401, 404, 409, 422], $accountKey); } public function edit(string $id, array $data, ?string $accountKey = null): bool { $request_uri = "/subscriptions/{$id}"; return $this->sendEdit($request_uri, $data, [200], [401, 404, 409, 422], $accountKey); } public function delete(string $id): void { $request_uri = "/subscriptions/{$id}"; $this->sendDelete($request_uri, [204], [404, 409]); } public function reset(array $skip = []): array { try { $tokuIds = $this->subscriptionRepsitory->fetchAllTokuIds(); $tokuIds = array_filter($tokuIds, function (string $tokuId) use ($skip) { return !in_array($tokuId, $skip); }); } catch (EmptyResult $exception) { $this->logger->warning($exception); return []; } foreach ($tokuIds as $tokuId) { try { $this->delete($tokuId); $this->subscriptionRepsitory->removeByTokuId($tokuId); } catch (EmptyResponse | PDOException $exception) { $this->logger->warning($exception, ['subscription->toku_id' => $tokuId]); } } return $tokuIds; } /** * @return array * @throws Read */ public function check(): array { $ventas = $this->ventaService->getAllWithCuotaPending(); $ids = array_column($ventas, 'id'); $existingSubscriptions = []; try { $existingSubscriptions = $this->subscriptionRepsitory->fetchByVentas($ids); array_walk($existingSubscriptions, function(&$subscription) { $subscription->venta = $this->ventaService->getById($subscription->venta->id); }); } catch (EmptyResult) {} if (count($existingSubscriptions) === 0) { $missingVentas = $ventas; } else { $missingVentas = array_filter($ventas, function($venta) use ($existingSubscriptions) { return !array_any($existingSubscriptions, fn($subscription) => $subscription->venta->id === $venta->id); }); } return compact('existingSubscriptions', 'missingVentas'); } public function queue(int $venta_id): bool { try { $venta = $this->ventaService->getById($venta_id); } catch (Read $exception) { $this->logger->warning($exception); return false; } try { $subscription = $this->subscriptionRepsitory->fetchByVenta($venta_id); return false; } catch (EmptyResult) { return true; } } /** * @param array $idsData * @return array * @throws EmptyResult * @throws EmptyResponse */ public function update(array $idsData): array { $tokuIds = array_column($idsData, 'toku_id'); $oldPids = array_column($idsData, 'product_id'); $placeholders = array_map(fn($id) => "id{$id}", array_keys($oldPids)); $placeholdersString = implode(', ', array_map(fn($id) => ":{$id}", $placeholders)); $query = $this->ventaService->getRepository()->getConnection()->getQueryBuilder() ->select('venta.id, CONCAT_WS("-", unidad.descripcion, CONCAT_WS("-", propietario.rut, propietario.dv)) AS old_pid') ->from('venta') ->joined('JOIN propietario ON propietario.rut = venta.propietario') ->joined('JOIN propiedad_unidad pu ON pu.propiedad = venta.propiedad') ->joined('JOIN unidad ON pu.unidad = unidad.id') ->having("old_pid IN ({$placeholdersString})"); $values = array_combine($placeholders, $oldPids); try { $statement = $this->ventaService->getRepository()->getConnection()->execute($query, $values); $results = $statement->fetchAll(PDO::FETCH_ASSOC); } catch (PDOException $exception) { $this->logger->error($exception->getMessage(), [ 'query' => $query, 'values' => $values, 'ids' => $idsData, 'exception' => $exception]); throw new EmptyResult($query, $exception); } $accountKeys = $this->getAccountKey(array_column($results, 'id')); $newPids = []; $keys = []; foreach ($results as $result) { $idx = array_search($result['old_pid'], $oldPids); $newPids[$idx] = $result['id']; if (array_key_exists($result['id'], $accountKeys)) { $keys[$idx] = $accountKeys[$result['id']]; } } $output = []; foreach ($tokuIds as $idx => $tokuId) { if (!isset($newPids[$idx])) { continue; } $data = [ 'product_id' => $newPids[$idx], ]; try { if (!$this->edit($tokuId, $data, array_key_exists($idx, $keys) ? $keys[$idx] : null)) { $this->logger->error('Error while updating Toku', [ 'toku_id' => $tokuId, 'old_pid' => $oldPids[$idx], 'product_id' => $newPids[$idx], 'account_key' => array_key_exists($idx, $keys) ? $keys[$idx] : null]); $output[] = [ 'toku_id' => $tokuId, 'old_pid' => $oldPids[$idx], 'product_id' => $newPids[$idx], 'account_key' => array_key_exists($idx, $keys) ? $keys[$idx] : null, 'error' => 'Error while updating Toku' ]; continue; } } catch (EmptyResponse $exception) { $this->logger->error($exception->getMessage(), [ 'toku_id' => $tokuId, 'old_pid' => $oldPids[$idx], 'product_id' => $newPids[$idx], 'account_key' => array_key_exists($idx, $keys) ? $keys[$idx] : null, 'exception' => $exception]); $output[] = [ 'toku_id' => $tokuId, 'old_pid' => $oldPids[$idx], 'product_id' => $newPids[$idx], 'account_key' => array_key_exists($idx, $keys) ? $keys[$idx] : null, 'error' => $exception->getMessage() ]; continue; } $output[] = [ 'toku_id' => $tokuId, 'old_pid' => $oldPids[$idx], 'product_id' => $newPids[$idx], 'account_key' => array_key_exists($idx, $keys) ? $keys[$idx] : null ]; } return $output; } public function save(array $data): bool { return $this->doSave($this->subscriptionRepsitory, $data); } protected function mapParams(array $data): array { $paramsMap = [ 'customer' => 'customer', 'product_id' => 'product_id', 'pac_mandate_id' => null, 'is_recurring' => null, 'due_day' => null, 'amount' => 'pieValor', 'receipt_product_code' => null, 'metadata' => 'datosVenta' ]; $params = []; foreach ($paramsMap as $key => $ref) { if ($ref === null) { continue; } if ($ref === 'pieValor' and array_key_exists('venta', $data)) { $params[$key] = $data['venta']?->formaPago()?->pie?->valor ?? 0; continue; } if ($ref === 'datosVenta' and array_key_exists('venta', $data)) { $params[$key] = $this->datosVenta($data['venta']); continue; } if (array_key_exists($ref, $data) and $data[$ref] !== '' and $data[$ref] !== null) { $params[$key] = $data[$ref]; } } return $params; } protected function mapSave(array $data): array { $responseMap = [ 'product_id' => 'venta_id', 'id' => 'toku_id' ]; $mappedData = []; foreach ($responseMap as $responseKey => $dataKey) { if (isset($data[$responseKey])) { $mappedData[$dataKey] = $data[$responseKey]; } } return $mappedData; } protected function datosVenta(Venta $venta): array { return [ 'Proyecto' => $venta->proyecto()->descripcion, 'Unidades' => $venta->propiedad()->summary() ]; } /** * @param array $ventaIds * @return array * @throws EmptyResult */ protected function getAccountKey(array $ventaIds): array { $placeholders = array_map(fn($id) => "id{$id}", array_keys($ventaIds)); $placeholdersString = implode(', ', array_map(fn($id) => ":{$id}", $placeholders)); $query = $this->ventaService->getRepository()->getConnection()->getQueryBuilder() ->select('account_key, venta.id AS venta_id') ->from('toku_accounts') ->joined('JOIN proyecto ON proyecto.inmobiliaria = toku_accounts.sociedad_rut') ->joined('JOIN proyecto_tipo_unidad ptu ON ptu.proyecto = proyecto.id') ->joined('JOIN unidad ON unidad.pt = ptu.id') ->joined('JOIN propiedad_unidad pu ON pu.unidad = unidad.id') ->joined('JOIN venta ON venta.propiedad = pu.propiedad') ->where("venta.id IN ({$placeholdersString}) AND toku_accounts.enabled = 1"); $values = array_combine($placeholders, $ventaIds); try { $statement = $this->ventaService->getRepository()->getConnection()->execute($query, $values); $results = $statement->fetchAll(PDO::FETCH_ASSOC); } catch (PDOException $exception) { $this->logger->error($exception->getMessage(), [ 'query' => $query, 'values' => $values, 'exception' => $exception]); throw new EmptyResult($query, $exception); } $keys = array_column($results, 'account_key'); $ids = array_column($results, 'venta_id'); return array_combine($ids, $keys); } }