feature/cierres (#25)

Varios cambios

Co-authored-by: Juan Pablo Vial <jpvialb@incoviba.cl>
Reviewed-on: #25
This commit is contained in:
2025-07-22 13:18:00 +00:00
parent ba57cad514
commit 307f2ac7d7
418 changed files with 20045 additions and 984 deletions

View File

@ -58,6 +58,12 @@ class Credito extends Ideal\Repository
->where('pago = ?');
return $this->fetchOne($query, [$pago_id]);
}
/**
* @param int $venta_id
* @return Model\Venta\Credito
* @throws Implement\Exception\EmptyResult
*/
public function fetchByVenta(int $venta_id): Model\Venta\Credito
{
$query = $this->connection->getQueryBuilder()

View File

@ -0,0 +1,112 @@
<?php
namespace Incoviba\Repository\Venta\MediosPago\Toku;
use DateTimeImmutable;
use PDO;
use PDOException;
use Incoviba\Common\Define;
use Incoviba\Common\Ideal;
use Incoviba\Common\Implement;
use Incoviba\Model;
use Incoviba\Service;
class Customer extends Ideal\Repository
{
public function __construct(Define\Connection $connection, protected Service\Persona $personaService)
{
parent::__construct($connection);
}
public function getTable(): string
{
return 'toku_customers';
}
public function create(?array $data = null): Model\Venta\MediosPago\Toku\Customer
{
$map = (new Implement\Repository\MapperParser(['toku_id']))
->register('rut', (new Implement\Repository\Mapper())
->setProperty('persona')
->setFunction(function($data) {
$rut = (int) substr($data['rut'], 0, -1);
return $this->personaService->getById($rut);
})
);
return $this->parseData(new Model\Venta\MediosPago\Toku\Customer(), $data, $map);
}
public function save(Define\Model $model): Model\Venta\MediosPago\Toku\Customer
{
$model->id = $this->saveNew(
['rut', 'toku_id', 'created_at'],
[implode('', [$model->persona->rut, $model->persona->digito]), $model->toku_id, (new DateTimeImmutable())->format('Y-m-d H:i:s')]
);
return $model;
}
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')]));
}
/**
* @param string $rut
* @return Model\Venta\MediosPago\Toku\Customer
* @throws Implement\Exception\EmptyResult
*/
public function fetchByRut(string $rut): Model\Venta\MediosPago\Toku\Customer
{
if (str_contains($rut, '-')) {
$rut = str_replace('-', '', $rut);
}
if (str_contains($rut, '.')) {
$rut = str_replace('.', '', $rut);
}
$rut = strtoupper($rut);
$query = $this->connection->getQueryBuilder()
->select()
->from($this->getTable())
->where('rut = :rut');
return $this->fetchOne($query, compact('rut'));
}
/**
* @param string $toku_id
* @return 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'));
}
/**
* @return array
* @throws Implement\Exception\EmptyResult
*/
public function fetchAllTokuIds(): array
{
$query = $this->connection->getQueryBuilder()
->select('toku_id')
->from($this->getTable());
try {
$statement = $this->connection->query($query);
} catch (PDOException $exception) {
throw new Implement\Exception\EmptyResult($query, $exception);
}
if ($statement->rowCount() === 0) {
throw new Implement\Exception\EmptyResult($query);
}
return $statement->fetchAll(PDO::FETCH_COLUMN);
}
public function removeByTokuId(string $toku_id): void
{
$query = $this->connection->getQueryBuilder()
->delete()
->from($this->getTable())
->where('toku_id = :toku_id');
$this->connection->execute($query, compact('toku_id'));
}
}

View File

@ -0,0 +1,108 @@
<?php
namespace Incoviba\Repository\Venta\MediosPago\Toku;
use DateTimeImmutable;
use PDO;
use PDOException;
use Incoviba\Common\Define;
use Incoviba\Common\Ideal;
use Incoviba\Common\Implement;
use Incoviba\Model;
use Incoviba\Repository;
class Invoice extends Ideal\Repository
{
public function __construct(Define\Connection $connection, protected Repository\Venta\Cuota $cuotaRepository)
{
parent::__construct($connection);
}
public function getTable(): string
{
return 'toku_invoices';
}
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())
->setProperty('cuota')
->setFunction(function($data) {
return $this->cuotaRepository->fetchById($data['cuota_id']);
}));
return $this->parseData(new Model\Venta\MediosPago\Toku\Invoice(), $data, $map);
}
public function save(Define\Model $model): Model\Venta\MediosPago\Toku\Invoice
{
$model->id = $this->saveNew(
['cuota_id', 'toku_id', 'created_at'],
[$model->cuota->id, $model->toku_id, (new DateTimeImmutable())->format('Y-m-d H:i:s')]
);
return $model;
}
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')]));
}
/**
* @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()
->from($this->getTable())
->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'));
}
/**
* @return array
* @throws Implement\Exception\EmptyResult
*/
public function fetchAllTokuIds(): array
{
$query = $this->connection->getQueryBuilder()
->select('toku_id')
->from($this->getTable());
try {
$statement = $this->connection->query($query);
} catch (PDOException $exception) {
throw new Implement\Exception\EmptyResult($query, $exception);
}
if ($statement->rowCount() === 0) {
throw new Implement\Exception\EmptyResult($query);
}
return $statement->fetchAll(PDO::FETCH_COLUMN);
}
/**
* @param string $toku_id
* @return void
* @throws PDOException
*/
public function removeByTokuId(string $toku_id): void
{
$query = $this->connection->getQueryBuilder()
->delete()
->from($this->getTable())
->where('toku_id = :toku_id');
$this->connection->execute($query, compact('toku_id'));
}
}

View File

@ -0,0 +1,124 @@
<?php
namespace Incoviba\Repository\Venta\MediosPago\Toku;
use DateTimeImmutable;
use PDO;
use PDOException;
use Incoviba\Common\Define;
use Incoviba\Common\Ideal;
use Incoviba\Common\Implement;
use Incoviba\Model;
use Incoviba\Repository;
class Subscription extends Ideal\Repository
{
public function __construct(Define\Connection $connection, protected Repository\Venta $ventaRepository)
{
parent::__construct($connection);
}
public function getTable(): string
{
return 'toku_subscriptions';
}
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())
->setProperty('venta')
->setFunction(function($data) {
return $this->ventaRepository->fetchById($data['venta_id']);
}));
return $this->parseData(new Model\Venta\MediosPago\Toku\Subscription(), $data, $map);
}
public function save(Define\Model $model): Model\Venta\MediosPago\Toku\Subscription
{
$model->id = $this->saveNew(
['venta_id', 'toku_id', 'created_at'],
[$model->venta->id, $model->toku_id, (new DateTimeImmutable())->format('Y-m-d H:i:s')]
);
return $model;
}
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')]));
}
/**
* @param int $venta_id
* @return Model\Venta\MediosPago\Toku\Subscription
* @throws Implement\Exception\EmptyResult
*/
public function fetchByVenta(int $venta_id): Model\Venta\MediosPago\Toku\Subscription
{
$query = $this->connection->getQueryBuilder()
->select()
->from($this->getTable())
->where('venta_id = :venta_id');
return $this->fetchOne($query, compact('venta_id'));
}
/**
* @param string $toku_id
* @return Model\Venta\MediosPago\Toku\Subscription
* @throws Implement\Exception\EmptyResult
*/
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'));
}
/**
* @param array $ventas_ids
* @return array
* @throws Implement\Exception\EmptyResult
*/
public function fetchByVentas(array $ventas_ids): array
{
$idsQuery = implode(', ', array_fill(0, count($ventas_ids), '?'));
$query = $this->connection->getQueryBuilder()
->select()
->from($this->getTable())
->where("venta_id IN ({$idsQuery})");
return $this->fetchMany($query, $ventas_ids);
}
/**
* @return array
* @throws Implement\Exception\EmptyResult
*/
public function fetchAllTokuIds(): array
{
$query = $this->connection->getQueryBuilder()
->select('toku_id')
->from($this->getTable());
try {
$statement = $this->connection->query($query);
} catch (PDOException $exception) {
throw new Implement\Exception\EmptyResult($query, $exception);
}
if ($statement->rowCount() === 0) {
throw new Implement\Exception\EmptyResult($query);
}
return $statement->fetchAll(PDO::FETCH_COLUMN);
}
/**
* @param string $toku_id
* @return void
* @throws PDOException
*/
public function removeByTokuId(string $toku_id): void
{
$query = $this->connection->getQueryBuilder()
->delete()
->from($this->getTable())
->where('toku_id = :toku_id');
$this->connection->execute($query, compact('toku_id'));
}
}

View File

