11 Commits

Author SHA1 Message Date
4d5b657b92 Manejo de trabajos en cli por php en vez de cron 2025-05-10 12:40:06 -04:00
4ca1616dfc Integracion Toku a flujo 2025-05-10 12:39:31 -04:00
fb7177fd65 Reorden Toku 2025-05-10 12:38:14 -04:00
1486d6cf38 Toku settings 2025-05-10 12:32:01 -04:00
8b2de31e02 Job Queue 2025-05-10 12:30:35 -04:00
61324f159b Toku endpoint 2025-05-10 12:30:21 -04:00
c95e74d574 Controlador Toku 2025-05-09 18:31:00 -04:00
59ecb6cc79 Se agregan fetchs 2025-05-09 18:05:40 -04:00
db84187461 Pruebas de Toku 2025-05-09 18:05:19 -04:00
c2f98c8b0d Excepcion 2025-05-09 18:04:37 -04:00
8d73987ac3 FIX: Cambios a Servicios Toku 2025-05-09 18:04:17 -04:00
48 changed files with 1183 additions and 217 deletions

View File

@ -1,4 +1,4 @@
FROM php:8.2-cli
FROM php:8.4-cli
ENV TZ "${TZ}"
ENV APP_NAME "${APP_NAME}"
@ -6,9 +6,10 @@ ENV API_URL "${API_URL}"
RUN apt-get update && apt-get install -y --no-install-recommends cron rsyslog nano && rm -r /var/lib/apt/lists/*
RUN pecl install xdebug-3.2.2 \
&& docker-php-ext-enable xdebug \
&& echo "#/bin/bash\nprintenv >> /etc/environment\ncron -f -L 11" > /root/entrypoint && chmod a+x /root/entrypoint
RUN pecl install xdebug-3.4.2 \
&& docker-php-ext-enable xdebug
COPY --chmod=550 ./cli/entrypoint /root/entrypoint
COPY ./php-errors.ini /usr/local/etc/php/conf.d/docker-php-errors.ini

View File

@ -0,0 +1,7 @@
<?php
use Incoviba\Controller\API\Ventas\MediosPago\Toku;
$app->group('/toku', function($app) {
$app->post('/cuotas/{venta_id}[/]', [Toku::class, 'cuotas']);
$app->post('/success[/]', [Toku::class, 'success']);
});

View File

@ -114,5 +114,40 @@ return [
$container->get(Psr\Log\LoggerInterface::class),
))
->registerSub($container->get(Incoviba\Service\Contabilidad\Cartola\BCI\Mes::class));
},
'tokuClient' => function(ContainerInterface $container) {
return new GuzzleHttp\Client([
'base_uri' => $container->get('TOKU_URL'),
'headers' => [
'Authorization' => "Bearer {$container->get('TOKU_TOKEN')}"
]
]);
},
Incoviba\Service\Venta\MediosPago\Toku\Customer::class => function(ContainerInterface $container) {
return new Incoviba\Service\Venta\MediosPago\Toku\Customer(
$container->get('tokuClient'),
$container->get(Incoviba\Repository\Venta\MediosPago\Toku\Customer::class)
);
},
Incoviba\Service\Venta\MediosPago\Toku\Subscription::class => function(ContainerInterface $container) {
return new Incoviba\Service\Venta\MediosPago\Toku\Subscription(
$container->get('tokuClient'),
$container->get(Incoviba\Repository\Venta\MediosPago\Toku\Subscription::class)
);
},
Incoviba\Service\Venta\MediosPago\Toku\Invoice::class => function(ContainerInterface $container) {
return new Incoviba\Service\Venta\MediosPago\Toku\Invoice(
$container->get('tokuClient'),
$container->get(Incoviba\Repository\Venta\MediosPago\Toku\Invoice::class),
$container->get(Incoviba\Service\Venta\Pago::class),
$container->get(Incoviba\Service\UF::class)
);
},
Incoviba\Service\Venta\MediosPago\Toku::class => function(ContainerInterface $container) {
return (new Incoviba\Service\Venta\MediosPago\Toku(
$container->get(Psr\Log\LoggerInterface::class)
))->register('customer', $container->get(Incoviba\Service\Venta\MediosPago\Toku\Customer::class))
->register('subscription', $container->get(Incoviba\Service\Venta\MediosPago\Toku\Subscription::class))
->register('invoice', $container->get(Incoviba\Service\Venta\MediosPago\Toku\Invoice::class));
}
];

View File

@ -0,0 +1,63 @@
<?php
namespace Incoviba\Controller\API\Ventas\MediosPago;
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Incoviba\Common\Ideal\Controller;
use Incoviba\Controller\API\withJson;
use Incoviba\Exception\InvalidResult;
use Incoviba\Exception\ServiceAction\Read;
use Incoviba\Service;
class Toku extends Controller
{
use withJson;
public function cuotas(ServerRequestInterface $request, ResponseInterface $response,
Service\Venta\MediosPago\Toku $tokuService, Service\Venta $ventaService, int $venta_id): ResponseInterface
{
$input = $request->getParsedBody();
$output = [
'input' => $input,
'venta_id' => $venta_id,
'cuotas' => [],
'success' => false,
'partial' => false,
];
try {
$venta = $ventaService->getById($venta_id);
$cuotas = $tokuService->sendCuotas($venta, $input['cuotas']);
$output['cuotas'] = array_map(function($row) { return $row['cuota_id']; }, $cuotas);
if (count($cuotas) < count($input['cuotas'])) {
$output['partial'] = true;
} else {
$output['success'] = true;
}
} catch (Read | InvalidResult) {}
return $this->withJson($response, $output);
}
public function success(ServerRequestInterface $request, ResponseInterface $response,
ResponseFactoryInterface $responseFactory,
Service\Venta\MediosPago\Toku $tokuService): ResponseInterface
{
$body = $request->getBody();
$input = json_decode($body->getContents(), true);
try {
if ($tokuService->updatePago($input['payment_intent'])) {
return $responseFactory->createResponse(204);
}
return $responseFactory->createResponse(409, 'Payment could not be updated');
} catch (InvalidResult $exception) {
$this->logger->warning($exception);
if (str_contains($exception->getMessage(), 'Customer')) {
$message = 'Customer not found';
} elseif (str_contains($exception->getMessage(), 'Invoice')) {
$message = 'Invoice not found';
} else {
$message = $exception->getMessage();
}
return $responseFactory->createResponse($exception->getCode(), $message);
}
}
}

View File

@ -6,6 +6,7 @@ use Psr\Http\Message\ServerRequestInterface;
use DateTimeImmutable;
use Incoviba\Common\Alias\View;
use Incoviba\Common\Implement\Exception\EmptyResult;
use Incoviba\Exception\ServiceAction\Create;
use Incoviba\Model;
use Incoviba\Repository;
use Incoviba\Service;
@ -84,13 +85,15 @@ class Cuotas
return $view->render($response, 'ventas.pies.cuotas.add', compact('pie', 'venta', 'bancos'));
}
public function doAdd(ServerRequestInterface $request, ResponseInterface $response, Service\Venta\Pie $pieService,
Repository\Venta $ventaRepository, Service\Valor $valorService, int $pie_id): ResponseInterface
Repository\Venta $ventaRepository, Service\Valor $valorService,
Service\Queue $queueService, int $pie_id): ResponseInterface
{
$body = $request->getParsedBody();
$pie = $pieService->getById($pie_id);
$venta = $ventaRepository->fetchByPie($pie_id);
$start = count($pie->cuotas(vigentes: true));
$total = $pie->cuotas;
$cuotas = [];
for ($i = $start; $i < $total; $i ++) {
if ($body["banco{$i}"] === '') {
continue;
@ -103,7 +106,17 @@ class Cuotas
'valor' => $valorService->clean(str_replace('.', '', $body["valor{$i}"])),
'numero' => $i + 1,
];
$pieService->addCuota($data);
try {
$cuotas []= $pieService->addCuota($data)->id;
} catch (Create) {}
}
if (count($cuotas) > 0) {
$data = [
'type' => 'request',
'action' => "/api/external/toku/cuotas/{$venta->id}",
'body' => compact('cuotas')
];
$queueService->enqueue($data);
}
return $response->withHeader('Location', "/venta/{$venta->id}");
}

View File

@ -0,0 +1,13 @@
<?php
namespace Incoviba\Exception;
use Exception;
use Throwable;
class InvalidResult extends Exception
{
public function __construct(string $message = "", int $code = 404, ?Throwable $previous = null)
{
parent::__construct($message, $code, $previous);
}
}

18
app/src/Model/Job.php Normal file
View File

@ -0,0 +1,18 @@
<?php
namespace Incoviba\Model;
use Incoviba\Common\Ideal;
class Job extends Ideal\Model
{
public array $configuration;
public bool $executed = false;
protected function jsonComplement(): array
{
return [
'configuration' => $this->configuration,
'executed' => $this->executed
];
}
}

View File

@ -1,5 +1,5 @@
<?php
namespace Incoviba\Model\MediosPago\Toku;
namespace Incoviba\Model\Venta\MediosPago\Toku;
use Incoviba\Common\Ideal;
use Incoviba\Model\Persona;

View File

@ -1,5 +1,5 @@
<?php
namespace Incoviba\Model\MediosPago\Toku;
namespace Incoviba\Model\Venta\MediosPago\Toku;
use Incoviba\Common\Ideal;
use Incoviba\Model\Venta\Cuota;

View File

@ -1,5 +1,5 @@
<?php
namespace Incoviba\Model\MediosPago\Toku;
namespace Incoviba\Model\Venta\MediosPago\Toku;
use Incoviba\Common\Ideal;
use Incoviba\Model\Venta;

View File

@ -0,0 +1,54 @@
<?php
namespace Incoviba\Repository;
use DateTimeImmutable;
use Incoviba\Common\Define;
use Incoviba\Common\Implement;
use Incoviba\Common\Ideal;
use Incoviba\Model;
class Job extends Ideal\Repository
{
public function getTable(): string
{
return 'workers';
}
public function create(?array $data = null): Model\Job
{
$map = (new Implement\Repository\MapperParser())
->register('configuration', (new Implement\Repository\Mapper())
->setFunction(function($data) {
return json_decode($data['configuration'], true);
}))
->register('executed', new Implement\Repository\Mapper\Boolean('executed'));
return $this->parseData(new Model\Job(), $data, $map);
}
public function save(Define\Model $model): Model\Job
{
$model->id = $this->saveNew(['configuration', 'executed', 'created_at'],
[json_encode($model->configuration), $model->executed, (new DateTimeImmutable())->format('Y-m-d H:i:s.u')]);
return $model;
}
public function edit(Define\Model $model, array $new_data): Model\Job
{
if (isset($new_data['configuration']) and !is_string($new_data['configuration'])) {
$new_data['configuration'] = json_encode($new_data['configuration']);
}
return $this->update($model, ['configuration', 'executed', 'updated_at'],
array_merge($new_data, ['updated_at' => (new DateTimeImmutable())->format('Y-m-d H:i:s.u')]));
}
/**
* @return array
* @throws Implement\Exception\EmptyResult
*/
public function fetchPending(): array
{
$query = $this->connection->getQueryBuilder()
->select()
->from($this->getTable())
->where('executed = ?');
return $this->fetchMany($query, [false]);
}
}

View File

