300 lines
11 KiB
PHP
300 lines
11 KiB
PHP
<?php
|
|
namespace Incoviba\Service\Venta\MediosPago\Toku;
|
|
|
|
use DateMalformedStringException;
|
|
use DateTimeImmutable;
|
|
use DateTimeZone;
|
|
use PDOException;
|
|
use Psr\Http\Client\ClientInterface;
|
|
use Psr\Log\LoggerInterface;
|
|
use Incoviba\Common\Implement\Exception\EmptyResponse;
|
|
use Incoviba\Common\Implement\Exception\EmptyResult;
|
|
use Incoviba\Exception\InvalidResult;
|
|
use Incoviba\Model;
|
|
use Incoviba\Repository;
|
|
use Incoviba\Service\UF;
|
|
use Incoviba\Service\Venta\MediosPago\AbstractEndPoint;
|
|
use Incoviba\Service\Venta\Pago;
|
|
|
|
class Invoice extends AbstractEndPoint
|
|
{
|
|
public function __construct(ClientInterface $client,
|
|
protected Repository\Venta\MediosPago\Toku\Invoice $invoiceRepository,
|
|
protected Pago $pagoService,
|
|
protected UF $ufService)
|
|
{
|
|
parent::__construct($client);
|
|
}
|
|
|
|
public function getById(string $id): array
|
|
{
|
|
return $this->doGetById([$this->invoiceRepository, 'fetchByCuota'], $id, "No existe toku_id para Cuota {$id}");
|
|
}
|
|
public function getByExternalId(string $id): array
|
|
{
|
|
return $this->doGetById([$this->invoiceRepository, 'fetchByTokuId'], $id, "No existe Invoice para toku_id {$id}");
|
|
}
|
|
public function get(string $id): array
|
|
{
|
|
$request_uri = "/invoices/{$id}";
|
|
return $this->sendGet($request_uri, [200], [404]);
|
|
}
|
|
public function add(array $data): bool
|
|
{
|
|
$request_uri = "/invoices";
|
|
return $this->sendAdd($request_uri, $data, [200, 201], [400, 409, 422]);
|
|
}
|
|
public function edit(string $id, array $data): bool
|
|
{
|
|
$request_uri = "/invoices/{$id}";
|
|
return $this->sendEdit($request_uri, $data, [200], [400, 404, 409, 422]);
|
|
}
|
|
public function delete(string $id): void
|
|
{
|
|
$request_uri = "/invoices/{$id}";
|
|
$this->sendDelete($request_uri, [204], [404, 409]);
|
|
}
|
|
public function reset(array $skip = []): array
|
|
{
|
|
try {
|
|
$tokuIds = $this->invoiceRepository->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->invoiceRepository->removeByTokuId($tokuId);
|
|
} catch (EmptyResponse | PDOException $exception) {
|
|
$this->logger->warning($exception, ['invoice->toku_id' => $tokuId]);
|
|
}
|
|
}
|
|
return $tokuIds;
|
|
}
|
|
public function resetPayments(): array
|
|
{
|
|
$page = 1;
|
|
$pageSize = 1000;
|
|
$totalPayments = [];
|
|
while (true) {
|
|
if ($page > 100) {
|
|
break;
|
|
}
|
|
try {
|
|
$request_uri = "/organization/payments?page=1&page_size=1000";
|
|
$payments = $this->sendGet($request_uri, [200], [404, 422]);
|
|
} catch (EmptyResponse $exception) {
|
|
$this->logger->warning($exception, ['request_uri' => $request_uri]);
|
|
return [];
|
|
}
|
|
if (array_key_exists('message', $payments)) {
|
|
break;
|
|
}
|
|
$this->altLogger->info('Reset Payments', ['count' => count($payments), 'payments' => $payments]);
|
|
$query = [];
|
|
/*
|
|
"id": "pay_79zh1OU1pVV5g0V0I6kShf5AF-I24cUn",
|
|
"created_at": "2025-06-07T07:08:51+0000",
|
|
"deleted_at": null,
|
|
"invoice": "in_IhbKbT21x0ADlnKRCbV57sn2DDI8neq0",
|
|
"customer": "cus_bTXPBVopZxKOqTOWzRZkhvDEM9XXtvWh",
|
|
"government_id": "175181431",
|
|
"name": "Augusto Felipe Schilfferli Rojas",
|
|
"product_id": "1304-d1749582981383358",
|
|
"due_date": "2024-11-01",
|
|
"transaction_date": "2025-06-07T07:08:51+0000",
|
|
"payment_amount": 14.4822,
|
|
"buy_order": null,
|
|
"processed_by_toku": false,
|
|
"payment_method": null,
|
|
"card_type": null,
|
|
"card_number": null,
|
|
"payment_type": null,
|
|
"authorization_code": null,
|
|
"mc_order_id": null,
|
|
"amount_paid": 14.4822
|
|
*/
|
|
foreach ($payments as $payment) {
|
|
$query[] = [
|
|
'payment_amount' => $payment['payment_amount'],
|
|
'payment_date' => $payment['transaction_date'],
|
|
'payment_method' => $payment['payment_method'],
|
|
'product_id' => $payment['product_id'],
|
|
'due_date' => $payment['due_date'],
|
|
];
|
|
}
|
|
try {
|
|
$request_uri = "/payments";
|
|
$this->sendDelete($request_uri, [204], [404, 422], ['payments' => $query]);
|
|
} catch (EmptyResponse $exception) {
|
|
$this->logger->warning($exception, ['request_uri' => $request_uri]);
|
|
return [];
|
|
}
|
|
$this->altLogger->info('Reset Payments Payload', ['count' => count($payments), 'payments' => $query]);
|
|
$totalPayments = array_merge($totalPayments, $payments);
|
|
if (count($payments) < $pageSize) {
|
|
break;
|
|
}
|
|
$page++;
|
|
}
|
|
return $totalPayments;
|
|
}
|
|
|
|
/**
|
|
* @param string $customer_id
|
|
* @return array
|
|
* @throws EmptyResponse
|
|
*/
|
|
public function getByCustomer(string $customer_id): array
|
|
{
|
|
$request_uri = "/invoices/customer/{$customer_id}";
|
|
return $this->sendGet($request_uri, [200], [404]);
|
|
}
|
|
|
|
/**
|
|
* @param string $invoice_toku_id
|
|
* @param array $data
|
|
* @return bool
|
|
* @throws InvalidResult
|
|
*/
|
|
public function update(string $invoice_toku_id, array $data): bool
|
|
{
|
|
try {
|
|
$invoice = $this->invoiceRepository->fetchByTokuId($invoice_toku_id);
|
|
} catch (EmptyResult $exception) {
|
|
$this->logger->warning($exception, ['invoice_toku_id' => $invoice_toku_id, 'data' => $data]);
|
|
throw new InvalidResult("No existe Invoice para toku_id {$invoice_toku_id}", 404, $exception);
|
|
}
|
|
if ($data['status'] !== 'AUTHORIZED') {
|
|
$this->logger->warning("Pago no autorizado", ['invoice_toku_id' => $invoice_toku_id, 'data' => $data]);
|
|
throw new InvalidResult("Pago no autorizado", 422);
|
|
}
|
|
$dateString = $data['date'];
|
|
try {
|
|
$date = new DateTimeImmutable($dateString);
|
|
} catch (DateMalformedStringException $exception) {
|
|
$this->logger->warning($exception, ['invoice_toku_id' => $invoice_toku_id, 'data' => $data]);
|
|
throw new InvalidResult("Fecha no válida: {$dateString}", 422, $exception);
|
|
}
|
|
$uf = $this->ufService->get($date);
|
|
if ($uf === 0.0) {
|
|
$this->logger->warning("No hay UF para la fecha: {$dateString}", ['invoice_toku_id' => $invoice_toku_id, 'data' => $data]);
|
|
throw new InvalidResult("No hay UF para la fecha: {$dateString}", 422);
|
|
}
|
|
$valor = $data['amount'];
|
|
if ($valor > 1000) {
|
|
$valor = $data['amount'] / $uf;
|
|
}
|
|
if (abs($valor - $invoice->cuota->pago->valor()) >= 0.0001) {
|
|
$this->logger->warning("Valor en UF no coincide: {$data['amount']}, {$valor} <=> {$invoice->cuota->pago->valor()}", ['invoice_toku_id' => $invoice_toku_id, 'data' => $data]);
|
|
throw new InvalidResult("Valor en UF no coincide: {$data['amount']}, {$valor} <=> {$invoice->cuota->pago->valor()}", 422);
|
|
}
|
|
if ($invoice->cuota->pago->isPagado()) {
|
|
return true;
|
|
}
|
|
return $this->pagoService->depositar($invoice->cuota->pago, $date);
|
|
}
|
|
|
|
public function save(array $data): bool
|
|
{
|
|
return $this->doSave($this->invoiceRepository, $data);
|
|
}
|
|
|
|
protected LoggerInterface $altLogger;
|
|
public function setAltLogger(LoggerInterface $altLogger): self
|
|
{
|
|
$this->altLogger = $altLogger;
|
|
return $this;
|
|
}
|
|
|
|
protected function mapParams(array $data): array
|
|
{
|
|
$paramsMap = [
|
|
'customer' => 'customer',
|
|
'product_id' => 'product_id',
|
|
'due_date' => 'fecha',
|
|
'subscription' => 'subscription',
|
|
'amount' => 'valor',
|
|
'is_paid' => 'isPagada',
|
|
'is_void' => 'isRechazada',
|
|
'link_payment' => null,
|
|
'metadata' => 'datosCuota',
|
|
'receipt_type' => null,
|
|
'id_receipt' => null,
|
|
'disable_automatic_payment' => null,
|
|
'currency_code' => 'CLF',
|
|
'invoice_external_id' => 'cuota_id'
|
|
];
|
|
|
|
$today = new DateTimeImmutable('now', new DateTimeZone('America/Santiago'));
|
|
|
|
$params = [];
|
|
foreach ($paramsMap as $key => $ref) {
|
|
if ($ref === null) {
|
|
continue;
|
|
}
|
|
if ($ref === 'fecha') {
|
|
$params[$key] = $data['cuota']->pago->fecha->format('Y-m-d');
|
|
continue;
|
|
}
|
|
if ($ref === 'valor') {
|
|
/*$valor = 0;
|
|
if ($data['cuota']->pago->fecha <= $today) {
|
|
$valor = $data['cuota']->pago->valor();
|
|
}
|
|
if ($valor === 0) {
|
|
$valor = $data['cuota']->pago->valor / $data['venta']->uf;
|
|
}
|
|
$params[$key] = $valor;*/
|
|
$params[$key] = $data['cuota']->pago->valor;
|
|
continue;
|
|
}
|
|
if ($ref === 'datosCuota') {
|
|
$params[$key] = $this->datosCuota($data['cuota']);
|
|
continue;
|
|
}
|
|
if ($ref === 'isPagada') {
|
|
$params[$key] = $data['cuota']->isPagada();
|
|
}
|
|
if ($ref === 'isRechazada') {
|
|
$params[$key] = $data['cuota']->isRechazada();
|
|
}
|
|
if ($ref === 'cuota_id') {
|
|
$params[$key] = $data['cuota']->id;
|
|
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 = [
|
|
'invoice_external_id' => 'cuota_id',
|
|
'id' => 'toku_id'
|
|
];
|
|
$mappedData = [];
|
|
foreach ($responseMap as $responseKey => $dataKey) {
|
|
if (isset($data[$responseKey])) {
|
|
$mappedData[$dataKey] = $data[$responseKey];
|
|
}
|
|
}
|
|
return $mappedData;
|
|
}
|
|
|
|
protected function datosCuota(Model\Venta\Cuota $cuota): array
|
|
{
|
|
return [
|
|
'Numero' => $cuota->numero,
|
|
'Monto_CLP' => $cuota->pago->valor
|
|
];
|
|
}
|
|
}
|