@ -114,6 +114,12 @@ WHERE venta_id = ?";
->where('valor = ? OR ROUND(valor/uf, 3) = ?');
return $this->fetchMany($query, [$value, $value]);
}
/**
* @param int $venta_id
* @return Model\Venta\Pago
* @throws Implement\Exception\EmptyResult
*/
public function fetchDevolucionByVenta(int $venta_id): Model\Venta\Pago
{
$query = $this->connection->getQueryBuilder()

View File

@ -83,6 +83,12 @@ class Pie extends Ideal\Repository
->where('reajuste = ?');
return $this->fetchOne($query, [$reajuste_id]);
}
/**
* @param int $venta_id
* @return Model\Venta\Pie
* @throws Implement\Exception\EmptyResult
*/
public function fetchByVenta(int $venta_id): Model\Venta\Pie
{
$query = $this->connection->getQueryBuilder()

View File

@ -1,6 +1,8 @@
<?php
namespace Incoviba\Repository\Venta;
use PDO;
use PDOException;
use Incoviba\Common\Ideal;
use Incoviba\Common\Define;
use Incoviba\Common\Implement;
@ -51,15 +53,16 @@ class Precio extends Ideal\Repository
*/
public function fetchByProyecto(int $proyecto_id): array
{
$query = "SELECT a.*
FROM `{$this->getTable()}` a
JOIN (SELECT e1.* FROM `estado_precio` e1 JOIN (SELECT MAX(`id`) AS 'id', `precio` FROM `estado_precio` GROUP BY `precio`) e0 ON e0.`id` = e1.`id`) ep ON ep.`precio` = a.`id`
JOIN `tipo_estado_precio` tep ON tep.`id` = ep.`estado`
JOIN `unidad` ON `unidad`.`id` = a.`unidad`
JOIN `proyecto_tipo_unidad` ptu ON ptu.`id` = `unidad`.`pt`
JOIN `tipo_unidad` tu ON tu.`id` = ptu.`tipo`
WHERE ptu.`proyecto` = ? AND tep.`descripcion` = 'vigente'
ORDER BY tu.`orden`, ptu.`nombre`, `unidad`.`subtipo`, LPAD(`unidad`.`descripcion`, 4, '0')";
$query = $this->connection->getQueryBuilder()
->select('a.*')
->from("{$this->getTable()} a")
->joined($this->joinEstado())
->joined('INNER JOIN `tipo_estado_precio` tep ON tep.`id` = ep.`estado`')
->joined('INNER JOIN `unidad` ON `unidad`.`id` = a.`unidad`')
->joined('INNER JOIN `proyecto_tipo_unidad` ptu ON ptu.`id` = `unidad`.`pt`')
->joined('INNER JOIN `tipo_unidad` tu ON tu.`id` = ptu.`tipo`')
->where('ptu.`proyecto` = ? AND tep.`descripcion` = "vigente"')
->order('tu.`orden`, ptu.`nombre`, `unidad`.`subtipo`, LPAD(`unidad`.`descripcion`, 4, "0")');
return $this->fetchMany($query, [$proyecto_id]);
}
@ -70,11 +73,12 @@ ORDER BY tu.`orden`, ptu.`nombre`, `unidad`.`subtipo`, LPAD(`unidad`.`descripcio
*/
public function fetchByUnidad(int $unidad_id): array
{
$query = "SELECT a.*
FROM `{$this->getTable()}` a
JOIN (SELECT e1.* FROM `estado_precio` e1 JOIN (SELECT MAX(`id`) AS 'id', `precio` FROM `estado_precio` GROUP BY `precio`) e0 ON e0.`id` = e1.`id`) ep ON ep.`precio` = a.`id`
JOIN `tipo_estado_precio` tep ON tep.`id` = ep.`estado`
WHERE `unidad` = ?";
$query = $this->connection->getQueryBuilder()
->select('a.*')
->from("{$this->getTable()} a")
->joined($this->joinEstado())
->joined('INNER JOIN tipo_estado_precio tep ON tep.`id` = ep.`estado`')
->where('`unidad` = ?');
return $this->fetchMany($query, [$unidad_id]);
}
@ -85,14 +89,45 @@ WHERE `unidad` = ?";
*/
public function fetchVigenteByUnidad(int $unidad_id): Define\Model
{
$query = "SELECT a.*
FROM `{$this->getTable()}` a
JOIN (SELECT e1.* FROM `estado_precio` e1 JOIN (SELECT MAX(`id`) AS 'id', `precio` FROM `estado_precio` GROUP BY `precio`) e0 ON e0.`id` = e1.`id`) ep ON ep.`precio` = a.`id`
JOIN `tipo_estado_precio` tep ON tep.`id` = ep.`estado`
WHERE `unidad` = ? AND tep.`descripcion` = 'vigente'";
$query = $this->connection->getQueryBuilder()
->select('a.*')
->from("{$this->getTable()} a")
->joined($this->joinEstado())
->joined('INNER JOIN tipo_estado_precio tep ON tep.`id` = ep.`estado`')
->where('`unidad` = ? AND tep.`descripcion` = "vigente"');
return $this->fetchOne($query, [$unidad_id]);
}
/**
* @param array $unidad_ids
* @return array
* @throws Implement\Exception\EmptyResult
*/
public function fetchVigentesByUnidades(array $unidad_ids): array
{
$interrogations = implode(',', array_fill(0, count($unidad_ids), '?'));
$query = $this->connection->getQueryBuilder()
->select('a.*, unidad')
->from("{$this->getTable()} a")
->joined($this->joinEstado())
->joined('INNER JOIN tipo_estado_precio tep ON tep.`id` = ep.`estado`')
->where("`unidad` IN ({$interrogations}) AND tep.`descripcion` = \"vigente\"");
try {
$results = $this->connection->execute($query, $unidad_ids)->fetchAll(PDO::FETCH_ASSOC);
if (empty($results)) {
throw new Implement\Exception\EmptyResult($query);
}
return array_map(function($result) {
return [
'id' => $result['unidad'],
'precio' => $this->load($result)
];
}, $results);
} catch (PDOException $exception) {
throw new Implement\Exception\EmptyResult($query, $exception);
}
}
/**
* @param int $unidad_id
* @param string $date_time
@ -101,11 +136,25 @@ WHERE `unidad` = ? AND tep.`descripcion` = 'vigente'";
*/
public function fetchByUnidadAndDate(int $unidad_id, string $date_time): Define\Model
{
$query = "SELECT a.*
FROM `{$this->getTable()}` a
JOIN (SELECT e1.* FROM `estado_precio` e1 JOIN (SELECT MAX(`id`) AS 'id', `precio` FROM `estado_precio` GROUP BY `precio`) e0 ON e0.`id` = e1.`id`) ep ON ep.`precio` = a.`id`
JOIN `tipo_estado_precio` tep ON tep.`id` = ep.`estado`
WHERE `unidad` = ? AND ep.`fecha` <= ? AND tep.`descripcion` = 'vigente'";
$query = $this->connection->getQueryBuilder()
->select('a.*')
->from("{$this->getTable()} a")
->joined($this->joinEstado())
->joined('INNER JOIN `tipo_estado_precio` tep ON tep.`id` = ep.`estado`')
->where('`unidad` = ? AND ep.`fecha` <= ? AND tep.`descripcion` = "vigente"');
return $this->fetchOne($query, [$unidad_id, $date_time]);
}
protected function joinEstado(): string
{
$subSubQuery = $this->connection->getQueryBuilder()
->select('MAX(id) AS id, precio')
->from('estado_precio')
->group('precio');
$subQuery = $this->connection->getQueryBuilder()
->select('e1.*')
->from('estado_precio e1')
->joined("INNER JOIN ($subSubQuery) e0 ON e0.id = e1.id");
return "JOIN ($subQuery) ep ON ep.precio = a.id";
}
}

View File

@ -0,0 +1,431 @@
<?php
namespace Incoviba\Repository\Venta;
use PDO;
use PDOException;
use Incoviba\Common;
use Incoviba\Model;
use Incoviba\Repository\Proyecto\Broker;
class Promotion extends Common\Ideal\Repository
{
public function __construct(Common\Define\Connection $connection, protected Broker\Contract $contractRepository, protected Precio $precioRepository)
{
parent::__construct($connection);
}
public function getTable(): string
{
return 'promotions';
}
public function create(?array $data = null): Model\Venta\Promotion
{
$map = (new Common\Implement\Repository\MapperParser(['description', 'amount']))
->register('type', (new Common\Implement\Repository\Mapper())
->setFunction(function($data) {
return Model\Venta\Promotion\Type::from($data['type']);
}))
->register('state', (new Common\Implement\Repository\Mapper())
->setFunction(function($data) {
return Model\Venta\Promotion\State::from($data['state']);
})
->setDefault(Model\Venta\Promotion\State::ACTIVE))
->register('start_date', new Common\Implement\Repository\Mapper\DateTime('start_date', 'startDate'))
->register('end_date', (new Common\Implement\Repository\Mapper\DateTime('end_date', 'endDate'))
->setDefault(null))
->register('valid_until', (new Common\Implement\Repository\Mapper\DateTime('valid_until', 'validUntil'))
->setDefault(null));
return $this->parseData(new Model\Venta\Promotion(), $data, $map);
}
public function save(Common\Define\Model $model): Model\Venta\Promotion
{
$model->id = $this->saveNew(
['description', 'amount', 'type', 'start_date', 'end_date', 'valid_until'],
[$model->description, $model->amount, $model->type->value, $model->startDate->format('Y-m-d'),
$model->endDate?->format('Y-m-d'), $model->validUntil?->format('Y-m-d')]
);
return $model;
}
public function edit(Common\Define\Model $model, array $new_data): Model\Venta\Promotion
{
return $this->update($model, ['description', 'amount', 'type', 'start_date', 'end_date', 'valid_until'], $new_data);
}
public function filterData(array $data): array
{
$filteredData = array_intersect_key($data, array_flip(['description', 'amount', 'type', 'start_date', 'end_date', 'valid_until']));
if (!isset($filteredData['amount']) and isset($data['value'])) {
$filteredData['amount'] = $data['value'];
}
$filteredData['type'] = (int) $filteredData['type'];
if ($filteredData['amount'] > 1 and $filteredData['type'] === Model\Venta\Promotion\Type::VARIABLE->value) {
$filteredData['amount'] = $filteredData['amount'] / 100;
}
return $filteredData;
}
/**
* @param int $contract_id
* @return array
* @throws Common\Implement\Exception\EmptyResult
*/
public function fetchByContract(int $contract_id): array
{
$query = $this->connection->getQueryBuilder()
->select('DISTINCT a.*')
->from("{$this->getTable()} a")
->joined('LEFT OUTER JOIN promotion_brokers pb ON pb.promotion_id = a.id')
->joined('LEFT OUTER JOIN broker_contracts bc ON bc.broker_rut = pb.broker_rut')
->joined('LEFT OUTER JOIN promotion_projects pp ON pp.promotion_id = a.id')
->joined('LEFT OUTER JOIN broker_contracts bc2 ON bc2.project_id = pp.project_id')
->joined('LEFT OUTER JOIN promotion_unit_types put ON put.promotion_id = a.id')
->joined('LEFT OUTER JOIN broker_contracts bc3 ON bc3.project_id = put.project_id')
->joined('LEFT OUTER JOIN promotion_unit_lines pul ON pul.promotion_id = a.id')
->joined('LEFT OUTER JOIN proyecto_tipo_unidad ptu ON ptu.id = pul.unit_line_id')
->joined('LEFT OUTER JOIN broker_contracts bc4 ON bc4.project_id = ptu.proyecto')
->joined('LEFT OUTER JOIN promotion_units pu ON pu.promotion_id = a.id')
->joined('LEFT OUTER JOIN unidad ON unidad.id = pu.unit_id')
->joined('LEFT OUTER JOIN proyecto_tipo_unidad ptu2 ON ptu2.id = unidad.pt')
->joined('LEFT OUTER JOIN broker_contracts bc5 ON bc5.project_id = ptu2.proyecto')
->where('bc.id = :contract_id OR bc2.id = :contract_id OR bc3.id = :contract_id OR bc4.id = :contract_id OR bc5.id = :contract_id')
->group('a.id');
return $this->fetchMany($query, ['contract_id' => $contract_id]);
}
/**
* @param int $contract_id
* @return array
* @throws Common\Implement\Exception\EmptyResult
*/
public function fetchActiveByContract(int $contract_id): array
{
$query = $this->connection->getQueryBuilder()
->select('DISTINCT a.*')
->from("{$this->getTable()} a")
->joined('LEFT OUTER JOIN promotion_broker pb ON pb.promotion_id = a.id')
->joined('LEFT OUTER JOIN broker_contracts bc ON bc.id = pb.contract_id')
->joined('LEFT OUTER JOIN promotion_projects pp ON pp.promotion_id = a.id')
->joined('LEFT OUTER JOIN broker_contracts bc2 ON bc2.project_id = pp.project_id')
->joined('LEFT OUTER JOIN promotion_unit_types put ON put.promotion_id = a.id')
->joined('LEFT OUTER JOIN broker_contracts bc3 ON bc3.project_id = put.project_id')
->joined('LEFT OUTER JOIN promotion_unit_lines pul ON pul.promotion_id = a.id')
->joined('LEFT OUTER JOIN proyecto_tipo_unidad ptu ON ptu.id = pul.unit_line_id')
->joined('LEFT OUTER JOIN broker_contracts bc4 ON bc4.project_id = btu.proyecto')
->joined('LEFT OUTER JOIN promotion_units pu ON pu.promotion_id = a.id')
->joined('LEFT OUTER JOIN unidad ON unidad.id = pu.unit_id')
->joined('LEFT OUTER JOIN proyecto_tipo_unidad ptu2 ON ptu2.id = unidad.pt')
->joined('LEFT OUTER JOIN broker_contracts bc5 ON bc5.project_id = ptu2.proyecto')
->where('(bc.id = :contract_id OR bc2.id = :contract_id OR bc3.id = :contract_id OR bc4.id = :contract_id OR bc5.id = :contract_id) AND a.state = :state')
->group('a.id');
return $this->fetchMany($query, ['contract_id' => $contract_id, 'state' => Model\Venta\Promotion\State::ACTIVE]);
}
/**
* @param int $unit_id
* @return array
* @throws Common\Implement\Exception\EmptyResult
*/
public function fetchByUnit(int $unit_id): array
{
$query = $this->connection->getQueryBuilder()
->select('DISTINCT a.*')
->from("{$this->getTable()} a")
->joined('LEFT OUTER JOIN promotion_units pu ON pu.promotion_id = a.id')
->joined('LEFT OUTER JOIN promotion_projects pp ON pp.promotion_id = a.id')
->joined('LEFT OUTER JOIN proyecto_tipo_unidad ptu1 ON ptu1.proyecto = pp.project_id')
->joined('LEFT OUTER JOIN unidad u1 ON u1.pt = ptu1.id')
->joined('LEFT OUTER JOIN promotion_unit_types put ON put.promotion_id = a.id')
->joined('LEFT OUTER JOIN proyecto_tipo_unidad ptu2 ON ptu2.tipo = put.unit_type_id AND ptu2.proyecto = put.project_id')
->joined('LEFT OUTER JOIN unidad u2 ON u2.pt = ptu2.id')
->joined('LEFT OUTER JOIN promotion_unit_lines pul ON pul.promotion_id = a.id')
->joined('LEFT OUTER JOIN unidad u3 ON u3.pt = pul.unit_line_id')
->where('pu.unit_id = :unit_id OR u1.id = :unit_id OR u2.id = :unit_id OR u3.id = :unit_id')
->group('a.id');
return $this->fetchMany($query, ['unit_id' => $unit_id]);
}
/**
* @param int $unit_id
* @return array
* @throws Common\Implement\Exception\EmptyResult
*/
public function fetchActiveByUnit(int $unit_id): array
{
$query = $this->connection->getQueryBuilder()
->select('DISTINCT a.*')
->from("{$this->getTable()} a")
->joined('LEFT OUTER JOIN promotion_units pu ON pu.promotion_id = a.id')
->joined('LEFT OUTER JOIN promotion_projects pp ON pp.promotion_id = a.id')
->joined('LEFT OUTER JOIN proyecto_tipo_unidad ptu1 ON ptu1.proyecto = pp.project_id')
->joined('LEFT OUTER JOIN unidad u1 ON u1.pt = ptu1.id')
->joined('LEFT OUTER JOIN promotion_unit_types put ON put.promotion_id = a.id')
->joined('LEFT OUTER JOIN proyecto_tipo_unidad ptu2 ON ptu2.tipo = put.unit_type_id AND ptu2.proyecto = put.project_id')
->joined('LEFT OUTER JOIN unidad u2 ON u2.pt = ptu2.id')
->joined('LEFT OUTER JOIN promotion_unit_lines pul ON pul.promotion_id = a.id')
->joined('LEFT OUTER JOIN unidad u3 ON u3.pt = pul.unit_line_id')
->where('(pu.unit_id = :unit_id OR u1.id = :unit_id OR u2.id = :unit_id OR u3.id = :unit_id) AND a.state = :state')
->group('a.id');
return $this->fetchMany($query, ['unit_id' => $unit_id, 'state' => Model\Venta\Promotion\State::ACTIVE]);
}
/**
* @param int $project_id
* @return array
* @throws Common\Implement\Exception\EmptyResult
*/
public function fetchByProject(int $project_id): array
{
$query = $this->connection->getQueryBuilder()
->select('DISTINCT a.*')
->from("{$this->getTable()} a")
->joined('LEFT OUTER JOIN promotion_projects pp ON pp.promotion_id = a.id')
->joined('LEFT OUTER JOIN promotion_unit_types put ON put.promotion_id = a.id')
->joined('LEFT OUTER JOIN promotion_unit_lines pul ON pul.promotion_id = a.id')
->joined('LEFT OUTER JOIN proyecto_tipo_unidad ptu ON ptu.id = pul.unit_line_id')
->joined('LEFT OUTER JOIN promotion_units pu ON pu.promotion_id = a.id')
->joined('LEFT OUTER JOIN unidad ON unidad.id = pu.unit_id')
->joined('LEFT OUTER JOIN proyecto_tipo_unidad ptu1 ON ptu.id = unidad.pt')
->where('pp.project_id = :project_id OR put.project_id = :project_id OR ptu.proyecto = :project_id OR ptu1.proyecto = :project_id')
->group('a.id');
return $this->fetchMany($query, ['project_id' => $project_id]);
}
/**
* @param int $project_id
* @return array
* @throws Common\Implement\Exception\EmptyResult
*/
public function fetchActiveByProject(int $project_id): array
{
$query = $this->connection->getQueryBuilder()
->select('DISTINCT a.*')
->from("{$this->getTable()} a")
->joined('LEFT OUTER JOIN promotion_projects pp ON pp.promotion_id = a.id')
->joined('LEFT OUTER JOIN promotion_unit_types put ON put.promotion_id = a.id')
->joined('LEFT OUTER JOIN promotion_unit_lines pul ON pul.promotion_id = a.id')
->joined('LEFT OUTER JOIN proyecto_tipo_unidad ptu ON ptu.id = pul.unit_line_id')
->joined('LEFT OUTER JOIN promotion_units pu ON pu.promotion_id = a.id')
->joined('LEFT OUTER JOIN unidad ON unidad.id = pu.unit_id')
->joined('LEFT OUTER JOIN proyecto_tipo_unidad ptu1 ON ptu.id = unidad.pt')
->where('(pp.project_id = :project_id OR put.project_id = :project_id OR ptu.proyecto = :project_id OR ptu1.proyecto = :project_id) AND a.state = :state')
->group('a.id');
return $this->fetchMany($query, ['project_id' => $project_id, 'state' => Model\Venta\Promotion\State::ACTIVE]);
}
/**
* @param int $contract_id
* @param int $unit_id
* @return array
* @throws Common\Implement\Exception\EmptyResult
*/
public function fetchByContractAndUnit(int $contract_id, int $unit_id): array
{
$query = $this->connection->getQueryBuilder()
->select('DISTINCT a.*')
->from("{$this->getTable()} a")
->joined('LEFT OUTER JOIN promotion_brokers pb ON pb.promotion_id = a.id')
->joined('LEFT OUTER JOIN broker_contracts bc ON bc.broker_rut = pb.broker_rut')
->joined('LEFT OUTER JOIN promotion_units pu ON pu.promotion_id = a.id')
->joined('LEFT OUTER JOIN promotion_projects pp ON pp.promotion_id = a.id')
->joined('LEFT OUTER JOIN proyecto_tipo_unidad ptu1 ON ptu1.proyecto = pp.project_id')
->joined('LEFT OUTER JOIN unidad u1 ON u1.pt = ptu1.id')
->joined('LEFT OUTER JOIN promotion_unit_types put ON put.promotion_id = a.id')
->joined('LEFT OUTER JOIN proyecto_tipo_unidad ptu2 ON ptu2.tipo = put.unit_type_id AND ptu2.proyecto = put.project_id')
->joined('LEFT OUTER JOIN unidad u2 ON u2.pt = ptu2.id')
->joined('LEFT OUTER JOIN promotion_unit_lines pul ON pul.promotion_id = a.id')
->joined('LEFT OUTER JOIN proyecto_tipo_unidad ptu3 ON ptu3.id = pul.unit_line_id')
->joined('LEFT OUTER JOIN unidad u3 ON u3.pt = ptu3.id')
->where('bc.id = :contract_id OR pu.unit_id = :unit_id OR u1.id = :unit_id OR u2.id = :unit_id OR u3.id = :unit_id')
->group('a.id');
return $this->fetchMany($query, ['contract_id' => $contract_id, 'unit_id' => $unit_id]);
}
/**
* @param int $contract_id
* @param array $unit_ids
* @return array
* @throws Common\Implement\Exception\EmptyResult
*/
public function fetchByContractAndUnits(int $contract_id, array $unit_ids): array
{
$interrogations = implode(',', array_map(fn($k) => ":id{$k}", array_keys($unit_ids)));
$query = $this->connection->getQueryBuilder()
->select('DISTINCT a.*, GROUP_CONCAT(COALESCE(pu.unit_id, u1.id, u2.id, u3.id) SEPARATOR "|") as unit_id')
->from("{$this->getTable()} a")
->joined('LEFT OUTER JOIN promotion_brokers pb ON pb.promotion_id = a.id')
->joined('LEFT OUTER JOIN broker_contracts bc ON bc.broker_rut = pb.broker_rut')
->joined('LEFT OUTER JOIN promotion_units pu ON pu.promotion_id = a.id')
->joined('LEFT OUTER JOIN promotion_projects pp ON pp.promotion_id = a.id')
->joined('LEFT OUTER JOIN proyecto_tipo_unidad ptu1 ON ptu1.proyecto = pp.project_id')
->joined('LEFT OUTER JOIN unidad u1 ON u1.pt = ptu1.id')
->joined('LEFT OUTER JOIN promotion_unit_types put ON put.promotion_id = a.id')
->joined('LEFT OUTER JOIN proyecto_tipo_unidad ptu2 ON ptu2.tipo = put.unit_type_id AND ptu2.proyecto = put.project_id')
->joined('LEFT OUTER JOIN unidad u2 ON u2.pt = ptu2.id')
->joined('LEFT OUTER JOIN promotion_unit_lines pul ON pul.promotion_id = a.id')
->joined('LEFT OUTER JOIN proyecto_tipo_unidad ptu3 ON ptu3.id = pul.unit_line_id')
->joined('LEFT OUTER JOIN unidad u3 ON u3.pt = ptu3.id')
->where("bc.id = :contract_id OR pu.unit_id IN ({$interrogations}) OR u1.id IN ({$interrogations}) OR u2.id IN ({$interrogations}) OR u3.id IN ({$interrogations})")
->group('a.id');
$unitParams = array_combine(array_map(fn($k) => "id{$k}", array_keys($unit_ids)), $unit_ids);
try {
$results = $this->connection->execute($query, array_merge(['contract_id' => $contract_id], $unitParams))->fetchAll(PDO::FETCH_ASSOC);
if (empty($results)) {
throw new Common\Implement\Exception\EmptyResult($query);
}
$temp = new class()
{
protected array $promotions = [];
public function addItem(int $id, Model\Venta\Promotion $promotion): void
{
if (!array_key_exists($id, $this->promotions)) {
$this->promotions[$id] = [
'id' => $id,
'promotions' => []
];
}
$this->promotions[$id]['promotions'] []= $promotion;
}
public function toArray(): array
{
return array_values($this->promotions);
}
};
foreach ($results as $result) {
if (str_contains($result['unit_id'], '|')) {
$ids = explode('|', $result['unit_id']);
foreach ($ids as $id) {
$temp->addItem((int) $id, $this->load($result));
}
continue;
}
$temp->addItem((int) $result['unit_id'], $this->load($result));
}
return $temp->toArray();
} catch (PDOException $exception) {
throw new Common\Implement\Exception\EmptyResult($query, $exception);
}
}
/**
* @param Model\Venta\Promotion $promotion
* @param int $project_id
* @return void
* @throws PDOException
*/
public function insertProjectForPromotion(Model\Venta\Promotion $promotion, int $project_id): void
{
$query = $this->connection->getQueryBuilder()
->insert()
->into('promotion_projects')
->columns(['promotion_id', 'project_id'])
->values([':promotion_id', ':project_id']);
$this->connection->execute($query, ['promotion_id' => $promotion->id, 'project_id' => $project_id]);
}
public function removeProjectForPromotion(Model\Venta\Promotion $promotion, int $project_id): void
{
$query = $this->connection->getQueryBuilder()
->delete()
->from('promotion_projects')
->where('promotion_id = :promotion_id AND project_id = :project_id');
$this->connection->execute($query, ['promotion_id' => $promotion->id, 'project_id' => $project_id]);
}
/**
* @param Model\Venta\Promotion $promotion
* @param int $broker_rut
* @return void
* @throws PDOException
*/
public function insertBrokerForPromotion(Model\Venta\Promotion $promotion, int $broker_rut): void
{
$query = $this->connection->getQueryBuilder()
->insert()
->into('promotion_brokers')
->columns(['promotion_id', 'broker_rut'])
->values([':promotion_id', ':broker_rut']);
$this->connection->execute($query, ['promotion_id' => $promotion->id, 'broker_rut' => $broker_rut]);
}
public function removeBrokerForPromotion(Model\Venta\Promotion $promotion, int $broker_rut): void
{
$query = $this->connection->getQueryBuilder()
->delete()
->from('promotion_brokers')
->where('promotion_id = :promotion_id AND broker_rut = :broker_rut');
$this->connection->execute($query, ['promotion_id' => $promotion->id, 'broker_rut' => $broker_rut]);
}
/**
* @param Model\Venta\Promotion $promotion
* @param int $project_id
* @param int $unit_type_id
* @return void
*/
public function insertUnitTypeForPromotion(Model\Venta\Promotion $promotion, int $project_id, int $unit_type_id): void
{
$query = $this->connection->getQueryBuilder()
->insert()
->into('promotion_unit_types')
->columns(['promotion_id', 'project_id', 'unit_type_id'])
->values([':promotion_id', ':project_id', ':unit_type_id']);
$this->connection->execute($query,
['promotion_id' => $promotion->id, 'project_id' => $project_id, 'unit_type_id' => $unit_type_id]);
}
public function removeUnitTypeForPromotion(Model\Venta\Promotion $promotion, int $project_id, int $unit_type_id): void
{
$query = $this->connection->getQueryBuilder()
->delete()
->from('promotion_unit_types')
->where('promotion_id = :promotion_id AND project_id = :project_id AND unit_type_id = :unit_type_id');
$this->connection->execute($query,
['promotion_id' => $promotion->id, 'project_id' => $project_id, 'unit_type_id' => $unit_type_id]);
}
/**
* @param Model\Venta\Promotion $promotion
* @param int $unit_line_id
* @return void
*/
public function insertUnitLineForPromotion(Model\Venta\Promotion $promotion, int $unit_line_id): void
{
$query = $this->connection->getQueryBuilder()
->insert()
->into('promotion_unit_lines')
->columns(['promotion_id', 'unit_line_id'])
->values([':promotion_id', ':unit_line_id']);
$this->connection->execute($query, ['promotion_id' => $promotion->id, 'unit_line_id' => $unit_line_id]);
}
public function removeUnitLineForPromotion(Model\Venta\Promotion $promotion, int $unit_line_id): void
{
$query = $this->connection->getQueryBuilder()
->delete()
->from('promotion_unit_lines')
->where('promotion_id = :promotion_id AND unit_line_id = :unit_line_id');
$this->connection->execute($query, ['promotion_id' => $promotion->id, 'unit_line_id' => $unit_line_id]);
}
/**
* @param Model\Venta\Promotion $promotion
* @param int $unit_id
* @return void
*/
public function insertUnitForPromotion(Model\Venta\Promotion $promotion, int $unit_id): void
{
$query = $this->connection->getQueryBuilder()
->insert()
->into('promotion_units')
->columns(['promotion_id', 'unit_id'])
->values([':promotion_id', ':unit_id']);
$this->connection->execute($query, ['promotion_id' => $promotion->id, 'unit_id' => $unit_id]);
}
public function removeUnitForPromotion(Model\Venta\Promotion $promotion, int $unit_id): void
{
$query = $this->connection->getQueryBuilder()
->delete()
->from('promotion_units')
->where('promotion_id = :promotion_id AND unit_id = :unit_id');
$this->connection->execute($query, ['promotion_id' => $promotion->id, 'unit_id' => $unit_id]);
}
}

View File

@ -1,6 +1,8 @@
<?php
namespace Incoviba\Repository\Venta;
use PDO;
use PDOException;
use Incoviba\Common\Ideal;
use Incoviba\Common\Define;
use Incoviba\Common\Implement;
@ -9,7 +11,9 @@ use Incoviba\Service;
class Propiedad extends Ideal\Repository
{
public function __construct(Define\Connection $connection, protected Service\Venta\PropiedadUnidad $propiedadUnidadService, protected Service\Venta\Unidad $unidadService)
public function __construct(Define\Connection $connection,
protected Service\Venta\PropiedadUnidad $propiedadUnidadService,
protected Service\Venta\Unidad $unidadService)
{
parent::__construct($connection);
$this->setTable('propiedad');
@ -41,10 +45,12 @@ class Propiedad extends Ideal\Repository
{
$model->id = $this->saveNew(
['unidad_principal', 'estacionamientos', 'bodegas', 'estado'],
[$model->principal()?->id,
[
$model->principal()?->id,
implode(',', array_map(function(Model\Venta\Unidad $unidad) {return $unidad->id;}, $model->estacionamientos())),
implode(',', array_map(function(Model\Venta\Unidad $unidad) {return $unidad->id;}, $model->bodegas())),
1]
1
]
);
return $model;
}
@ -67,7 +73,28 @@ class Propiedad extends Ideal\Repository
*/
public function fetchVigenteByUnidad(int $unidad_id): Model\Venta\Propiedad
{
$query = "SELECT * FROM `{$this->getTable()}` WHERE `unidad_principal` = ?";
$query = $this->connection->getQueryBuilder()
->select('a.*')
->from("{$this->getTable()} a")
->joined('propiedad_unidad pu ON pu.propiedad = a.id')
->where('`pu`.unidad = ? AND `estado` = 1');
return $this->fetchOne($query, [$unidad_id]);
}
/**
* @param int $propiedad_id
* @return array
* @throws Implement\Exception\EmptyResult
*/
public function fetchArrayById(int $propiedad_id): array
{
$query = $this->connection->getQueryBuilder()
->select()
->from($this->getTable())
->where('`id` = ?')
->limit(1);
$propiedad = $this->fetchAsArray($query, [$propiedad_id])[0];
$propiedad['unidades'] = $this->propiedadUnidadService->getArrayByPropiedad($propiedad_id);
return $propiedad;
}
}

View File

@ -1,6 +1,7 @@
<?php
namespace Incoviba\Repository\Venta;
use PDOException;
use Incoviba\Common\Ideal;
use Incoviba\Common\Define;
use Incoviba\Common\Implement;
@ -57,7 +58,12 @@ class PropiedadUnidad extends Ideal\Repository
return $this->update($model, ['propiedad', 'unidad', 'valor'], $new_data);
}
public function fetchById(int $id): Define\Model
/**
* @param int $id
* @return Model\Venta\PropiedadUnidad
* @throws Implement\Exception\EmptyResult
*/
public function fetchById(int $id): Model\Venta\PropiedadUnidad
{
$query = $this->connection->getQueryBuilder()
->select()
@ -66,16 +72,27 @@ class PropiedadUnidad extends Ideal\Repository
return $this->fetchOne($query, [$id]);
}
/**
* @param int $venta_id
* @return array
* @throws Implement\Exception\EmptyResult
*/
public function fetchByVenta(int $venta_id): array
{
$query = $this->connection->getQueryBuilder()
->select('a.*')
->from("{$this->getTable()} a")
->joined('JOIN unidad ON a.unidad = unidad.id
JOIN venta ON venta.propiedad = a.propiedad')
->joined('INNER JOIN unidad ON a.unidad = unidad.id')
->joined('INNER JOIN venta ON venta.propiedad = a.propiedad')
->where('venta.id = ?');
return $this->fetchMany($query, [$venta_id]);
}
/**
* @param int $propiedad_id
* @return array
* @throws Implement\Exception\EmptyResult
*/
public function fetchByPropiedad(int $propiedad_id): array
{
$query = $this->connection->getQueryBuilder()
@ -86,6 +103,32 @@ class PropiedadUnidad extends Ideal\Repository
->group('`unidad`.`id`');
return $this->fetchMany($query, [$propiedad_id]);
}
/**
* @param int $propiedad_id
* @return array
* @throws Implement\Exception\EmptyResult
*/
public function fetchArrayByPropiedad(int $propiedad_id): array
{
$query = $this->connection->getQueryBuilder()
->select('a.id AS pu_id, a.valor, a.propiedad, unidad.*')
->from("{$this->getTable()} a")
->joined('INNER JOIN `unidad` ON a.`unidad` = `unidad`.`id`')
->where('a.`propiedad` = ?')
->group('`unidad`.`id`');
$unidades = $this->fetchAsArray($query, [$propiedad_id]);
array_walk($unidades, function(&$unidad) {
$unidad['proyecto_tipo_unidad'] = json_decode(json_encode($this->proyectoTipoUnidadService->getById($unidad['pt'])), true);
});
return $unidades;
}
/**
* @param Define\Model $model
* @return void
* @throws PDOException
*/
public function remove(Define\Model $model): void
{
$query = $this->connection->getQueryBuilder()
@ -94,7 +137,15 @@ class PropiedadUnidad extends Ideal\Repository
$this->connection->execute($query, [$model->pu_id]);
}
protected function update(Define\Model $model, array $columns, array $data): Define\Model
/**
* @param Define\Model $model
* @param array $columns
* @param array $data
* @return Model\Venta\PropiedadUnidad
* @throws Implement\Exception\EmptyResult
* @throws PDOException
*/
protected function update(Define\Model $model, array $columns, array $data): Model\Venta\PropiedadUnidad
{
$changes = [];
$values = [];

View File

@ -63,24 +63,46 @@ class Propietario extends Ideal\Repository
return $data['otro'] !== 0;
})
->setDefault(null));
return $this->parseData(new Model\Venta\Propietario(), $data, $map);
$model = $this->parseData(new Model\Venta\Propietario(), $data, $map);
if (array_key_exists('email', $data)) {
$model->datos->email = $data['email'];
}
if (array_key_exists('telefono', $data)) {
$model->datos->telefono = $data['telefono'];
}
return $model;
}
public function save(Define\Model $model): Define\Model
{
$this->saveNew(
['rut', 'dv', 'nombres', 'apellido_paterno', 'apellido_materno', 'direccion', 'otro', 'representante'],
[$model->rut, $model->dv, $model->nombres, $model->apellidos['paterno'], $model->apellidos['materno'], $model->datos->direccion->id, $model->otro->rut ?? 0, $model->contacto->rut ?? 0]
['rut', 'dv', 'nombres', 'apellido_paterno', 'apellido_materno', 'direccion', 'email', 'telefono', 'otro', 'representante'],
[$model->rut, $model->dv, $model->nombres, $model->apellidos['paterno'], $model->apellidos['materno'] ?? '', $model->datos?->direccion->id, $model->datos?->email, $model->datos?->telefono, $model->otro->rut ?? 0, $model->contacto->rut ?? 0]
);
return $model;
}
public function edit(Define\Model $model, array $new_data): Define\Model
{
return $this->update($model, ['dv', 'nombres', 'apellido_paterno', 'apellido_materno', 'direccion', 'otro', 'representante'], $new_data);
return $this->update($model, ['dv', 'nombres', 'apellido_paterno', 'apellido_materno', 'direccion', 'email', 'telefono', 'otro', 'representante'], $new_data);
}
public function filterData(array $data): array
{
return array_intersect_key($data, array_flip(['rut', 'dv', 'nombres', 'apellido_paterno', 'apellido_materno', 'direccion', 'representante']));
return array_intersect_key($data, array_flip(['rut', 'dv', 'nombres', 'apellido_paterno', 'apellido_materno', 'direccion', 'email', 'telefono', 'otro', 'representante']));
}
/**
* @param array $ruts
* @return array
* @throws Implement\Exception\EmptyResult
*/
public function fetchByRuts(array $ruts): array
{
$rutsQuery = implode(', ', array_fill(0, count($ruts), '?'));
$query = $this->connection->getQueryBuilder()
->select()
->from($this->getTable())
->where("rut IN ({$rutsQuery})");
return $this->fetchMany($query, $ruts);
}
}

View File

@ -0,0 +1,230 @@
<?php
namespace Incoviba\Repository\Venta;
use DateTimeInterface;
use DateInterval;
use PDO;
use Incoviba\Common;
use Incoviba\Model;
use Incoviba\Repository;
class Reservation extends Common\Ideal\Repository
{
public function __construct(Common\Define\Connection $connection, protected Repository\Persona $personaRepository,
protected Repository\Proyecto\Broker $brokerRepository,
protected Unidad $unitRepository, protected Promotion $promotionRepository)
{
parent::__construct($connection);
}
public function getTable(): string
{
return 'reservations';
}
public function create(?array $data = null): Model\Venta\Reservation
{
$map = (new Common\Implement\Repository\MapperParser())
->register('buyer_rut', (new Common\Implement\Repository\Mapper())
->setProperty('buyer')
->setFunction(function($data) use ($data) {
return $this->personaRepository->fetchById($data['buyer_rut']);
}))
->register('date', new Common\Implement\Repository\Mapper\DateTime('date'))
->register('broker_rut', (new Common\Implement\Repository\Mapper())
->setProperty('broker')
->setDefault(null)
->setFunction(function($data) use ($data) {
try {
return $this->brokerRepository->fetchById($data['broker_rut']);
} catch (Common\Implement\Exception\EmptyResult) {
return null;
}
}));
return $this->parseData(new Model\Venta\Reservation(), $data, $map);
}
public function save(Common\Define\Model $model): Model\Venta\Reservation
{
$model->id = $this->saveNew([
'buyer_rut',
'date',
'broker_rut'
], [
$model->buyer->rut,
$model->date->format('Y-m-d'),
$model->broker?->rut
]);
$this->saveUnits($model);
$this->savePromotions($model);
return $model;
}
/**
* @param Common\Define\Model $model
* @param array $new_data
* @return Model\Venta\Reservation
* @throws Common\Implement\Exception\EmptyResult
*/
public function edit(Common\Define\Model $model, array $new_data): Model\Venta\Reservation
{
return $this->update($model, ['buyer_rut', 'date', 'broker_rut'], $new_data);
}
public function load(array $data_row): Model\Venta\Reservation
{
$model = parent::load($data_row);
$this->fetchUnits($model);
$this->fetchPromotions($model);
return $model;
}
/**
* @param int $buyer_rut
* @param DateTimeInterface $date
* @return Model\Venta\Reservation
* @throws Common\Implement\Exception\EmptyResult
*/
public function fetchByBuyerAndDate(int $buyer_rut, DateTimeInterface $date): Model\Venta\Reservation
{
$query = $this->connection->getQueryBuilder()
->select()
->from('reservations')
->where('buyer_rut = :buyer_rut AND date >= :date');
return $this->fetchOne($query, ['buyer_rut' => $buyer_rut, 'date' => $date->sub(new DateInterval('P10D'))->format('Y-m-d')]);
}
protected function saveUnits(Model\Venta\Reservation $reservation): void
{
if (empty($reservation->units)) {
return;
}
$queryCheck = $this->connection->getQueryBuilder()
->select('COUNT(id) AS cnt')
->from('reservation_data')
->where('reservation_id = :id AND type = "Unit" AND reference_id = :unit_id');
$statementCheck = $this->connection->prepare($queryCheck);
$queryInsert = $this->connection->getQueryBuilder()
->insert()
->into('reservation_data')
->columns(['reservation_id', 'type', 'reference_id', 'value'])
->values([':reservation_id', ':type', ':reference_id', ':value']);
$statementInsert = $this->connection->prepare($queryInsert);
foreach ($reservation->units as $unit) {
$statementCheck->execute(['id' => $reservation->id, 'unit_id' => $unit['unit']->id]);
$result = $statementCheck->fetch(PDO::FETCH_ASSOC);
if ($result['cnt'] > 0) {
continue;
}
$statementInsert->execute(['reservation_id' => $reservation->id, 'type' => 'Unit', 'reference_id' => $unit['unit']->id, 'value' => $unit['value']]);
}
}
protected function savePromotions(Model\Venta\Reservation $reservation): void
{
if (empty($reservation->promotions)) {
return;
}
$queryCheck = $this->connection->getQueryBuilder()
->select('COUNT(id) AS cnt')
->from('reservation_data')
->where('reservation_id = :id AND type = "Promotion" AND reference_id = :promotion_id');
$statementCheck = $this->connection->prepare($queryCheck);
$queryInsert = $this->connection->getQueryBuilder()
->insert()
->into('reservation_data')
->columns(['reservation_id', 'type', 'reference_id'])
->values([':reservation_id', ':type', ':reference_id']);
$statementInsert = $this->connection->prepare($queryInsert);
foreach ($reservation->promotions as $promotion) {
$statementCheck->execute(['id' => $reservation->id, 'promotion_id' => $promotion->id]);
$result = $statementCheck->fetch(PDO::FETCH_ASSOC);
if ($result['cnt'] > 0) {
continue;
}
$statementInsert->execute(['reservation_id' => $reservation->id, 'type' => 'Promotion', 'reference_id' => $promotion->id]);
}
}
protected function editUnits(Model\Venta\Reservation $reservation, array $new_data): void
{
$querySelect = $this->connection->getQueryBuilder()
->select()
->from('reservation_data')
->where('reservation_id = :id AND type = "Unit" AND reference_id = :unit_id');
$statementSelect = $this->connection->prepare($querySelect);
$queryUpdate = $this->connection->getQueryBuilder()
->update('reservation_data')
->set('value = :value')
->where('reservation_id = :id AND type = "Unit" AND reference_id = :unit_id');
$statementUpdate = $this->connection->prepare($queryUpdate);
foreach ($new_data as $unit_id => $value) {
$idx = $reservation->findUnit($unit_id);
if ($idx === null) {
$reservation->addUnit($this->unitRepository->fetchById($unit_id), $value);
continue;
}
$statementSelect->execute(['id' => $reservation->id, 'unit_id' => $unit_id]);
$result = $statementSelect->fetch(PDO::FETCH_ASSOC);
if (!$result) {
continue;
}
$statementUpdate->execute(['id' => $reservation->id, 'unit_id' => $unit_id, 'value' => $value]);
$reservation->units[$idx]['value'] = $value;
}
}
protected function editPromotions(Model\Venta\Reservation $reservation, array $new_data): void
{
$querySelect = $this->connection->getQueryBuilder()
->select()
->from('reservation_data')
->where('reservation_id = :id AND type = "Promotion" AND reference_id = :promotion_id');
$statementSelect = $this->connection->prepare($querySelect);
$queryUpdate = $this->connection->getQueryBuilder()
->update('reservation_data')
->set('value = :value')
->where('reservation_id = :id AND type = "Promotion" AND reference_id = :promotion_id');
$statementUpdate = $this->connection->prepare($queryUpdate);
foreach ($new_data as $promotion_id => $value) {
$idx = array_search($promotion_id, array_column($reservation->promotions, 'id'));
if ($idx === false) {
$reservation->promotions []= $this->promotionRepository->fetchById($promotion_id);
continue;
}
$statementSelect->execute(['id' => $reservation->id, 'promotion_id' => $promotion_id]);
$result = $statementSelect->fetch(PDO::FETCH_ASSOC);
if (!$result) {
continue;
}
$statementUpdate->execute(['id' => $reservation->id, 'promotion_id' => $promotion_id, 'value' => $value]);
$reservation->promotions[$idx] = $this->promotionRepository->fetchById($promotion_id);
}
}
protected function fetchUnits(Model\Venta\Reservation &$reservation): Model\Venta\Reservation
{
$query = $this->connection->getQueryBuilder()
->select()
->from('reservation_data')
->where('reservation_id = :id AND type = "Unit"');
$statement = $this->connection->execute($query, ['id' => $reservation->id]);
while ($result = $statement->fetch(PDO::FETCH_ASSOC)) {
try {
$reservation->addUnit($this->unitRepository->fetchById($result['reference_id']), $result['value']);
} catch (Common\Implement\Exception\EmptyResult) {}
}
return $reservation;
}
protected function fetchPromotions(Model\Venta\Reservation $reservation): Model\Venta\Reservation
{
$query = $this->connection->getQueryBuilder()
->select()
->from('reservation_data')
->where('type = "Promotion" AND reservation_id = :id');
$statement = $this->connection->execute($query, ['id' => $reservation->id]);
while ($result = $statement->fetch(PDO::FETCH_ASSOC)) {
try {
$reservation->promotions []= $this->promotionRepository->fetchById($result['reference_id']);
} catch (Common\Implement\Exception\EmptyResult) {}
}
return $reservation;
}
}

View File

@ -0,0 +1,60 @@
<?php
namespace Incoviba\Repository\Venta\Reservation;
use Incoviba\Common;
use Incoviba\Model;
use Incoviba\Repository;
class State extends Common\Ideal\Repository
{
public function __construct(Common\Define\Connection $connection, protected Repository\Venta\Reservation $reservationRepository)
{
parent::__construct($connection);
}
public function getTable(): string
{
return 'reservation_states';
}
public function create(?array $data = null): Model\Venta\Reservation\State
{
$map = (new Common\Implement\Repository\MapperParser(['type']))
->register('reservation_id', (new Common\Implement\Repository\Mapper())
->setProperty('reservation')
->setFunction(function($data) use ($data) {
return $this->reservationRepository->fetchById($data['reservation_id']);
}))
->register('date', new Common\Implement\Repository\Mapper\DateTime('date'));
return $this->parseData(new Model\Venta\Reservation\State(), $data, $map);
}
public function save(Common\Define\Model $model): Model\Venta\Reservation\State
{
$model->id = $this->saveNew(
['reservation_id', 'date', 'type'],
[$model->reservation->id, $model->date->format('Y-m-d'), $model->type]
);
return $model;
}
public function edit(Common\Define\Model $model, array $new_data): Model\Venta\Reservation\State
{
return $this->update($model, ['reservation_id', 'date', 'type'], $new_data);
}
public function fetchByReservation(int $reservation_id): array
{
$query = $this->connection->getQueryBuilder()
->select()
->from($this->getTable())
->where('reservation_id = :reservation_id');
return $this->fetchMany($query, ['reservation_id' => $reservation_id]);
}
public function fetchActiveByReservation(int $reservation_id): array
{
$query = $this->connection->getQueryBuilder()
->select()
->from($this->getTable())
->where('reservation_id = :reservation_id AND type = :type');
return $this->fetchMany($query, ['reservation_id' => $reservation_id, 'type' => Model\Venta\Reservation\State\Type::ACTIVE]);
}
}

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` = ?";

View File

@ -30,8 +30,9 @@ class Unidad extends Ideal\Repository
public function save(Define\Model $model): Model\Venta\Unidad
{
$model->id = $this->saveNew(
['subtipo', 'piso', 'descripcion', 'orientacion', 'pt'],
[$model->subtipo, $model->piso, $model->descripcion, $model->orientacion, $model->proyectoTipoUnidad->id]
['proyecto', 'tipo', 'subtipo', 'piso', 'descripcion', 'abreviacion', 'orientacion', 'pt'],
[$model->proyectoTipoUnidad->proyecto->id, $model->proyectoTipoUnidad->tipoUnidad->id, $model->subtipo,
$model->piso, $model->descripcion, $model->proyectoTipoUnidad->abreviacion, $model->orientacion, $model->proyectoTipoUnidad->id]
);
return $model;
}
@ -92,8 +93,8 @@ class Unidad extends Ideal\Repository
->select('a.*, up.prorrateo')
->from("{$this->getTable()} a")
->joined($this->joinProrrateo())
->joined("JOIN `proyecto_tipo_unidad` ptu ON ptu.`id` = a.`pt`
JOIN `tipo_unidad` tu ON tu.`id` = ptu.`tipo`")
->joined("INNER JOIN `proyecto_tipo_unidad` ptu ON ptu.`id` = a.`pt`")
->joined("INNER JOIN `tipo_unidad` tu ON tu.`id` = ptu.`tipo`")
->where('ptu.proyecto = ?')
->order('tu.orden');
return $this->fetchMany($query, [$proyecto_id]);
@ -104,12 +105,12 @@ class Unidad extends Ideal\Repository
->select('DISTINCT a.*, up.prorrateo')
->from("{$this->getTable()} a")
->joined($this->joinProrrateo())
->joined("JOIN `proyecto_tipo_unidad` ptu ON ptu.`id` = a.`pt`
JOIN `tipo_unidad` tu ON tu.`id` = ptu.`tipo`
LEFT OUTER JOIN `propiedad_unidad` pu ON pu.`unidad` = a.`id`
LEFT OUTER JOIN `venta` ON `venta`.`propiedad` = `pu`.`propiedad`
LEFT OUTER JOIN (SELECT ev1.* FROM `estado_venta` ev1 JOIN (SELECT MAX(`id`) as 'id', `venta` FROM `estado_venta` GROUP BY `venta`) ev0 ON ev0.`id` = ev1.`id`) ev ON ev.`venta` = `venta`.`id`
LEFT OUTER JOIN `tipo_estado_venta` tev ON tev.`id` = ev.`estado`")
->joined('INNER JOIN `proyecto_tipo_unidad` ptu ON ptu.`id` = a.`pt`')
->joined('INNER JOIN `tipo_unidad` tu ON tu.`id` = ptu.`tipo`')
->joined('LEFT OUTER JOIN `propiedad_unidad` pu ON pu.`unidad` = a.`id`')
->joined('LEFT OUTER JOIN `venta` ON `venta`.`propiedad` = pu.`propiedad`')
->joined($this->joinEstadoVenta())
->joined('LEFT OUTER JOIN `tipo_estado_venta` tev ON tev.`id` = ev.`estado`')
->where("ptu.`proyecto` = ? AND (pu.`id` IS NULL OR `venta`.`id` IS NULL OR tev.`activa` = 0)")
->order('tu.orden');
return $this->fetchMany($query, [$proyecto_id]);
@ -120,12 +121,12 @@ class Unidad extends Ideal\Repository
->select('DISTINCT a.*, up.prorrateo')
->from("{$this->getTable()} a")
->joined($this->joinProrrateo())
->joined("JOIN `proyecto_tipo_unidad` ptu ON ptu.`id` = a.`pt`
JOIN `tipo_unidad` tu ON tu.`id` = ptu.`tipo`
LEFT OUTER JOIN `propiedad_unidad` pu ON pu.`unidad` = a.`id`
LEFT OUTER JOIN `venta` ON `venta`.`propiedad` = pu.`propiedad`
LEFT OUTER JOIN (SELECT ev1.* FROM `estado_venta` ev1 JOIN (SELECT MAX(`id`) as 'id', `venta` FROM `estado_venta`) ev0 ON ev0.`id` = ev1.`id`) ev ON ev.`venta` = `venta`.`id`
LEFT OUTER JOIN `tipo_estado_venta` tev ON tev.`id` = ev.`estado`")
->joined('INNER JOIN proyecto_tipo_unidad ptu ON ptu.id = a.pt')
->joined('INNER tipo_unidad tu ON tu.id = ptu.tipo')
->joined('LEFT OUTER JOIN propiedad_unidad pu ON pu.unidad = a.id')
->joined('LEFT OUTER JOIN venta ON venta.propiedad = pu.propiedad')
->joined($this->joinEstadoVenta())
->joined('LEFT OUTER JOIN tipo_estado_venta tev ON tev.id = ev.estado')
->where("a.`descripcion` LIKE ? AND tu.`descripcion` = ? AND (pu.`id` IS NULL OR `venta`.`id` IS NULL OR tev.`activa` = 0)");
return $this->fetchMany($query, [$descripcion, $tipo]);
}
@ -141,12 +142,12 @@ class Unidad extends Ideal\Repository
$query = $this->connection->getQueryBuilder()
->select('a.id')
->from("{$this->getTable()} a")
->joined("JOIN `proyecto_tipo_unidad` ptu ON ptu.`id` = a.`pt`
JOIN `tipo_unidad` tu ON tu.`id` = ptu.`tipo`
LEFT OUTER JOIN `propiedad_unidad` pu ON pu.`unidad` = a.`id`
LEFT OUTER JOIN `venta` ON `venta`.`propiedad` = pu.`propiedad`
LEFT OUTER JOIN (SELECT ev1.* FROM `estado_venta` ev1 JOIN (SELECT MAX(`id`) as 'id', `venta` FROM `estado_venta`) ev0 ON ev0.`id` = ev1.`id`) ev ON ev.`venta` = `venta`.`id`
LEFT OUTER JOIN `tipo_estado_venta` tev ON tev.`id` = ev.`estado`")
->joined('INNER JOIN `proyecto_tipo_unidad` ptu ON ptu.`id` = a.`pt`')
->joined('INNER JOIN `tipo_unidad` tu ON tu.`id` = ptu.`tipo`')
->joined('LEFT OUTER JOIN `propiedad_unidad` pu ON pu.`unidad` = a.`id`')
->joined('LEFT OUTER JOIN `venta` ON `venta`.`propiedad` = pu.`propiedad`')
->joined($this->joinEstadoVenta())
->joined('LEFT OUTER JOIN `tipo_estado_venta` tev ON tev.`id` = ev.`estado`')
->where("a.`descripcion` LIKE ? AND tu.`descripcion` = ? AND (pu.`id` IS NULL OR `venta`.`id` IS NULL OR tev.`activa` = 0)");
try {
return $this->connection->execute($query, [$descripcion, $tipo])->fetchAll(PDO::FETCH_ASSOC);
@ -156,6 +157,14 @@ class Unidad extends Ideal\Repository
}
public function fetchByIdForSearch(int $unidad_id): array
{
$subSubQuery = $this->connection->getQueryBuilder()
->select('MAX(id) AS id, precio')
->from('estado_precio')
->group('precio');
$subQuery = $this->connection->getQueryBuilder()
->select('ep1.*')
->from('estado_precio ep1')
->joined("INNER JOIN ($subSubQuery) ep0 ON ep0.id = ep1.id");
$query = $this->connection->getQueryBuilder()
->select('unidad.id AS id, unidad.descripcion AS descripcion')
->columns('proyecto.id AS proyecto_id, proyecto.descripcion AS proyecto_descripcion')
@ -163,18 +172,123 @@ class Unidad extends Ideal\Repository
->columns('ptu.m2 + ptu.logia + ptu.terraza AS superficie')
->columns('precio.valor AS precio')
->from($this->getTable())
->joined('JOIN proyecto_tipo_unidad ptu ON ptu.id = unidad.pt')
->joined('JOIN proyecto ON proyecto.id = ptu.proyecto')
->joined('JOIN tipo_unidad tu ON tu.id = ptu.tipo')
->joined('JOIN precio ON precio.unidad = unidad.id')
->joined('JOIN (SELECT ep1.* FROM estado_precio ep1 JOIN (SELECT MAX(id) AS id, precio FROM estado_precio GROUP BY precio) ep0 ON ep0.id = ep1.id) ep ON ep.precio = precio.id')
->joined('INNER JOIN proyecto_tipo_unidad ptu ON ptu.id = unidad.pt')
->joined('INNER JOIN proyecto ON proyecto.id = ptu.proyecto')
->joined('INNER JOIN tipo_unidad tu ON tu.id = ptu.tipo')
->joined('LEFT OUTER JOIN precio ON precio.unidad = unidad.id')
->joined("LEFT OUTER JOIN ({$subQuery}) ep ON ep.precio = precio.id")
->where('unidad.id = ?')
->group('unidad.id');
return $this->connection->execute($query, [$unidad_id])->fetch(PDO::FETCH_ASSOC);
}
/**
* @param int $unidad_id
* @return bool
* @throws Implement\Exception\EmptyResult
*/
public function fetchSoldByUnidad(int $unidad_id): bool
{
$query = $this->connection->getQueryBuilder()
->select('a.id')
->from("{$this->getTable()} a")
->joined('INNER JOIN `propiedad_unidad` pu ON pu.`unidad` = a.`id`')
->joined('INNER JOIN `venta` ON `venta`.`propiedad` = `pu`.`propiedad`')
->joined($this->joinEstadoVenta())
->joined('LEFT OUTER JOIN `tipo_estado_venta` tev ON tev.`id` = ev.`estado`')
->where('a.id = :unidad_id AND tev.activa = 1');
try {
$result = $this->connection->execute($query, ['unidad_id' => $unidad_id])->fetch(PDO::FETCH_ASSOC);
return $result !== false;
} catch (PDOException $exception) {
throw new Implement\Exception\EmptyResult($query, $exception);
}
}
/**
* @param array $unidad_ids
* @return array
* @throws Implement\Exception\EmptyResult
*/
public function fetchSoldByUnidades(array $unidad_ids): array
{
$interrogations = implode(',', array_fill(0, count($unidad_ids), '?'));
$query = $this->connection->getQueryBuilder()
->select('a.id')
->from("{$this->getTable()} a")
->joined('INNER JOIN `propiedad_unidad` pu ON pu.`unidad` = a.`id`')
->joined('INNER JOIN `venta` ON `venta`.`propiedad` = `pu`.`propiedad`')
->joined($this->joinEstadoVenta(true))
->joined('INNER JOIN `tipo_estado_venta` tev ON tev.`id` = ev.`estado`')
->where("a.id IN ({$interrogations}) AND tev.activa = 1");
try {
$results = $this->connection->execute($query, $unidad_ids)->fetchAll(PDO::FETCH_ASSOC);
if (empty($results)) {
throw new Implement\Exception\EmptyResult($query);
}
$missing = array_diff(array_map(fn($id) => (int) $id, $unidad_ids), array_column($results, 'id'));
return [...array_map(function($result) {
return [
'id' => $result['id'],
'sold' => true
];
}, $results), ...array_map(function($id) {
return [
'id' => $id,
'sold' => false
];
}, $missing)];
} catch (PDOException $exception) {
throw new Implement\Exception\EmptyResult($query, $exception);
}
}
/**
* @param int $promotion_id
* @return array
* @throws Implement\Exception\EmptyResult
*/
public function fetchByPromotion(int $promotion_id): array
{
$query = $this->connection->getQueryBuilder()
->select('a.*')
->from("{$this->getTable()} a")
->joined('INNER JOIN `promotion_units` pu ON pu.`unit_id` = a.`id`')
->where('pu.`promotion_id` = :promotion_id');
return $this->fetchMany($query, ['promotion_id' => $promotion_id]);
}
/**
* @param int $proyecto_id
* @param int $tipo_id
* @return array
* @throws Implement\Exception\EmptyResult
*/
public function fetchByProyectoAndTipo(int $proyecto_id, int $tipo_id): array
{
$query = $this->connection->getQueryBuilder()
->select('a.*')
->from("{$this->getTable()} a")
->joined('INNER JOIN proyecto_tipo_unidad ptu ON a.pt = ptu.id')
->where('ptu.`proyecto` = :proyecto_id AND ptu.`tipo` = :tipo_id');
return $this->fetchMany($query, ['proyecto_id' => $proyecto_id, 'tipo_id' => $tipo_id]);
}
protected function joinProrrateo(): string
{
return "LEFT OUTER JOIN unidad_prorrateo up ON up.unidad_id = a.id";
}
protected function joinEstadoVenta(bool $inner = false): string
{
$subSubQuery = $this->connection->getQueryBuilder()
->select('MAX(id) AS id, venta')
->from('estado_venta')
->group('venta');
$join = $inner ? 'INNER' : 'LEFT OUTER';
$subQuery = $this->connection->getQueryBuilder()
->select('ev1.*')
->from('estado_venta ev1')
->joined("{$join} JOIN ($subSubQuery) ev0 ON ev0.id = ev1.id");
return "{$join} JOIN ({$subQuery}) ev ON ev.`venta` = `venta`.`id`";
}
}