@ -1,5 +1,5 @@
<?php
namespace Incoviba\Repository\MediosPago\Toku;
namespace Incoviba\Repository\Venta\MediosPago\Toku;
use DateTimeImmutable;
use Incoviba\Common\Define;
@ -20,7 +20,7 @@ class Customer extends Ideal\Repository
return 'teku_customers';
}
public function create(?array $data = null): Model\MediosPago\Toku\Customer
public function create(?array $data = null): Model\Venta\MediosPago\Toku\Customer
{
$map = (new Implement\Repository\MapperParser(['toku_id']))
->register('rut', (new Implement\Repository\Mapper())
@ -30,9 +30,9 @@ class Customer extends Ideal\Repository
return $this->personaService->getById($rut);
})
);
return $this->parseData(new Model\MediosPago\Toku\Customer(), $data, $map);
return $this->parseData(new Model\Venta\MediosPago\Toku\Customer(), $data, $map);
}
public function save(Define\Model $model): Model\MediosPago\Toku\Customer
public function save(Define\Model $model): Model\Venta\MediosPago\Toku\Customer
{
$model->id = $this->saveNew(
['rut', 'toku_id', 'created_at'],
@ -40,17 +40,17 @@ class Customer extends Ideal\Repository
);
return $model;
}
public function edit(Define\Model $model, array $new_data): Model\MediosPago\Toku\Customer
public function edit(Define\Model $model, array $new_data): Model\Venta\MediosPago\Toku\Customer
{
return $this->update($model, ['rut', 'toku_id', 'updated_at'], array_merge($new_data, ['updated_at' => (new DateTimeImmutable())->format('Y-m-d H:i:s.u')]));
}
/**
* @param string $rut
* @return Model\MediosPago\Toku\Customer
* @return \Incoviba\Model\Venta\MediosPago\Toku\Customer
* @throws Implement\Exception\EmptyResult
*/
public function fetchByRut(string $rut): Model\MediosPago\Toku\Customer
public function fetchByRut(string $rut): Model\Venta\MediosPago\Toku\Customer
{
if (str_contains($rut, '-')) {
$rut = str_replace('-', '', $rut);
@ -65,4 +65,18 @@ class Customer extends Ideal\Repository
->where('rut = :rut');
return $this->fetchOne($query, compact('rut'));
}
/**
* @param string $toku_id
* @return \Incoviba\Model\Venta\MediosPago\Toku\Customer
* @throws Implement\Exception\EmptyResult
*/
public function fetchByTokuId(string $toku_id): Model\Venta\MediosPago\Toku\Customer
{
$query = $this->connection->getQueryBuilder()
->select()
->from($this->getTable())
->where('toku_id = :toku_id');
return $this->fetchOne($query, compact('toku_id'));
}
}

View File

@ -1,12 +1,12 @@
<?php
namespace Incoviba\Repository\MediosPago\Toku;
namespace Incoviba\Repository\Venta\MediosPago\Toku;
use DateTimeImmutable;
use Incoviba\Common\Define;
use Incoviba\Common\Ideal;
use Incoviba\Common\Implement;
use Incoviba\Repository;
use Incoviba\Model;
use Incoviba\Repository;
class Invoice extends Ideal\Repository
{
@ -19,7 +19,7 @@ class Invoice extends Ideal\Repository
{
return 'toku_invoices';
}
public function create(?array $data = null): Model\MediosPago\Toku\Invoice
public function create(?array $data = null): Model\Venta\MediosPago\Toku\Invoice
{
$map = (new Implement\Repository\MapperParser(['toku_id']))
->register('cuota_id', (new Implement\Repository\Mapper())
@ -27,9 +27,9 @@ class Invoice extends Ideal\Repository
->setFunction(function($data) {
return $this->cuotaRepository->fetchById($data['cuota_id']);
}));
return $this->parseData(new Model\MediosPago\Toku\Invoice(), $data, $map);
return $this->parseData(new Model\Venta\MediosPago\Toku\Invoice(), $data, $map);
}
public function save(Define\Model $model): Model\MediosPago\Toku\Invoice
public function save(Define\Model $model): Model\Venta\MediosPago\Toku\Invoice
{
$model->id = $this->saveNew(
['cuota_id', 'toku_id', 'created_at'],
@ -37,12 +37,17 @@ class Invoice extends Ideal\Repository
);
return $model;
}
public function edit(Define\Model $model, array $new_data): Model\MediosPago\Toku\Invoice
public function edit(Define\Model $model, array $new_data): Model\Venta\MediosPago\Toku\Invoice
{
return $this->update($model, ['cuota_id', 'toku_id', 'updated_at'], array_merge($new_data, ['updated_at' => (new DateTimeImmutable())->format('Y-m-d H:i:s.u')]));
}
public function fetchByCuota(int $cuota_id): Model\MediosPago\Toku\Invoice
/**
* @param int $cuota_id
* @return \Incoviba\Model\Venta\MediosPago\Toku\Invoice
* @throws Implement\Exception\EmptyResult
*/
public function fetchByCuota(int $cuota_id): Model\Venta\MediosPago\Toku\Invoice
{
$query = $this->connection->getQueryBuilder()
->select()
@ -50,4 +55,18 @@ class Invoice extends Ideal\Repository
->where('cuota_id = :cuota_id');
return $this->fetchOne($query, compact('cuota_id'));
}
/**
* @param string $toku_id
* @return \Incoviba\Model\Venta\MediosPago\Toku\Invoice
* @throws Implement\Exception\EmptyResult
*/
public function fetchByTokuId(string $toku_id): Model\Venta\MediosPago\Toku\Invoice
{
$query = $this->connection->getQueryBuilder()
->select()
->from($this->getTable())
->where('toku_id = :toku_id');
return $this->fetchOne($query, compact('toku_id'));
}
}

View File

@ -1,9 +1,9 @@
<?php
namespace Incoviba\Repository\MediosPago\Toku;
namespace Incoviba\Repository\Venta\MediosPago\Toku;
use DateTimeImmutable;
use Incoviba\Common\Ideal;
use Incoviba\Common\Define;
use Incoviba\Common\Ideal;
use Incoviba\Common\Implement;
use Incoviba\Model;
use Incoviba\Repository;
@ -20,7 +20,7 @@ class Subscription extends Ideal\Repository
return 'toku_subscriptions';
}
public function create(?array $data = null): Model\MediosPago\Toku\Subscription
public function create(?array $data = null): Model\Venta\MediosPago\Toku\Subscription
{
$map = (new Implement\Repository\MapperParser(['toku_id']))
->register('venta_id', (new Implement\Repository\Mapper())
@ -28,9 +28,9 @@ class Subscription extends Ideal\Repository
->setFunction(function($data) {
return $this->ventaRepository->fetchById($data['venta_id']);
}));
return $this->parseData(new Model\MediosPago\Toku\Subscription(), $data, $map);
return $this->parseData(new Model\Venta\MediosPago\Toku\Subscription(), $data, $map);
}
public function save(Define\Model $model): Model\MediosPago\Toku\Subscription
public function save(Define\Model $model): Model\Venta\MediosPago\Toku\Subscription
{
$model->id = $this->saveNew(
['venta_id', 'toku_id', 'created_at'],
@ -38,12 +38,12 @@ class Subscription extends Ideal\Repository
);
return $model;
}
public function edit(Define\Model $model, array $new_data): Model\MediosPago\Toku\Subscription
public function edit(Define\Model $model, array $new_data): Model\Venta\MediosPago\Toku\Subscription
{
return $this->update($model, ['venta_id', 'toku_id', 'updated_at'], array_merge($new_data, ['updated_at' => (new DateTimeImmutable())->format('Y-m-d H:i:s.u')]));
}
public function fetchByVenta(int $venta_id): Model\MediosPago\Toku\Subscription
public function fetchByVenta(int $venta_id): Model\Venta\MediosPago\Toku\Subscription
{
$query = $this->connection->getQueryBuilder()
->select()
@ -51,4 +51,12 @@ class Subscription extends Ideal\Repository
->where('venta_id = :venta_id');
return $this->fetchOne($query, compact('venta_id'));
}
public function fetchByTokuId(string $toku_id): Model\Venta\MediosPago\Toku\Subscription
{
$query = $this->connection->getQueryBuilder()
->select()
->from($this->getTable())
->where('toku_id = :toku_id');
return $this->fetchOne($query, compact('toku_id'));
}
}

View File

@ -32,6 +32,11 @@ class TipoPago extends Ideal\Repository
return $this->update($model, ['descripcion'], $new_data);
}
/**
* @param string $descripcion
* @return Model\Venta\TipoPago
* @throws Implement\Exception\EmptyResult
*/
public function fetchByDescripcion(string $descripcion): Model\Venta\TipoPago
{
$query = "SELECT * FROM `{$this->getTable()}` WHERE `descripcion` = ?";

51
app/src/Service/Job.php Normal file
View File

@ -0,0 +1,51 @@
<?php
namespace Incoviba\Service;
use PDOException;
use Psr\Log\LoggerInterface;
use Incoviba\Common\Ideal;
use Incoviba\Common\Implement\Exception\EmptyResult;
use Incoviba\Exception\ServiceAction\{Create,Read};
use Incoviba\Repository;
use Incoviba\Model;
class Job extends Ideal\Service
{
public function __construct(LoggerInterface $logger, protected Repository\Job $jobRepository)
{
parent::__construct($logger);
}
/**
* @param array $configuration
* @return Model\Job
* @throws Create
*/
public function add(array $configuration): Model\Job
{
try {
$job = $this->jobRepository->create(compact('configuration'));
return $this->process($this->jobRepository->save($job));
} catch (PDOException $exception) {
throw new Create(__CLASS__, $exception);
}
}
/**
* @return array
* @throws Read
*/
public function getPending(): array
{
try {
return array_merge([$this, 'process'],$this->jobRepository->fetchPending());
} catch (EmptyResult $exception) {
throw new Read(__CLASS__, $exception);
}
}
protected function process(Model\Job $job): Model\Job
{
return $job;
}
}

69
app/src/Service/Queue.php Normal file
View File

@ -0,0 +1,69 @@
<?php
namespace Incoviba\Service;
use Exception;
use Psr\Log\LoggerInterface;
use Incoviba\Common\Ideal;
use Incoviba\Exception\ServiceAction\{Create, Read};
use Incoviba\Service;
class Queue extends Ideal\Service
{
public function __construct(LoggerInterface $logger, protected Service\Job $jobService, Worker $defaultWorker)
{
parent::__construct($logger);
$this->register('default', $defaultWorker);
}
protected array $workers;
public function register(string $name, Worker $worker): self
{
$this->workers[strtolower($name)] = $worker;
return $this;
}
public function enqueue(array $configuration): bool
{
try {
$this->jobService->add($configuration);
return true;
} catch (Create $exception) {
$final = new Exception("Could not enqueue job", 0, $exception);
$this->logger->warning($final);
return false;
}
}
public function run(): bool
{
try {
$jobs = $this->jobService->getPending();
} catch (Read $exception) {
$final = new Exception("Could not get pending jobs", 0, $exception);
$this->logger->warning($final);
return false;
}
$status = true;
foreach ($jobs as $job) {
$type = 'default';
if (isset($job->configuration['type'])) {
$type = strtolower($job->configuration['type']);
}
if (!isset($this->workers[$type])) {
$type = 'default';
}
$worker = $this->workers[$type];
try {
$status &= $worker->run($job);
} catch (Exception $exception) {
$final = new Exception("Could not run job", 0, $exception);
$this->logger->warning($final);
$status &= false;
}
}
return $status;
}
}

View File

@ -1,12 +1,14 @@
<?php
namespace Incoviba\Service\Venta;
use PDOException;
use DateTimeImmutable;
use DateInterval;
use Incoviba\Common\Implement\Exception\EmptyResult;
use IntlDateFormatter;
use Psr\Log\LoggerInterface;
use Incoviba\Common\Ideal;
use Incoviba\Common\Implement\Exception\EmptyResult;
use Incoviba\Exception\ServiceAction\Create;
use Incoviba\Repository;
use Incoviba\Model;
@ -92,9 +94,18 @@ class Cuota extends Ideal\Service
return $this->cuotaRepository->fetchVigenteByPie($pie_id);
}
/**
* @param array $data
* @return Model\Venta\Cuota
* @throws Create
*/
public function add(array $data): Model\Venta\Cuota
{
$tipoPago = $this->tipoPagoRepository->fetchByDescripcion('cheque');
try {
$tipoPago = $this->tipoPagoRepository->fetchByDescripcion('cheque');
} catch (EmptyResult $exception) {
throw new Create(__CLASS__, $exception);
}
$fields = array_flip([
'fecha',
'banco',
@ -112,8 +123,11 @@ class Cuota extends Ideal\Service
$mapped_data = $filtered_data;
$mapped_data['valor_$'] = $mapped_data['valor'];
unset($mapped_data['valor']);
$cuota = $this->cuotaRepository->create($mapped_data);
$this->cuotaRepository->save($cuota);
return $cuota;
try {
$cuota = $this->cuotaRepository->create($mapped_data);
return $this->cuotaRepository->save($cuota);
} catch (PDOException $exception) {
throw new Create(__CLASS__, $exception);
}
}
}

View File

@ -1,14 +1,15 @@
<?php
namespace Incoviba\Service\MediosPago;
namespace Incoviba\Service\Venta\MediosPago;
use HttpException;
use Incoviba\Common\Define\Repository;
use Incoviba\Common\Ideal\LoggerEnabled;
use Incoviba\Common\Implement\Exception\{EmptyResponse, EmptyResult};
use Incoviba\Exception\InvalidResult;
use PDOException;
use Psr\Http\Client\ClientExceptionInterface;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\ResponseInterface;
use Incoviba\Common\Define\Repository;
use Incoviba\Common\Implement\Exception\{EmptyResponse, EmptyResult};
use Incoviba\Common\Ideal\LoggerEnabled;
abstract class AbstractEndPoint extends LoggerEnabled implements EndPoint
{
@ -147,7 +148,7 @@ abstract class AbstractEndPoint extends LoggerEnabled implements EndPoint
* @param string $id
* @param string $message
* @return array
* @throws EmptyResponse
* @throws InvalidResult
*/
protected function doGetById(callable $callable, string $id, string $message): array
{
@ -155,7 +156,7 @@ abstract class AbstractEndPoint extends LoggerEnabled implements EndPoint
$model = $callable($id);
return json_decode(json_encode($model), true);
} catch (EmptyResult $exception) {
throw new EmptyResponse($message, $exception);
throw new InvalidResult($message, 404, $exception);
}
}

View File

@ -1,16 +1,24 @@
<?php
namespace Incoviba\Service\MediosPago;
namespace Incoviba\Service\Venta\MediosPago;
use Incoviba\Common\Implement\Exception\EmptyResponse;
use Incoviba\Exception\InvalidResult;
interface EndPoint
{
/**
* @param string $id
* @return array
* @throws EmptyResponse
* @throws InvalidResult
*/
public function getById(string $id): array;
/**
* @param string $id
* @return array
* @throws InvalidResult
*/
public function getByExternalId(string $id): array;
/**
* @param string $id
* @return array

View File

@ -1,12 +1,14 @@
<?php
namespace Incoviba\Service\MediosPago;
namespace Incoviba\Service\Venta\MediosPago;
use InvalidArgumentException;
use Psr\Http\Client\ClientInterface;
use Psr\Log\LoggerInterface;
use Incoviba\Common\Ideal;
use Incoviba\Common\Implement\Exception\EmptyResponse;
use Incoviba\Exception\InvalidResult;
use Incoviba\Model;
use Incoviba\Model\Persona;
use Incoviba\Model\Venta\Propietario;
use InvalidArgumentException;
use Psr\Log\LoggerInterface;
class Toku extends Ideal\Service
{
@ -32,16 +34,16 @@ class Toku extends Ideal\Service
}
/**
* @param Model\Persona $persona
* @param Persona|Propietario $persona
* @return array
* @throws EmptyResponse
* @throws InvalidResult
*/
public function sendPersona(Model\Persona|Model\Venta\Propietario $persona): array
{
$rut = implode('', [$persona->rut, strtoupper($persona->dv)]);
try {
return $this->customer->getById($rut);
} catch (EmptyResponse $exception) {
} catch (InvalidResult $exception) {
$datos = $persona->datos;
$customerData = [
'rut' => $rut,
@ -49,30 +51,38 @@ class Toku extends Ideal\Service
'email' => $datos?->email ?? '',
'telefono' => $datos?->telefono ?? ''
];
if (!$this->customer->add($customerData)) {
throw new EmptyResponse("Could not save Customer for Persona {$rut}", $exception);
try {
if (!$this->customer->add($customerData)) {
throw new InvalidResult("Could not save Customer for Persona {$rut}", 409, $exception);
}
} catch (EmptyResponse $exception) {
throw new InvalidResult("Could not save Customer for Persona {$rut}", 409, $exception);
}
return $this->customer->getById($rut);
}
}
/**
* @param Model\Venta $venta
* @return bool
* @throws EmptyResponse
* @return array
* @throws InvalidResult
*/
public function sendVenta(Model\Venta $venta): array
{
$customer = $this->sendPersona($venta->propietario());
try {
return $this->subscription->getById($venta->id);
} catch (EmptyResponse $exception) {
} catch (InvalidResult $exception) {
$subscriptionData = [
'customer' => $customer['toku_id'],
'product_id' => $venta->id,
'venta' => $venta
];
if (!$this->subscription->add($subscriptionData)) {
throw new EmptyResponse("Could not save Subscription for Venta {$venta->id}", $exception);
try {
if (!$this->subscription->add($subscriptionData)) {
throw new InvalidResult("Could not save Subscription for Venta {$venta->id}", 409, $exception);
}
} catch (EmptyResponse $exception) {
throw new InvalidResult("Could not save Subscription for Venta {$venta->id}", 409, $exception);
}
return $this->subscription->getById($venta->id);
}
@ -80,10 +90,11 @@ class Toku extends Ideal\Service
/**
* @param Model\Venta $venta
* @param array $cuotas_ids
* @return array
* @throws EmptyResponse
* @throws InvalidResult
*/
public function sendCuotas(Model\Venta $venta): array
public function sendCuotas(Model\Venta $venta, array $cuotas_ids = []): array
{
$customer = $this->sendPersona($venta->propietario());
$subscription = $this->sendVenta($venta);
@ -91,9 +102,12 @@ class Toku extends Ideal\Service
$invoices = [];
$errors = [];
foreach ($venta->formaPago()->pie->cuotas() as $cuota) {
if (count($cuotas_ids) > 0 and !in_array($cuota->id, $cuotas_ids)) {
continue;
}
try {
$invoices []= $this->invoice->getById($cuota->id);
} catch (EmptyResponse $exception) {
} catch (InvalidResult $exception) {
try {
$invoiceData = [
'customer' => $customer['toku_id'],
@ -116,4 +130,18 @@ class Toku extends Ideal\Service
}
return $invoices;
}
/**
* @param array $request
* @return bool
* @throws InvalidResult
*/
public function updatePago(array $request): bool
{
# If $customer is not found, it will throw an exception and stop
$customer = $this->customer->getByExternalId($request['customer']);
$invoice = $this->invoice->getByExternalId($request['invoice']);
return $this->invoice->update($invoice['id'], $request);
}
}

View File

@ -1,14 +1,14 @@
<?php
namespace Incoviba\Service\MediosPago\Toku;
namespace Incoviba\Service\Venta\MediosPago\Toku;
use Psr\Http\Client\ClientInterface;
use Incoviba\Repository;
use Incoviba\Service\MediosPago\AbstractEndPoint;
use Incoviba\Service\Venta\MediosPago\AbstractEndPoint;
use Psr\Http\Client\ClientInterface;
class Customer extends AbstractEndPoint
{
public function __construct(ClientInterface $client,
protected Repository\MediosPago\Toku\Customer $customerRepository)
public function __construct(ClientInterface $client,
protected Repository\Venta\MediosPago\Toku\Customer $customerRepository)
{
parent::__construct($client);
}
@ -17,6 +17,10 @@ class Customer extends AbstractEndPoint
{
return $this->doGetById([$this->customerRepository, 'fetchByRut'], $id, "No existe toku_id para Persona {$id}");
}
public function getByExternalId(string $id): array
{
return $this->doGetById([$this->customerRepository, 'fetchByTokuId'], $id, "No existe Customer para toku_id {$id}");
}
public function get(string $id): array
{
$request_uri = "/customers/{$id}";

View File

@ -1,14 +1,22 @@
<?php
namespace Incoviba\Service\MediosPago\Toku;
namespace Incoviba\Service\Venta\MediosPago\Toku;
use Incoviba\Model\Venta\Cuota;
use Psr\Http\Client\ClientInterface;
use DateMalformedStringException;
use DateTimeImmutable;
use Incoviba\Common\Implement\Exception\EmptyResult;
use Incoviba\Exception\InvalidResult;
use Incoviba\Model;
use Incoviba\Repository;
use Incoviba\Service\MediosPago\AbstractEndPoint;
use Incoviba\Service\UF;
use Incoviba\Service\Venta\MediosPago\AbstractEndPoint;
use Incoviba\Service\Venta\Pago;
use Psr\Http\Client\ClientInterface;
class Invoice extends AbstractEndPoint
{
public function __construct(ClientInterface $client, protected Repository\MediosPago\Toku\Invoice $invoiceRepository)
public function __construct(ClientInterface $client,
protected Repository\Venta\MediosPago\Toku\Invoice $invoiceRepository,
protected Pago $pagoService, protected UF $ufService)
{
parent::__construct($client);
}
@ -17,6 +25,10 @@ class Invoice extends AbstractEndPoint
{
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}";
@ -38,6 +50,38 @@ class Invoice extends AbstractEndPoint
$this->sendDelete($request_uri, [204], [404, 409]);
}
/**
* @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) {
throw new InvalidResult("No existe Invoice para toku_id {$invoice_toku_id}", 404, $exception);
}
if ($data['status'] !== 'AUTHORIZED') {
throw new InvalidResult("Pago no autorizado", 422);
}
try {
$date = new DateTimeImmutable($data['transaction_date']);
} catch (DateMalformedStringException $exception) {
throw new InvalidResult("Fecha no válida: {$data['transaction_date']}", 422, $exception);
}
$uf = $this->ufService->get($date);
if ($uf === 0.0) {
throw new InvalidResult("No hay UF para la fecha: {$data['transaction_date']}", 422);
}
$valor = $data['amount'] / $uf;
if (abs($valor - $invoice->cuota->pago->valor()) >= 0.0001) {
throw new InvalidResult("Valor en UF no coincide: {$data['amount']}", 422);
}
return $this->pagoService->depositar($invoice->cuota->pago, $date);
}
protected function save(array $data): bool
{
return $this->doSave($this->invoiceRepository, $data);
@ -71,7 +115,7 @@ class Invoice extends AbstractEndPoint
continue;
}
if ($ref === 'valor') {
$params[$key] = $data['cuota']->pago->valor;
$params[$key] = $data['cuota']->pago->valor();
continue;
}
if ($ref === 'datosCuota') {
@ -104,7 +148,7 @@ class Invoice extends AbstractEndPoint
return $mappedData;
}
protected function datosCuota(Cuota $cuota): string
protected function datosCuota(Model\Venta\Cuota $cuota): string
{
return json_encode([
'Numero' => $cuota->numero,

View File

@ -1,14 +1,14 @@
<?php
namespace Incoviba\Service\MediosPago\Toku;
namespace Incoviba\Service\Venta\MediosPago\Toku;
use Psr\Http\Client\ClientInterface;
use Incoviba\Model\Venta;
use Incoviba\Repository;
use Incoviba\Service\MediosPago\AbstractEndPoint;
use Incoviba\Service\Venta\MediosPago\AbstractEndPoint;
use Psr\Http\Client\ClientInterface;
class Subscription extends AbstractEndPoint
{
public function __construct(ClientInterface $client, protected Repository\MediosPago\Toku\Subscription $subscriptionRepsitory)
public function __construct(ClientInterface $client, protected Repository\Venta\MediosPago\Toku\Subscription $subscriptionRepsitory)
{
parent::__construct($client);
}
@ -17,6 +17,11 @@ class Subscription extends AbstractEndPoint
{
return $this->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}";

View File

@ -4,6 +4,7 @@ namespace Incoviba\Service\Venta;
use DateTimeInterface;
use DateTimeImmutable;
use DateMalformedStringException;
use Incoviba\Exception\ServiceAction\Create;
use Incoviba\Exception\ServiceAction\Read;
use Incoviba\Exception\ServiceAction\Update;
use PDOException;
@ -129,6 +130,11 @@ class Pago
}
}
/**
* @param array $data
* @return Model\Venta\Pago
* @throws Create
*/
public function add(array $data): Model\Venta\Pago
{
if (array_key_exists('fecha', $data)) {
@ -146,16 +152,24 @@ class Pago
$filtered_data = $this->pagoRepository->filterData($data);
$pago = $this->pagoRepository->create($filtered_data);
$pago = $this->pagoRepository->save($pago);
try {
$pago = $this->pagoRepository->create($filtered_data);
$pago = $this->pagoRepository->save($pago);
} catch (PDOException $exception) {
throw new Create(__CLASS__, $exception);
}
$tipoEstado = $this->tipoEstadoPagoRepository->fetchByDescripcion('no pagado');
$estado = $this->estadoPagoRepository->create([
'pago' => $pago->id,
'fecha' => $pago->fecha->format('Y-m-d'),
'estado' => $tipoEstado->id
]);
$estado = $this->estadoPagoRepository->save($estado);
try {
$estado = $this->estadoPagoRepository->create([
'pago' => $pago->id,
'fecha' => $pago->fecha->format('Y-m-d'),
'estado' => $tipoEstado->id
]);
$estado = $this->estadoPagoRepository->save($estado);
} catch (PDOException $exception) {
throw new Create(__CLASS__, $exception);
}
$pago->currentEstado = $estado;
return $pago;
}

View File

@ -53,6 +53,12 @@ class Pie
throw new Create(__CLASS__, $exception);
}
}
/**
* @param array $data
* @return Model\Venta\Cuota
* @throws Create
*/
public function addCuota(array $data): Model\Venta\Cuota
{
return $this->cuotaService->add($data);

View File

@ -0,0 +1,9 @@
<?php
namespace Incoviba\Service;
use Incoviba\Model;
interface Worker
{
public function execute(Model\Job $job): bool;
}

View File

@ -0,0 +1,50 @@
<?php
namespace Incoviba\Service\Worker;
use Incoviba\Common\Implement\Exception\EmptyResponse;
use Psr\Http\Client\ClientExceptionInterface;
use Psr\Http\Client\ClientInterface;
use Psr\Log\LoggerInterface;
use Incoviba\Common\Ideal;
use Incoviba\Model;
class Request extends Ideal\Service
{
public function __construct(LoggerInterface $logger, protected ClientInterface $client)
{
parent::__construct($logger);
}
/**
* @param Model\Job $job
* @return bool
* @throws EmptyResponse
*/
public function execute(Model\Job $job): bool
{
$url = $job->configuration['url'];
$method = strtolower($job->configuration['method']);
$body = $job->configuration['body'];
try {
$response = $this->client->{$method}($url, [
'json' => $body,
]);
} catch (ClientExceptionInterface $exception) {
throw new EmptyResponse($url, $exception);
}
$statusCode = $response->getStatusCode();
if ((int) floor($statusCode / 100) !== 2) {
throw new EmptyResponse($url);
}
if ($statusCode !== 204) {
$contents = $response->getBody()->getContents();
$data = json_decode($contents, true);
if (!isset($data['success']) or !$data['success']) {
throw new EmptyResponse($url);
}
}
return true;
}
}

View File

@ -1,14 +1,17 @@
<?php
namespace Test\Unit\Model\MediosPago\Toku;
namespace Test\Unit\Model\Venta\MediosPago\Toku;
use Faker;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Incoviba\Model\MediosPago\Toku\Customer;
use Tests\Extension\ObjectHasMethodTrait;
use Incoviba\Model\Persona;
use Incoviba\Model\Venta\MediosPago\Toku\Customer;
class CustomerTest extends TestCase
{
use ObjectHasMethodTrait;
public static function dataProperties(): array
{
return [
@ -17,7 +20,6 @@ class CustomerTest extends TestCase
['toku_id']
];
}
#[DataProvider('dataProperties')]
public function testProperties(string $propertyName): void
{
@ -26,6 +28,20 @@ class CustomerTest extends TestCase
$this->assertObjectHasProperty($propertyName, $customer);
}
public static function dataMethods(): array
{
return [
['rut']
];
}
#[DataProvider('dataMethods')]
public function testMethods(string $methodName): void
{
$customer = new Customer();
$this->assertObjectHasMethod($methodName, $customer);
}
public function testJson(): void
{
$faker = Faker\Factory::create();

View File

@ -1,5 +1,5 @@
<?php
namespace Tests\Unit\Model\MediosPago\Toku;
namespace Tests\Unit\Model\Venta\MediosPago\Toku;
use Faker;
use PHPUnit\Framework\Attributes\DataProvider;
@ -19,7 +19,7 @@ class InvoiceTest extends TestCase
#[DataProvider('dataProperties')]
public function testProperties(string $propertyName): void
{
$invoice = new Model\MediosPago\Toku\Invoice();
$invoice = new Model\Venta\MediosPago\Toku\Invoice();
$this->assertObjectHasProperty($propertyName, $invoice);
}
@ -35,7 +35,7 @@ class InvoiceTest extends TestCase
$id = $faker->randomNumber();
$invoice = new Model\MediosPago\Toku\Invoice();
$invoice = new Model\Venta\MediosPago\Toku\Invoice();
$invoice->id = $id;
$invoice->cuota = $cuota;
$invoice->toku_id = $toku_id;

View File

@ -1,5 +1,5 @@
<?php
namespace Tests\Unit\Model\MediosPago\Toku;
namespace Tests\Unit\Model\Venta\MediosPago\Toku;
use Faker;
use PHPUnit\Framework\Attributes\DataProvider;
@ -19,7 +19,7 @@ class SubscriptionTest extends TestCase
#[DataProvider('dataProperties')]
public function testProperties(string $propertyName): void
{
$subscription = new Model\MediosPago\Toku\Subscription();
$subscription = new Model\Venta\MediosPago\Toku\Subscription();
$this->assertObjectHasProperty($propertyName, $subscription);
}
@ -34,7 +34,7 @@ class SubscriptionTest extends TestCase
$id = $faker->randomNumber();
$subscription = new Model\MediosPago\Toku\Subscription();
$subscription = new Model\Venta\MediosPago\Toku\Subscription();
$subscription->id = $id;
$subscription->venta = $venta;
$subscription->toku_id = $toku_id;

View File

@ -1,14 +1,14 @@
<?php
namespace Tests\Unit\Repository\MediosPago\Toku;
namespace Tests\Unit\Repository\Venta\MediosPago\Toku;
use PDO;
use PHPUnit\Framework\Attributes\Depends;
use PHPUnit\Framework\TestCase;
use Faker;
use Incoviba\Common\Define;
use Incoviba\Model;
use Incoviba\Repository;
use Incoviba\Service;
use PDO;
use PHPUnit\Framework\Attributes\Depends;
use PHPUnit\Framework\TestCase;
class CustomerTest extends TestCase
{
@ -47,7 +47,7 @@ class CustomerTest extends TestCase
public function testCreate(): void
{
$repository = new Repository\MediosPago\Toku\Customer($this->connection, $this->personaService);
$repository = new Repository\Venta\MediosPago\Toku\Customer($this->connection, $this->personaService);
$faker = Faker\Factory::create();
$data = [
@ -59,9 +59,9 @@ class CustomerTest extends TestCase
$this->assertEquals($this->persona, $customer->persona);
$this->assertEquals($data['toku_id'], $customer->toku_id);
}
public function testSave(): Model\MediosPago\Toku\Customer
public function testSave(): Model\Venta\MediosPago\Toku\Customer
{
$repository = new Repository\MediosPago\Toku\Customer($this->connection, $this->personaService);
$repository = new Repository\Venta\MediosPago\Toku\Customer($this->connection, $this->personaService);
$faker = Faker\Factory::create();
$data = [
@ -77,7 +77,7 @@ class CustomerTest extends TestCase
return $customer;
}
#[Depends('testSave')]
public function testFetch(Model\MediosPago\Toku\Customer $reference): void
public function testFetch(Model\Venta\MediosPago\Toku\Customer $reference): void
{
$result = [
'id' => $reference->id,
@ -89,16 +89,16 @@ class CustomerTest extends TestCase
$resultSet->method('fetch')->willReturn($result);
$this->connection->method('execute')->willReturn($resultSet);
$repository = new Repository\MediosPago\Toku\Customer($this->connection, $this->personaService);
$repository = new Repository\Venta\MediosPago\Toku\Customer($this->connection, $this->personaService);
$customer = $repository->fetchById($reference->id);
$this->assertInstanceOf(Model\MediosPago\Toku\Customer::class, $customer);
$this->assertInstanceOf(Model\Venta\MediosPago\Toku\Customer::class, $customer);
$this->assertEquals($reference->id, $customer->id);
$this->assertEquals($this->persona, $customer->persona);
$this->assertEquals($reference->toku_id, $customer->toku_id);
}
#[Depends('testSave')]
public function testFetchByRut(Model\MediosPago\Toku\Customer $reference): void
public function testFetchByRut(Model\Venta\MediosPago\Toku\Customer $reference): void
{
$result = [
'id' => $reference->id,
@ -110,11 +110,30 @@ class CustomerTest extends TestCase
$resultSet->method('fetch')->willReturn($result);
$this->connection->method('execute')->willReturn($resultSet);
$repository = new Repository\MediosPago\Toku\Customer($this->connection, $this->personaService);
$repository = new Repository\Venta\MediosPago\Toku\Customer($this->connection, $this->personaService);
$customer = $repository->fetchByRut($this->persona->rut);
$this->assertEquals($reference->id, $customer->id);
$this->assertEquals($this->persona, $customer->persona);
$this->assertEquals($reference->toku_id, $customer->toku_id);
}
#[Depends('testSave')]
public function testFetchByTokuId(Model\Venta\MediosPago\Toku\Customer $reference): void
{
$result = [
'id' => $reference->id,
'rut' => implode('', [$this->persona->rut, $this->persona->digito]),
'toku_id' => $reference->toku_id,
];
$resultSet = $this->getMockBuilder(\PDOStatement::class)
->disableOriginalConstructor()->getMock();
$resultSet->method('fetch')->willReturn($result);
$this->connection->method('execute')->willReturn($resultSet);
$repository = new Repository\Venta\MediosPago\Toku\Customer($this->connection, $this->personaService);
$customer = $repository->fetchByTokuId($reference->toku_id);
$this->assertEquals($reference->id, $customer->id);
$this->assertEquals($this->persona, $customer->persona);
$this->assertEquals($reference->toku_id, $customer->toku_id);
}
}

View File

@ -1,13 +1,13 @@
<?php
namespace Tests\Unit\Repository\MediosPago\Toku;
namespace Tests\Unit\Repository\Venta\MediosPago\Toku;
use PDO;
use PHPUnit\Framework\Attributes\Depends;
use PHPUnit\Framework\TestCase;
use Faker;
use Incoviba\Common\Define;
use Incoviba\Model;
use Incoviba\Repository;
use PDO;
use PHPUnit\Framework\Attributes\Depends;
use PHPUnit\Framework\TestCase;
class InvoiceTest extends TestCase
{
@ -38,7 +38,7 @@ class InvoiceTest extends TestCase
public function testCreate(): void
{
$repository = new Repository\MediosPago\Toku\Invoice($this->connection, $this->cuotaRepository);
$repository = new Repository\Venta\MediosPago\Toku\Invoice($this->connection, $this->cuotaRepository);
$faker = Faker\Factory::create();
$data = [
@ -51,9 +51,9 @@ class InvoiceTest extends TestCase
$this->assertEquals($this->cuota->id, $invoice->cuota->id);
$this->assertEquals($data['toku_id'], $invoice->toku_id);
}
public function testSave(): Model\MediosPago\Toku\Invoice
public function testSave(): Model\Venta\MediosPago\Toku\Invoice
{
$repository = new Repository\MediosPago\Toku\Invoice($this->connection, $this->cuotaRepository);
$repository = new Repository\Venta\MediosPago\Toku\Invoice($this->connection, $this->cuotaRepository);
$faker = Faker\Factory::create();
$data = [
@ -70,7 +70,7 @@ class InvoiceTest extends TestCase
return $invoice;
}
#[Depends('testSave')]
public function testFetch(Model\MediosPago\Toku\Invoice $reference): void
public function testFetch(Model\Venta\MediosPago\Toku\Invoice $reference): void
{
$result = [
'id' => $reference->id,
@ -82,16 +82,16 @@ class InvoiceTest extends TestCase
$resultSet->method('fetch')->willReturn($result);
$this->connection->method('execute')->willReturn($resultSet);
$repository = new Repository\MediosPago\Toku\Invoice($this->connection, $this->cuotaRepository);
$repository = new Repository\Venta\MediosPago\Toku\Invoice($this->connection, $this->cuotaRepository);
$invoice = $repository->fetchById($reference->id);
$this->assertInstanceOf(Model\MediosPago\Toku\Invoice::class, $invoice);
$this->assertInstanceOf(Model\Venta\MediosPago\Toku\Invoice::class, $invoice);
$this->assertEquals($reference->id, $invoice->id);
$this->assertEquals($this->cuota->id, $invoice->cuota->id);
$this->assertEquals($reference->toku_id, $invoice->toku_id);
}
#[Depends('testSave')]
public function testFetchByCuota(Model\MediosPago\Toku\Invoice $reference): void
public function testFetchByCuota(Model\Venta\MediosPago\Toku\Invoice $reference): void
{
$result = [
'id' => $reference->id,
@ -103,11 +103,31 @@ class InvoiceTest extends TestCase
$resultSet->method('fetch')->willReturn($result);
$this->connection->method('execute')->willReturn($resultSet);
$repository = new Repository\MediosPago\Toku\Invoice($this->connection, $this->cuotaRepository);
$repository = new Repository\Venta\MediosPago\Toku\Invoice($this->connection, $this->cuotaRepository);
$invoice = $repository->fetchByCuota($this->cuota->id);
$this->assertEquals($reference->id, $invoice->id);
$this->assertEquals($this->cuota->id, $invoice->cuota->id);
$this->assertEquals($reference->toku_id, $invoice->toku_id);
}
#[Depends('testSave')]
public function testFetchByTokuId(Model\Venta\MediosPago\Toku\Invoice $reference): void
{
$result = [
'id' => $reference->id,
'cuota_id' => $this->cuota->id,
'toku_id' => $reference->toku_id,
];
$resultSet = $this->getMockBuilder(\PDOStatement::class)
->disableOriginalConstructor()->getMock();
$resultSet->method('fetch')->willReturn($result);
$this->connection->method('execute')->willReturn($resultSet);
$repository = new Repository\Venta\MediosPago\Toku\Invoice($this->connection, $this->cuotaRepository);
$invoice = $repository->fetchByTokuId($reference->toku_id);
$this->assertEquals($reference->id, $invoice->id);
$this->assertEquals($this->cuota->id, $invoice->cuota->id);
$this->assertEquals($reference->toku_id, $invoice->toku_id);
}
}

View File

@ -1,13 +1,13 @@
<?php
namespace Tests\Unit\Repository\MediosPago\Toku;
namespace Tests\Unit\Repository\Venta\MediosPago\Toku;
use PDO;
use PHPUnit\Framework\Attributes\Depends;
use PHPUnit\Framework\TestCase;
use Faker;
use Incoviba\Common\Define;
use Incoviba\Model;
use Incoviba\Repository;
use PDO;
use PHPUnit\Framework\Attributes\Depends;
use PHPUnit\Framework\TestCase;
class SubscriptionTest extends TestCase
{
@ -38,7 +38,7 @@ class SubscriptionTest extends TestCase
public function testCreate(): void
{
$repository = new Repository\MediosPago\Toku\Subscription($this->connection, $this->ventaRepository);
$repository = new Repository\Venta\MediosPago\Toku\Subscription($this->connection, $this->ventaRepository);
$faker = Faker\Factory::create();
$data = [
@ -50,9 +50,9 @@ class SubscriptionTest extends TestCase
$this->assertEquals($this->venta->id, $subscription->venta->id);
$this->assertEquals($data['toku_id'], $subscription->toku_id);
}
public function testSave(): Model\MediosPago\Toku\Subscription
public function testSave(): Model\Venta\MediosPago\Toku\Subscription
{
$repository = new Repository\MediosPago\Toku\Subscription($this->connection, $this->ventaRepository);
$repository = new Repository\Venta\MediosPago\Toku\Subscription($this->connection, $this->ventaRepository);
$faker = Faker\Factory::create();
$data = [
@ -69,7 +69,7 @@ class SubscriptionTest extends TestCase
return $subscription;
}
#[Depends('testSave')]
public function testFetch(Model\MediosPago\Toku\Subscription $reference): void
public function testFetch(Model\Venta\MediosPago\Toku\Subscription $reference): void
{
$result = [
'id' => $reference->id,
@ -82,15 +82,15 @@ class SubscriptionTest extends TestCase
$resultSet->method('fetch')->willReturn($result);
$this->connection->method('execute')->willReturn($resultSet);
$repository = new Repository\MediosPago\Toku\Subscription($this->connection, $this->ventaRepository);
$repository = new Repository\Venta\MediosPago\Toku\Subscription($this->connection, $this->ventaRepository);
$subscription = $repository->fetchById($reference->id);
$this->assertInstanceOf(Model\MediosPago\Toku\Subscription::class, $subscription);
$this->assertInstanceOf(Model\Venta\MediosPago\Toku\Subscription::class, $subscription);
$this->assertEquals($reference->id, $subscription->id);
$this->assertEquals($this->venta->id, $subscription->venta->id);
$this->assertEquals($reference->toku_id, $subscription->toku_id);
}
#[Depends('testSave')]
public function testFetchByVenta(Model\MediosPago\Toku\Subscription $reference): void
public function testFetchByVenta(Model\Venta\MediosPago\Toku\Subscription $reference): void
{
$result = [
'id' => $reference->id,
@ -103,10 +103,30 @@ class SubscriptionTest extends TestCase
$resultSet->method('fetch')->willReturn($result);
$this->connection->method('execute')->willReturn($resultSet);
$repository = new Repository\MediosPago\Toku\Subscription($this->connection, $this->ventaRepository);
$repository = new Repository\Venta\MediosPago\Toku\Subscription($this->connection, $this->ventaRepository);
$subscription = $repository->fetchByVenta($this->venta->id);
$this->assertEquals($reference->id, $subscription->id);
$this->assertEquals($this->venta->id, $subscription->venta->id);
$this->assertEquals($reference->toku_id, $subscription->toku_id);
}
#[Depends('testSave')]
public function testFetchByTokuId(Model\Venta\MediosPago\Toku\Subscription $reference): void
{
$result = [
'id' => $reference->id,
'venta_id' => $this->venta->id,
'toku_id' => $reference->toku_id,
];
$resultSet = $this->getMockBuilder(\PDOStatement::class)
->disableOriginalConstructor()->getMock();
$resultSet->method('fetch')->willReturn($result);
$this->connection->method('execute')->willReturn($resultSet);
$repository = new Repository\Venta\MediosPago\Toku\Subscription($this->connection, $this->ventaRepository);
$subscription = $repository->fetchByTokuId($reference->toku_id);
$this->assertEquals($reference->id, $subscription->id);
$this->assertEquals($this->venta->id, $subscription->venta->id);
$this->assertEquals($reference->toku_id, $subscription->toku_id);
}
}

View File

@ -1,22 +1,22 @@
<?php
namespace Tests\Unit\Service\MediosPago\Toku;
namespace Tests\Unit\Service\Venta\MediosPago\Toku;
use PDO;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;
use PHPUnit\Framework\TestCase;
use Faker;
use GuzzleHttp\Client;
use Incoviba\Common\Define;
use Incoviba\Repository;
use Incoviba\Model;
use Incoviba\Repository;
use Incoviba\Service;
use PDO;
use PHPUnit\Framework\TestCase;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;
class CustomerTest extends TestCase
{
protected Client $client;
protected Model\MediosPago\Toku\Customer $customer;
protected Repository\MediosPago\Toku\Customer $customerRepository;
protected Model\Venta\MediosPago\Toku\Customer $customer;
protected Repository\Venta\MediosPago\Toku\Customer $customerRepository;
protected array $getData;
protected array $postData;
@ -50,7 +50,7 @@ class CustomerTest extends TestCase
$persona->apellidoMaterno
]));
$this->customer = $this->getMockBuilder(Model\MediosPago\Toku\Customer::class)
$this->customer = $this->getMockBuilder(Model\Venta\MediosPago\Toku\Customer::class)
->disableOriginalConstructor()->getMock();
$this->customer->id = $faker->randomNumber();
$this->customer->persona = $persona;
@ -65,10 +65,11 @@ class CustomerTest extends TestCase
'toku_id' => $this->customer->toku_id
]);
$this->customerRepository = $this->getMockBuilder(Repository\MediosPago\Toku\Customer::class)
$this->customerRepository = $this->getMockBuilder(Repository\Venta\MediosPago\Toku\Customer::class)
->disableOriginalConstructor()->getMock();
$this->customerRepository->method('fetchById')->willReturn($this->customer);
$this->customerRepository->method('fetchByRut')->willReturn($this->customer);
$this->customerRepository->method('fetchByTokuId')->willReturn($this->customer);
$this->getData = [
'id' => $this->customer->id,
@ -147,19 +148,25 @@ class CustomerTest extends TestCase
public function testGetById(): void
{
$service = new Service\MediosPago\Toku\Customer($this->client, $this->customerRepository);
$service = new Service\Venta\MediosPago\Toku\Customer($this->client, $this->customerRepository);
$this->assertEquals(json_decode(json_encode($this->customer), true), $service->getById($this->customer->id));
}
public function testGetByExternalId(): void
{
$service = new Service\Venta\MediosPago\Toku\Customer($this->client, $this->customerRepository);
$this->assertEquals(json_decode(json_encode($this->customer), true), $service->getByExternalId($this->customer->rut()));
}
public function testGet(): void
{
$service = new Service\MediosPago\Toku\Customer($this->client, $this->customerRepository);
$service = new Service\Venta\MediosPago\Toku\Customer($this->client, $this->customerRepository);
$this->assertArrayIsEqualToArrayIgnoringListOfKeys($this->getData, $service->get($this->customer->toku_id), []);
}
public function testAdd(): void
{
$service = new Service\MediosPago\Toku\Customer($this->client, $this->customerRepository);
$service = new Service\Venta\MediosPago\Toku\Customer($this->client, $this->customerRepository);
$sendData = [
'rut' => $this->postData['government_id'],
@ -171,7 +178,7 @@ class CustomerTest extends TestCase
}
public function testEdit(): void
{
$service = new Service\MediosPago\Toku\Customer($this->client, $this->customerRepository);
$service = new Service\Venta\MediosPago\Toku\Customer($this->client, $this->customerRepository);
$sendData = [
'rut' => $this->postData['government_id'],
@ -183,7 +190,7 @@ class CustomerTest extends TestCase
}
public function testDelete(): void
{
$service = new Service\MediosPago\Toku\Customer($this->client, $this->customerRepository);
$service = new Service\Venta\MediosPago\Toku\Customer($this->client, $this->customerRepository);
$this->expectNotToPerformAssertions();
$service->delete($this->customer->toku_id);

View File

@ -1,25 +1,28 @@
<?php
namespace Tests\Unit\Service\MediosPago\Toku;
namespace Tests\Unit\Service\Venta\MediosPago\Toku;
use PDO;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;
use PHPUnit\Framework\TestCase;
use Faker;
use GuzzleHttp\Client;
use Incoviba\Common\Define;
use Incoviba\Repository;
use Incoviba\Model;
use Incoviba\Repository;
use Incoviba\Service;
use PDO;
use PHPUnit\Framework\TestCase;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;
class InvoiceTest extends TestCase
{
protected Client $client;
protected Model\MediosPago\Toku\Invoice $invoice;
protected Repository\MediosPago\Toku\Invoice $invoiceRepository;
protected Model\Venta\MediosPago\Toku\Invoice $invoice;
protected Repository\Venta\MediosPago\Toku\Invoice $invoiceRepository;
protected Model\Venta\Cuota $cuota;
protected Service\Venta\Pago $pagoService;
protected Service\UF $ufService;
protected array $getData;
protected array $saveData;
protected \DateTimeInterface $fechaUF2;
protected function setUp(): void
{
@ -32,31 +35,47 @@ class InvoiceTest extends TestCase
$faker = Faker\Factory::create();
$customer = $this->getMockBuilder(Model\MediosPago\Toku\Customer::class)
$customer = $this->getMockBuilder(Model\Venta\MediosPago\Toku\Customer::class)
->disableOriginalConstructor()->getMock();
$customer->id = $faker->randomNumber();
$customer->toku_id = $faker->ean13();
$venta = $this->getMockBuilder(Model\Venta::class)
->disableOriginalConstructor()->getMock();
$venta->id = $faker->randomNumber();
$subscription = $this->getMockBuilder(Model\MediosPago\Toku\Subscription::class)
$subscription = $this->getMockBuilder(Model\Venta\MediosPago\Toku\Subscription::class)
->disableOriginalConstructor()->getMock();
$subscription->id = $faker->randomNumber();
$subscription->venta = $venta;
$subscription->toku_id = $faker->ean13();
$fechaUF1 = $faker->dateTimeInInterval('-3 years', '-1 weeks');
$this->fechaUF2 = $faker->dateTimeInInterval('-1 month', 'now');
$uf1 = $faker->randomFloat(2, 30000, 40000);
$uf2 = $faker->randomFloat(2, 30000, 40000);
$this->ufService = $this->getMockBuilder(Service\UF::class)
->disableOriginalConstructor()->getMock();
$this->ufService->method('get')->willReturnCallback(function(\DateTimeInterface $dateTime) use ($fechaUF1, $uf1, $uf2, $faker) {
return match ($dateTime->format('Y-m-d H:i:s')) {
$fechaUF1->format('Y-m-d H:i:s') => $uf1,
$this->fechaUF2->format('Y-m-d H:i:s') => $uf2,
default => $faker->randomFloat(2, 30000, 40000)
};
});
$pago = $this->getMockBuilder(Model\Venta\Pago::class)
->disableOriginalConstructor()->getMock();
$pago->fecha = $faker->dateTime();
$pago->fecha = $fechaUF1;
$pago->valor = $faker->randomNumber(6, true);
$pago->method('valor')->willReturn($faker->randomFloat(3, true));
$pago->uf = $uf1;
$pago->method('valor')->willReturn($pago->valor / $uf1);
$this->cuota = $this->getMockBuilder(Model\Venta\Cuota::class)
->disableOriginalConstructor()->getMock();
$this->cuota->id = $faker->randomNumber();
$this->cuota->numero = $faker->randomNumber(2);
$this->cuota->pago = $pago;
$this->invoice = $this->getMockBuilder(Model\MediosPago\Toku\Invoice::class)
$this->invoice = $this->getMockBuilder(Model\Venta\MediosPago\Toku\Invoice::class)
->disableOriginalConstructor()->getMock();
$this->invoice->id = $faker->randomNumber();
$this->invoice->cuota = $this->cuota;
@ -67,10 +86,11 @@ class InvoiceTest extends TestCase
'toku_id' => $this->invoice->toku_id
]);
$this->invoiceRepository = $this->getMockBuilder(Repository\MediosPago\Toku\Invoice::class)
$this->invoiceRepository = $this->getMockBuilder(Repository\Venta\MediosPago\Toku\Invoice::class)
->disableOriginalConstructor()->getMock();
$this->invoiceRepository->method('fetchById')->willReturn($this->invoice);
$this->invoiceRepository->method('fetchByCuota')->willReturn($this->invoice);
$this->invoiceRepository->method('fetchByTokuId')->willReturn($this->invoice);
$this->getData = [
'customer' => $customer->toku_id,
@ -151,22 +171,33 @@ class InvoiceTest extends TestCase
$this->client->method('post')->willReturn($postResponse);
$this->client->method('put')->willReturn($postResponse);
$this->client->method('delete')->willReturn($deleteResponse);
$this->pagoService = $this->getMockBuilder(Service\Venta\Pago::class)
->disableOriginalConstructor()->getMock();
$this->pagoService->method('depositar')->willReturn(true);
}
public function testGetById(): void
{
$service = new Service\MediosPago\Toku\Invoice($this->client, $this->invoiceRepository);
$this->assertEquals(json_decode(json_encode($this->invoice), true), $service->getById($this->invoice->toku_id));
$service = new Service\Venta\MediosPago\Toku\Invoice($this->client, $this->invoiceRepository, $this->pagoService, $this->ufService);
$this->assertEquals(json_decode(json_encode($this->invoice), true), $service->getById($this->cuota->id));
}
public function testGetByExternalId(): void
{
$service = new Service\Venta\MediosPago\Toku\Invoice($this->client, $this->invoiceRepository, $this->pagoService, $this->ufService);
$this->assertEquals(json_decode(json_encode($this->invoice), true), $service->getByExternalId($this->invoice->toku_id));
}
public function testGet(): void
{
$service = new Service\MediosPago\Toku\Invoice($this->client, $this->invoiceRepository);
$service = new Service\Venta\MediosPago\Toku\Invoice($this->client, $this->invoiceRepository, $this->pagoService, $this->ufService);
$this->assertEquals($this->getData, $service->get($this->invoice->toku_id));
}
public function testAdd(): void
{
$service = new Service\MediosPago\Toku\Invoice($this->client, $this->invoiceRepository);
$service = new Service\Venta\MediosPago\Toku\Invoice($this->client, $this->invoiceRepository, $this->pagoService, $this->ufService);
$sendData = [
'customer' => $this->postData['customer'],
@ -179,7 +210,7 @@ class InvoiceTest extends TestCase
}
public function testEdit(): void
{
$service = new Service\MediosPago\Toku\Invoice($this->client, $this->invoiceRepository);
$service = new Service\Venta\MediosPago\Toku\Invoice($this->client, $this->invoiceRepository, $this->pagoService, $this->ufService);
$sendData = [
'customer' => $this->postData['customer'],
@ -192,9 +223,43 @@ class InvoiceTest extends TestCase
}
public function testDelete(): void
{
$service = new Service\MediosPago\Toku\Invoice($this->client, $this->invoiceRepository);
$service = new Service\Venta\MediosPago\Toku\Invoice($this->client, $this->invoiceRepository, $this->pagoService, $this->ufService);
$this->expectNotToPerformAssertions();
$service->delete($this->invoice->toku_id);
}
public function testUpdate(): void
{
$faker = Faker\Factory::create();
$uf2 = $this->ufService->get($this->fechaUF2);
$valor = round($this->cuota->pago->valor() * $uf2);
$request = [
'id' => $faker->ean13(),
'event_type' => 'payment_intent.succeeded',
'payment_intent' => [
'id' => $faker->ean13(),
'invoice' => $this->invoice->toku_id,
'customer' => $this->getData['customer'],
'id_account' => $faker->ean13(),
'gateway' => 'khipu_transfer',
'amount' => $valor,
'status' => 'AUTHORIZED',
'payment_method' => $faker->ean13(),
'transaction_date' => $this->fechaUF2->format('Y-m-d H:i:s.u'),
'card_detail' => null,
'buy_order' => $faker->ean8(),
'child_buy_order' => null,
'authorization_code' => null,
'payment_type_code' => null,
'response_code' => null,
'toku_response_code' => null,
'installments_number' => null,
'mc_order_id' => null,
]
];
$service = new Service\Venta\MediosPago\Toku\Invoice($this->client, $this->invoiceRepository, $this->pagoService, $this->ufService);
$this->assertTrue($service->update($request['payment_intent']['invoice'], $request['payment_intent']));
}
}

View File

@ -1,22 +1,22 @@
<?php
namespace Tests\Unit\Service\MediosPago\Toku;
namespace Tests\Unit\Service\Venta\MediosPago\Toku;
use PDO;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;
use PHPUnit\Framework\TestCase;
use Faker;
use GuzzleHttp\Client;
use Incoviba\Common\Define;
use Incoviba\Repository;
use Incoviba\Model;
use Incoviba\Repository;
use Incoviba\Service;
use PDO;
use PHPUnit\Framework\TestCase;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;
class SubscriptionTest extends TestCase
{
protected Client $client;
protected Model\MediosPago\Toku\Subscription $subscription;
protected Repository\MediosPago\Toku\Subscription $subscriptionRepository;
protected Model\Venta\MediosPago\Toku\Subscription $subscription;
protected Repository\Venta\MediosPago\Toku\Subscription $subscriptionRepository;
protected Model\Venta $venta;
protected array $getData;
protected array $postData;
@ -32,7 +32,7 @@ class SubscriptionTest extends TestCase
$faker = Faker\Factory::create();
$customer = $this->getMockBuilder(Model\MediosPago\Toku\Customer::class)
$customer = $this->getMockBuilder(Model\Venta\MediosPago\Toku\Customer::class)
->disableOriginalConstructor()->getMock();
$customer->id = $faker->randomNumber();
@ -60,7 +60,7 @@ class SubscriptionTest extends TestCase
$this->venta->method('proyecto')->willReturn($proyecto);
$this->venta->method('propiedad')->willReturn($propiedad);
$this->subscription = $this->getMockBuilder(Model\MediosPago\Toku\Subscription::class)
$this->subscription = $this->getMockBuilder(Model\Venta\MediosPago\Toku\Subscription::class)
->disableOriginalConstructor()->getMock();
$this->subscription->id = $faker->randomNumber();
$this->subscription->venta = $this->venta;
@ -71,10 +71,11 @@ class SubscriptionTest extends TestCase
'toku_id' => $this->subscription->toku_id,
]);
$this->subscriptionRepository = $this->getMockBuilder(Repository\MediosPago\Toku\Subscription::class)
$this->subscriptionRepository = $this->getMockBuilder(Repository\Venta\MediosPago\Toku\Subscription::class)
->disableOriginalConstructor()->getMock();
$this->subscriptionRepository->method('fetchById')->willReturn($this->subscription);
$this->subscriptionRepository->method('fetchByVenta')->willReturn($this->subscription);
$this->subscriptionRepository->method('fetchByTokuId')->willReturn($this->subscription);
$this->getData = [
'id' => $this->subscription->toku_id,
@ -141,19 +142,25 @@ class SubscriptionTest extends TestCase
public function testGetById(): void
{
$service = new Service\MediosPago\Toku\Subscription($this->client, $this->subscriptionRepository);
$service = new Service\Venta\MediosPago\Toku\Subscription($this->client, $this->subscriptionRepository);
$this->assertEquals(json_decode(json_encode($this->subscription), true), $service->getById($this->subscription->toku_id));
}
public function testGetByExternalId(): void
{
$service = new Service\Venta\MediosPago\Toku\Subscription($this->client, $this->subscriptionRepository);
$this->assertEquals(json_decode(json_encode($this->subscription), true), $service->getByExternalId($this->subscription->toku_id));
}
public function testGet(): void
{
$service = new Service\MediosPago\Toku\Subscription($this->client, $this->subscriptionRepository);
$service = new Service\Venta\MediosPago\Toku\Subscription($this->client, $this->subscriptionRepository);
$this->assertArrayIsEqualToArrayIgnoringListOfKeys($this->getData, $service->get($this->subscription->toku_id), []);
}
public function testAdd(): void
{
$service = new Service\MediosPago\Toku\Subscription($this->client, $this->subscriptionRepository);
$service = new Service\Venta\MediosPago\Toku\Subscription($this->client, $this->subscriptionRepository);
$sendData = [
'customer' => $this->postData['customer'],
@ -164,7 +171,7 @@ class SubscriptionTest extends TestCase
}
public function testEdit(): void
{
$service = new Service\MediosPago\Toku\Subscription($this->client, $this->subscriptionRepository);
$service = new Service\Venta\MediosPago\Toku\Subscription($this->client, $this->subscriptionRepository);
$sendData = [
'customer' => $this->postData['customer'],
@ -175,7 +182,7 @@ class SubscriptionTest extends TestCase
}
public function testDelete(): void
{
$service = new Service\MediosPago\Toku\Subscription($this->client, $this->subscriptionRepository);
$service = new Service\Venta\MediosPago\Toku\Subscription($this->client, $this->subscriptionRepository);
$this->expectNotToPerformAssertions();
$service->delete($this->subscription->toku_id);

View File

@ -1,24 +1,26 @@
<?php
namespace Tests\Unit\Service\MediosPago;
namespace Tests\Unit\Service\Venta\MediosPago;
use Psr\Log\LoggerInterface;
use PHPUnit\Framework\TestCase;
use Faker;
use Incoviba\Exception\InvalidResult;
use Incoviba\Model;
use Incoviba\Service;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
class TokuTest extends TestCase
{
protected LoggerInterface $logger;
protected Service\MediosPago\Toku\Customer $customerService;
protected Service\MediosPago\Toku\Subscription $subscriptionService;
protected Service\MediosPago\Toku\Invoice $invoiceService;
protected Model\MediosPago\Toku\Customer $customer;
protected Model\MediosPago\Toku\Subscription $subscription;
protected Model\MediosPago\Toku\Invoice $invoice;
protected Service\Venta\MediosPago\Toku\Customer $customerService;
protected Service\Venta\MediosPago\Toku\Subscription $subscriptionService;
protected Service\Venta\MediosPago\Toku\Invoice $invoiceService;
protected Model\Venta\MediosPago\Toku\Customer $customer;
protected Model\Venta\MediosPago\Toku\Subscription $subscription;
protected Model\Venta\MediosPago\Toku\Invoice $invoice;
protected Model\Persona $persona;
protected Model\Venta $venta;
protected Model\Venta\Cuota $cuota;
protected Model\Venta\Pago $pago;
protected function setUp(): void
{
@ -40,7 +42,7 @@ class TokuTest extends TestCase
$this->persona->apellidoMaterno = $faker->lastName();
$this->persona->method('datos')->willReturn($datos);
$this->persona->method('__get')->with('dv')->willReturn($this->persona->digito);
$this->customer = $this->getMockBuilder(Model\MediosPago\Toku\Customer::class)
$this->customer = $this->getMockBuilder(Model\Venta\MediosPago\Toku\Customer::class)
->disableOriginalConstructor()->getMock();
$this->customer->id = $faker->randomNumber();
$this->customer->persona = $this->persona;
@ -85,36 +87,38 @@ class TokuTest extends TestCase
$this->venta->method('proyecto')->willReturn($proyecto);
$this->venta->method('propiedad')->willReturn($propiedad);
$this->venta->method('propietario')->willReturn($propietario);
$this->subscription = $this->getMockBuilder(Model\MediosPago\Toku\Subscription::class)
$this->subscription = $this->getMockBuilder(Model\Venta\MediosPago\Toku\Subscription::class)
->disableOriginalConstructor()->getMock();
$this->subscription->id = $faker->randomNumber();
$this->subscription->venta = $this->venta;
$this->subscription->toku_id = $faker->ean13();
$pago = $this->getMockBuilder(Model\Venta\Pago::class)
$this->pago = $this->getMockBuilder(Model\Venta\Pago::class)
->disableOriginalConstructor()->getMock();
$pago->fecha = $faker->dateTime();
$pago->valor = $faker->randomNumber(6);
$pago->method('valor')->willReturn($faker->randomFloat(3, 10, 500));
$this->pago->fecha = $faker->dateTime();
$this->pago->valor = $faker->randomNumber(6);
$this->pago->method('valor')->willReturn($faker->randomFloat(3, 10, 500));
$this->cuota = $this->getMockBuilder(Model\Venta\Cuota::class)
->disableOriginalConstructor()->getMock();
$this->cuota->id = $faker->randomNumber();
$this->cuota->numero = $faker->randomNumber(2);
$this->cuota->pago = $pago;
$this->cuota->pago = $this->pago;
$pie->method('cuotas')->willReturn([$this->cuota]);
$this->invoice = $this->getMockBuilder(Model\MediosPago\Toku\Invoice::class)
$this->invoice = $this->getMockBuilder(Model\Venta\MediosPago\Toku\Invoice::class)
->disableOriginalConstructor()->getMock();
$this->invoice->id = $faker->randomNumber();
$this->invoice->cuota = $this->cuota;
$this->invoice->toku_id = $faker->ean13();
$this->customerService = $this->getMockBuilder(Service\MediosPago\Toku\Customer::class)
->disableOriginalConstructor()->getMock();
$this->customerService->method('getById')->willReturn([
$customerArray = [
'id' => $this->customer->id,
'rut' => $this->customer->rut(),
'toku_id' => $this->customer->toku_id
]);
];
$this->customerService = $this->getMockBuilder(Service\Venta\MediosPago\Toku\Customer::class)
->disableOriginalConstructor()->getMock();
$this->customerService->method('getById')->willReturn($customerArray);
$this->customerService->method('getByExternalId')->willReturn($customerArray);
$this->customerService->method('get')->willReturn([
'id' => $this->customer->toku_id,
'goverment_id' => $this->customer->rut(),
@ -138,7 +142,7 @@ class TokuTest extends TestCase
$this->customerService->method('edit')->willReturn(true);
$this->customerService->method('delete');
$this->subscriptionService = $this->getMockBuilder(Service\MediosPago\Toku\Subscription::class)
$this->subscriptionService = $this->getMockBuilder(Service\Venta\MediosPago\Toku\Subscription::class)
->disableOriginalConstructor()->getMock();
$this->subscriptionService->method('getById')->willReturn([
'id' => $this->subscription->id,
@ -163,22 +167,24 @@ class TokuTest extends TestCase
$this->subscriptionService->method('edit')->willReturn(true);
$this->subscriptionService->method('delete');
$this->invoiceService = $this->getMockBuilder(Service\MediosPago\Toku\Invoice::class)
->disableOriginalConstructor()->getMock();
$this->invoiceService->method('getById')->willReturn([
$invoiceArray = [
'id' => $this->invoice->id,
'cuota_id' => $this->cuota->id,
'toku_id' => $this->invoice->toku_id,
]);
];
$this->invoiceService = $this->getMockBuilder(Service\Venta\MediosPago\Toku\Invoice::class)
->disableOriginalConstructor()->getMock();
$this->invoiceService->method('getById')->willReturn($invoiceArray);
$this->invoiceService->method('getByExternalId')->willReturn($invoiceArray);
$this->invoiceService->method('get')->willReturn([
'id' => $this->invoice->toku_id,
'customer' => $this->customer->toku_id,
'product_id' => $this->venta->id,
'subscription' => $this->subscription->toku_id,
'is_paid' => false,
'due_date' => $pago->fecha->format('Y-m-d'),
'due_date' => $this->pago->fecha->format('Y-m-d'),
'is_void' => false,
'amount' => $pago->valor(),
'amount' => $this->pago->valor(),
'link_payment' => '',
'metadata' => [
'numero' => $this->cuota->numero,
@ -195,12 +201,13 @@ class TokuTest extends TestCase
$this->invoiceService->method('add')->willReturn(true);
$this->invoiceService->method('edit')->willReturn(true);
$this->invoiceService->method('delete');
$this->invoiceService->method('update')->willReturn(true);
}
public function testSendCustomer(): void
{
$service = new Service\MediosPago\Toku($this->logger);
$service->register(Service\MediosPago\Toku::CUSTOMER, $this->customerService);
$service = new Service\Venta\MediosPago\Toku($this->logger);
$service->register(Service\Venta\MediosPago\Toku::CUSTOMER, $this->customerService);
$expected = [
'id' => $this->customer->id,
@ -212,9 +219,9 @@ class TokuTest extends TestCase
}
public function testSendSubscription(): void
{
$service = new Service\MediosPago\Toku($this->logger);
$service->register(Service\MediosPago\Toku::CUSTOMER, $this->customerService);
$service->register(Service\MediosPago\Toku::SUBSCRIPTION, $this->subscriptionService);
$service = new Service\Venta\MediosPago\Toku($this->logger);
$service->register(Service\Venta\MediosPago\Toku::CUSTOMER, $this->customerService);
$service->register(Service\Venta\MediosPago\Toku::SUBSCRIPTION, $this->subscriptionService);
$expected = [
'id' => $this->subscription->id,
@ -226,10 +233,10 @@ class TokuTest extends TestCase
}
public function testSendInvoice(): void
{
$service = new Service\MediosPago\Toku($this->logger);
$service->register(Service\MediosPago\Toku::CUSTOMER, $this->customerService);
$service->register(Service\MediosPago\Toku::SUBSCRIPTION, $this->subscriptionService);
$service->register(Service\MediosPago\Toku::INVOICE, $this->invoiceService);
$service = new Service\Venta\MediosPago\Toku($this->logger);
$service->register(Service\Venta\MediosPago\Toku::CUSTOMER, $this->customerService);
$service->register(Service\Venta\MediosPago\Toku::SUBSCRIPTION, $this->subscriptionService);
$service->register(Service\Venta\MediosPago\Toku::INVOICE, $this->invoiceService);
$expected = [
[
@ -241,4 +248,92 @@ class TokuTest extends TestCase
$this->assertEquals($expected, $service->sendCuotas($this->venta));
}
public function testUpdatePago(): void
{
$service = new Service\Venta\MediosPago\Toku($this->logger);
$service->register(Service\Venta\MediosPago\Toku::CUSTOMER, $this->customerService);
$service->register(Service\Venta\MediosPago\Toku::INVOICE, $this->invoiceService);
$faker = Faker\Factory::create();
$request = [
'id' => $faker->ean13(),
'event_type' => 'payment_intent.succeeded',
'payment_intent' => [
'id' => $faker->ean13(),
'invoice' => $this->invoice->toku_id,
'customer' => $this->customer->toku_id,
'id_account' => $faker->ean13(),
'gateway' => 'khipu_transfer',
'amount' => $this->pago->valor,
'status' => 'AUTHORIZED',
'payment_method' => $faker->ean13(),
'transaction_date' => $faker->dateTime(),
'card_detail' => null,
'buy_order' => $faker->ean8(),
'child_buy_order' => null,
'authorization_code' => null,
'payment_type_code' => null,
'response_code' => null,
'toku_response_code' => null,
'installments_number' => null,
'mc_order_id' => null,
]
];
$this->assertTrue($service->updatePago($request['payment_intent']));
}
public function testUpdatePagoException(): void
{
$emptyResponse = $this->getMockBuilder(InvalidResult::class)
->setConstructorArgs(['message' => "No existe Customer para toku_id {$this->customer->toku_id}"])->getMock();
$customerService = clone($this->customerService);
$customerService->method('getByExternalId')->willThrowException($emptyResponse);
$service = new Service\Venta\MediosPago\Toku($this->logger);
$service->register(Service\Venta\MediosPago\Toku::CUSTOMER, $customerService);
$service->register(Service\Venta\MediosPago\Toku::INVOICE, $this->invoiceService);
$faker = Faker\Factory::create();
$request = [
'id' => $faker->ean13(),
'event_type' => 'payment_intent.succeeded',
'payment_intent' => [
'id' => $faker->ean13(),
'invoice' => $this->invoice->toku_id,
'customer' => $this->customer->toku_id,
'id_account' => $faker->ean13(),
'gateway' => 'khipu_transfer',
'amount' => $this->pago->valor,
'status' => 'AUTHORIZED',
'payment_method' => $faker->ean13(),
'transaction_date' => $faker->dateTime(),
'card_detail' => null,
'buy_order' => $faker->ean8(),
'child_buy_order' => null,
'authorization_code' => null,
'payment_type_code' => null,
'response_code' => null,
'toku_response_code' => null,
'installments_number' => null,
'mc_order_id' => null,
]
];
$this->expectException(InvalidResult::class);
$service->updatePago($request['payment_intent']);
$emptyResponse = $this->getMockBuilder(InvalidResult::class)
->setConstructorArgs(['message' => "No existe Invoice para toku_id {$this->invoice->toku_id}"])->getMock();
$invoiceService = clone($this->invoiceService);
$invoiceService->method('getByExternalId')->willThrowException($emptyResponse);
$service = new Service\Venta\MediosPago\Toku($this->logger);
$service->register(Service\Venta\MediosPago\Toku::CUSTOMER, $this->customerService);
$service->register(Service\Venta\MediosPago\Toku::INVOICE, $invoiceService);
$this->expectException(InvalidResult::class);
$service->updatePago($request['payment_intent']);
}
}

View File

@ -2,6 +2,7 @@
"name": "incoviba/cli",
"type": "project",
"require": {
"dragonmantank/cron-expression": "^3.4",
"guzzlehttp/guzzle": "^7.8",
"monolog/monolog": "^3.5",
"php-di/php-di": "^7.0",

View File

@ -7,3 +7,4 @@
0 2 * * * /code/bin/incoviba money:uf >> /logs/commands 2>&1
0 2 * * * /code/bin/incoviba money:uf:update >> /logs/commands 2>&1
0 2 1 * * /code/bin/incoviba money:ipc >> /logs/commands 2>&1
*/5 * * * * /code/bin/incoviba queue >> /logs/commands 2>&1

6
cli/entrypoint Normal file
View File

@ -0,0 +1,6 @@
#/usr/bin/bash
printenv >> /etc/environment
#cron -f -L 11
/code/bin/incoviba loop

View File

@ -0,0 +1,2 @@
<?php
$app->add($app->getContainer()->get(Incoviba\Command\BaseLoop::class));

View File

@ -0,0 +1,2 @@
<?php
$app->add($app->getContainer()->get(Incoviba\Command\Queue::class));

View File

@ -13,6 +13,8 @@ return [
'ventas:cuotas:hoy' => Incoviba\Command\Ventas\Cuotas\Hoy::class,
'ventas:cuotas:pendientes' => Incoviba\Command\Ventas\Cuotas\Pendientes::class,
'ventas:cuotas:vencer' => Incoviba\Command\Ventas\Cuotas\PorVencer::class,
'queue' => Incoviba\Command\Queue::class,
'loop' => Incoviba\Command\BaseLoop::class
];
}
];

View File

@ -0,0 +1,63 @@
<?php
namespace Incoviba\Command;
use Throwable;
use DateTimeInterface;
use DateTimeImmutable;
use Psr\Log\LoggerInterface;
use Symfony\Component\Console;
use Incoviba\Service\Schedule;
#[Console\Attribute\AsCommand(
name: 'loop',
description: 'Run base loop',
)]
class BaseLoop extends Console\Command\Command
{
public function __construct(protected LoggerInterface $logger, protected Schedule $scheduleService, ?string $name = null)
{
parent::__construct($name);
}
public function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output): int
{
$output->writeln("Running Loop...");
// wait for next minute
$now = new DateTimeImmutable();
$nextMinute = new DateTimeImmutable($now->format('Y-m-d H:i:00'));
$nextMinute->add(new \DateInterval('PT1M'));
$diff = $nextMinute->getTimestamp() - $now->getTimestamp();
if ($diff > 0) {
$output->writeln("Waiting {$diff} seconds...");
sleep($diff);
}
$output->writeln('Starting loop...');
while (true) {
$commands = $this->scheduleService->run();
foreach ($commands as $command) {
$this->runCommand($input, $output, $command);
}
}
return self::SUCCESS;
}
protected function runCommand(Console\Input\InputInterface $input, Console\Output\OutputInterface $output, string $commandName): int
{
try {
$command = $this->getApplication()->find($commandName);
} catch (Console\Exception\CommandNotFoundException $exception) {
$this->logger->warning($exception);
}
$cmd = new Console\Input\ArrayInput([
'command' => $commandName
]);
try {
return $this->getApplication()->doRun($cmd, $output);
} catch (Throwable $exception) {
$this->logger->warning($exception);
return self::FAILURE;
}
}
}

26
cli/src/Command/Queue.php Normal file
View File

@ -0,0 +1,26 @@
<?php
namespace Incoviba\Command;
use Symfony\Component\Console;
use Incoviba\Common\Alias\Command;
#[Console\Attribute\AsCommand(
name: 'queue',
description: 'Run queue'
)]
class Queue extends Command
{
public function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output): int
{
$this->logger->debug("Running {$this->getName()}");
$io = new Console\Style\SymfonyStyle($input, $output);
$io->title("Running Queue...");
$uri = '/api/queue/run';
$output->writeln("GET {$uri}");
$response = $this->client->get($uri);
$output->writeln("Response Code: {$response->getStatusCode()}");
return Console\Command\Command::SUCCESS;
}
}

View File

@ -0,0 +1,60 @@
<?php
namespace Incoviba\Service;
use Cron\CronExpression;
use DateTimeInterface;
use DateTimeImmutable;
use Psr\Log\LoggerInterface;
class Schedule
{
public function __construct(protected LoggerInterface $logger) {}
protected string $filename = '/var/spool/cron/crontabs/root';
public function run(): array
{
$now = new DateTimeImmutable();
$schedule = $this->getCommandList();
$commands = [];
foreach ($schedule as $line) {
$line = trim($line);
if ($line === '') {
continue;
}
$data = $this->parseCommandLine($line);
if ($this->processSchedule($now, $data)) {
$commands[] = $data['command'];
}
}
return $commands;
}
protected function getCommandList(): array
{
if (!file_exists($this->filename)) {
return [];
}
return explode("\n", file_get_contents($this->filename));
}
protected function parseCommandLine(string $line): array
{
$regex = '/^(?<minutes>(\d{1,2}|\*|\*\/\d{1,2})?) (?<hours>(\d{1,2}|\*|\*\/\d{1,2})?) (?<day_month>(\d{1,2}|\*|\*\/\d{1,2})?) (?<month>(\d{1,2}|\*|\*\/\d{1,2})?) (?<day_week>(\d{1,2}|\*|\*\/\d{1,2})?) (?<command>.*)$/';
preg_match_all($regex, $line, $matches);
return [
'minutes' => $matches['minutes'][0],
'hours' => $matches['hours'][0],
'day_month' => $matches['day_month'][0],
'month' => $matches['month'][0],
'day_week' => $matches['day_week'][0],
'command' => trim(str_replace(['/code/bin/incoviba', '>> /logs/commands 2>&1'], '', $matches['command'][0])),
];
}
protected function processSchedule(DateTimeInterface $now, array $schedule): bool
{
$cronLine = "{$schedule['minutes']} {$schedule['hours']} {$schedule['day_month']} {$schedule['month']} {$schedule['day_week']}";
$cron = new CronExpression($cronLine);
return $cron->isDue($now);
}
}

View File

@ -84,6 +84,7 @@ services:
volumes:
- ${CLI_PATH:-.}:/code
- ./logs/cli:/logs
- ${CLI_PATH:-.}/crontab:/var/spool/cron/crontabs/root
volumes:
dbdata: {}