From 600773a27092dcc1ae4327758106ba6b891a234b Mon Sep 17 00:00:00 2001 From: Juan Pablo Vial Date: Mon, 15 Sep 2025 14:07:52 -0300 Subject: [PATCH 01/10] Unit promotions --- .../ventas/reservations/modal/add.blade.php | 75 ++++++++++++------- 1 file changed, 47 insertions(+), 28 deletions(-) diff --git a/app/resources/views/ventas/reservations/modal/add.blade.php b/app/resources/views/ventas/reservations/modal/add.blade.php index 4c7fcf2..5e9f2fd 100644 --- a/app/resources/views/ventas/reservations/modal/add.blade.php +++ b/app/resources/views/ventas/reservations/modal/add.blade.php @@ -293,34 +293,7 @@ return } this.components.units.innerHTML = this.data.units.map(unit => { - return [ - '
', - '
', - ``, - `', - '
', - '
', - '', - '
', - '', - '
UF
', - '
', - '
', - '
', - '', - ``, - '
', - '
', - ].join('') + return this.draw.unit(unit) }).join('') this.components.units.querySelectorAll('.dropdown').forEach(dropdown => { $(dropdown).dropdown() @@ -331,6 +304,52 @@ this.remove(idx) }) }) + }, + unit: unit => { + let promotions = '' + if (unit.type === 'departamento') { + promotions = [ + '
', + '', + '', + '
Promociones
', + '', + '
', + '' + ].join('') + } + return [ + '
', + '
', + ``, + `', + '
', + '
', + '', + '
', + '', + '
UF
', + '
', + '
', + promotions, + '
', + '', + ``, + '
', + '
', + ].join('') } } reset() { -- 2.49.0 From 22195dae8b2a84476d65c48161caefe1fb4c701d Mon Sep 17 00:00:00 2001 From: Juan Pablo Vial Date: Mon, 15 Sep 2025 14:21:46 -0300 Subject: [PATCH 02/10] Redis max log size --- app/common/Implement/Log/Processor/ArrayBuilder.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/common/Implement/Log/Processor/ArrayBuilder.php b/app/common/Implement/Log/Processor/ArrayBuilder.php index d323e4c..f6551ac 100644 --- a/app/common/Implement/Log/Processor/ArrayBuilder.php +++ b/app/common/Implement/Log/Processor/ArrayBuilder.php @@ -60,7 +60,8 @@ class ArrayBuilder try { $params = [ $this->container->get(Predis\ClientInterface::class), - "logs:{$handlerData['name']}" + "logs:{$handlerData['name']}", + 'capSize' => 100 ]; } catch (NotFoundExceptionInterface | ContainerExceptionInterface $exception) { $this->log($exception, ['handlerData' => $handlerData]); -- 2.49.0 From b2e0031422efa20ccc685e25c53d2b32690ee277 Mon Sep 17 00:00:00 2001 From: Juan Pablo Vial Date: Mon, 15 Sep 2025 18:45:37 -0300 Subject: [PATCH 03/10] Cleanup --- app/src/Service/Venta/MediosPago/Toku/Subscription.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/Service/Venta/MediosPago/Toku/Subscription.php b/app/src/Service/Venta/MediosPago/Toku/Subscription.php index 01f7d98..4e1505c 100644 --- a/app/src/Service/Venta/MediosPago/Toku/Subscription.php +++ b/app/src/Service/Venta/MediosPago/Toku/Subscription.php @@ -99,13 +99,13 @@ class Subscription extends AbstractEndPoint public function queue(int $venta_id): bool { try { - $venta = $this->ventaService->getById($venta_id); + $this->ventaService->getById($venta_id); } catch (Read $exception) { $this->logger->warning($exception); return false; } try { - $subscription = $this->subscriptionRepsitory->fetchByVenta($venta_id); + $this->subscriptionRepsitory->fetchByVenta($venta_id); return false; } catch (EmptyResult) { return true; -- 2.49.0 From b750f80eb727049aaeb29a30db992914dee6178f Mon Sep 17 00:00:00 2001 From: Juan Pablo Vial Date: Mon, 15 Sep 2025 20:16:44 -0300 Subject: [PATCH 04/10] FIX: unidades port tipo --- app/src/Repository/Venta/Promotion.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/Repository/Venta/Promotion.php b/app/src/Repository/Venta/Promotion.php index 0b20bff..9839032 100644 --- a/app/src/Repository/Venta/Promotion.php +++ b/app/src/Repository/Venta/Promotion.php @@ -187,7 +187,7 @@ class Promotion extends Common\Ideal\Repository ->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') + ->joined('LEFT OUTER JOIN proyecto_tipo_unidad ptu1 ON ptu1.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]); -- 2.49.0 From fc65ee581a8a10d6b67af708e8815548dd89855e Mon Sep 17 00:00:00 2001 From: Juan Pablo Vial Date: Mon, 15 Sep 2025 20:18:29 -0300 Subject: [PATCH 05/10] Promotions by unit --- .../ventas/reservations/modal/add.blade.php | 100 +++++++++++------- 1 file changed, 64 insertions(+), 36 deletions(-) diff --git a/app/resources/views/ventas/reservations/modal/add.blade.php b/app/resources/views/ventas/reservations/modal/add.blade.php index 5e9f2fd..c95f2e4 100644 --- a/app/resources/views/ventas/reservations/modal/add.blade.php +++ b/app/resources/views/ventas/reservations/modal/add.blade.php @@ -238,6 +238,7 @@ } } class AddModalUnits { + parent = null ids = { buttons_holder: '', units: '' @@ -252,7 +253,8 @@ units: null, } - constructor() { + constructor(parent) { + this.parent = parent this.ids = { buttons_holder: 'add_unit_buttons', units: 'add_units' @@ -265,6 +267,9 @@ } this.setup() } + get promotions() { + return this.parent.data.promotions[this.parent.data.current_project] + } draw = { button: type => { return [ @@ -295,7 +300,24 @@ this.components.units.innerHTML = this.data.units.map(unit => { return this.draw.unit(unit) }).join('') - this.components.units.querySelectorAll('.dropdown').forEach(dropdown => { + this.components.units.querySelectorAll('.dropdown.add_units').forEach(dropdown => { + $(dropdown).dropdown({ + onChange: (value, text, $selectedItem) => { + const unitPromotions = this.promotions.filter(promotion => promotion.units.length > 0) + const promotions = unitPromotions.filter(promotion => promotion.units.filter(unit => unit.id === parseInt(value)).length > 0) + console.debug($selectedItem.parent().parent().parent().parent().find('.add_promotions_unit')) + $selectedItem.parent().parent().parent().parent().find('.add_promotions_unit') + .dropdown('change values', promotions.map(promotion => { + return { + value: promotion.id, + name: promotion.description, + text: promotion.description, + } + })) + } + }) + }) + this.components.units.querySelectorAll('.dropdown.add_promotions_unit').forEach(dropdown => { $(dropdown).dropdown() }) this.components.units.querySelectorAll('.remove_unit').forEach(button => { @@ -308,24 +330,26 @@ unit: unit => { let promotions = '' if (unit.type === 'departamento') { - promotions = [ - '
', - '', - '', - '
Promociones
', - '' - ].join('') + '
' + ].join('') + } } return [ '
', '
', ``, - `
@@ -107,7 +107,7 @@ @push('page_styles') @@ -294,9 +294,9 @@ } } columnsData() { - return this.reservations.map(reservation => { + return this.reservations.map(reservation => { const date = new Date(Date.parse(reservation.date) + 24 * 60 * 60 * 1000) - return { + return { id: reservation.id, unidades: reservation.summary, cliente: reservation.buyer.nombreCompleto, @@ -412,7 +412,7 @@ columnsData() { const data = super.columnsData(); return data.map(row => { - delete (row['valida']) + delete(row['valida']) return row }) } @@ -475,8 +475,8 @@ columnsData() { const data = super.columnsData() return this.reservations.map((reservation, idx) => { - data[idx]['estado'] = reservation.state.charAt(0).toUpperCase() + reservation.state.slice(1) - data[idx]['comentarios'] = reservation.comments?.join('
\n') ?? '' + data[idx]['estado'] = this.mapState(reservation.current_state) + data[idx]['comentarios'] = reservation.comments ?? '' return data[idx] }) } @@ -484,6 +484,13 @@ return '' } watch() {} + + mapState(state) { + return { + 'canceled': 'Cancelado', + 'rejected': 'Rechazado' + }[state.toLowerCase()] + } } const reservations = { @@ -645,6 +652,7 @@ } } } + $(document).ready(() => { reservations.setup({ ids: { diff --git a/app/src/Model/Venta/Reservation.php b/app/src/Model/Venta/Reservation.php index cc777eb..8f84ce4 100644 --- a/app/src/Model/Venta/Reservation.php +++ b/app/src/Model/Venta/Reservation.php @@ -117,6 +117,8 @@ class Reservation extends Common\Ideal\Model return $base >= $price; } + public string $comments; + protected function jsonComplement(): array { return [ @@ -131,7 +133,10 @@ class Reservation extends Common\Ideal\Model 'base' => $this->base(), 'price' => $this->price(), 'valid' => $this->valid(), - 'summary' => $this->summary() + 'summary' => $this->summary(), + 'states' => $this->states() ?? [], + 'current_state' => $this->currentState()?->type?->name ?? null, + 'comments' => $this->comments ?? '', ]; } } diff --git a/app/src/Model/Venta/Reservation/State.php b/app/src/Model/Venta/Reservation/State.php index 64eeed5..c7468d5 100644 --- a/app/src/Model/Venta/Reservation/State.php +++ b/app/src/Model/Venta/Reservation/State.php @@ -16,7 +16,10 @@ class State extends Common\Ideal\Model return [ 'reservation_id' => $this->reservation->id, 'date' => $this->date->format('Y-m-d'), - 'type' => $this->type + 'type' => [ + 'id' => $this->type->value, + 'name' => $this->type->name, + ] ]; } } diff --git a/app/src/Model/Venta/Reservation/State/Type.php b/app/src/Model/Venta/Reservation/State/Type.php index 96d60e5..2ea7319 100644 --- a/app/src/Model/Venta/Reservation/State/Type.php +++ b/app/src/Model/Venta/Reservation/State/Type.php @@ -18,6 +18,6 @@ enum Type: int } public static function getTypes(): array { - return [self::ACTIVE->value, self::INACTIVE->value, self::REJECTED->value]; + return [self::ACTIVE->value, self::INACTIVE->value, self::REJECTED->value, self::CANCELLED->value]; } } diff --git a/app/src/Repository/Venta/Reservation.php b/app/src/Repository/Venta/Reservation.php index e181eba..bd457f4 100644 --- a/app/src/Repository/Venta/Reservation.php +++ b/app/src/Repository/Venta/Reservation.php @@ -4,6 +4,7 @@ namespace Incoviba\Repository\Venta; use DateTimeInterface; use DateInterval; use Incoviba\Common\Define; +use Incoviba\Common\Implement\Exception\EmptyResult; use Incoviba\Exception\Model\InvalidState; use PDO; use Incoviba\Common; @@ -29,7 +30,7 @@ class Reservation extends Common\Ideal\Repository public function create(?array $data = null): Model\Venta\Reservation { - $map = (new Common\Implement\Repository\MapperParser()) + $map = (new Common\Implement\Repository\MapperParser(['comments'])) ->register('project_id', (new Common\Implement\Repository\Mapper()) ->setProperty('project') ->setFunction(function($data) { @@ -114,13 +115,16 @@ class Reservation extends Common\Ideal\Repository /** * @param int $project_id - * @param int $state + * @param int|string $state * @return array - * @throws Common\Implement\Exception\EmptyResult + * @throws EmptyResult * @throws InvalidState */ - public function fetchState(int $project_id, int $state): array + public function fetchState(int $project_id, int|string $state): array { + if (is_string($state)) { + $state = Model\Venta\Reservation\State\Type::from($state)->value; + } if (!in_array($state, Model\Venta\Reservation\State\Type::getTypes())) { throw new InvalidState(); } -- 2.49.0 From 31fc1269b49f35848618bb9238ad701a06997c8d Mon Sep 17 00:00:00 2001 From: Juan Pablo Vial Date: Mon, 22 Sep 2025 14:09:19 -0300 Subject: [PATCH 07/10] Cleanup --- app/resources/views/ventas/reservations/modal/add.blade.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/resources/views/ventas/reservations/modal/add.blade.php b/app/resources/views/ventas/reservations/modal/add.blade.php index c95f2e4..1150441 100644 --- a/app/resources/views/ventas/reservations/modal/add.blade.php +++ b/app/resources/views/ventas/reservations/modal/add.blade.php @@ -305,7 +305,6 @@ onChange: (value, text, $selectedItem) => { const unitPromotions = this.promotions.filter(promotion => promotion.units.length > 0) const promotions = unitPromotions.filter(promotion => promotion.units.filter(unit => unit.id === parseInt(value)).length > 0) - console.debug($selectedItem.parent().parent().parent().parent().find('.add_promotions_unit')) $selectedItem.parent().parent().parent().parent().find('.add_promotions_unit') .dropdown('change values', promotions.map(promotion => { return { -- 2.49.0 From 7b11fdc6cef02f6ce343f761d1e793dbcee1e58d Mon Sep 17 00:00:00 2001 From: Juan Pablo Vial Date: Mon, 22 Sep 2025 14:16:52 -0300 Subject: [PATCH 08/10] Getter --- app/resources/views/ventas/reservations.blade.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/resources/views/ventas/reservations.blade.php b/app/resources/views/ventas/reservations.blade.php index 473dd9e..3d61aa0 100644 --- a/app/resources/views/ventas/reservations.blade.php +++ b/app/resources/views/ventas/reservations.blade.php @@ -293,7 +293,7 @@ return this } } - columnsData() { + get columnsData() { return this.reservations.map(reservation => { const date = new Date(Date.parse(reservation.date) + 24 * 60 * 60 * 1000) return { @@ -314,7 +314,7 @@ } const tbody = this.component.querySelector('tbody') tbody.innerHTML = '' - this.columnsData().forEach(column => { + this.columnsData.forEach(column => { const tr = document.createElement('tr') const contents = [] const id = column.id @@ -409,8 +409,8 @@ super({component_id, formatters}) } - columnsData() { - const data = super.columnsData(); + get columnsData() { + const data = super.columnsData; return data.map(row => { delete(row['valida']) return row @@ -472,8 +472,8 @@ super({component_id, formatters}) } - columnsData() { - const data = super.columnsData() + get columnsData() { + const data = super.columnsData return this.reservations.map((reservation, idx) => { data[idx]['estado'] = this.mapState(reservation.current_state) data[idx]['comentarios'] = reservation.comments ?? '' -- 2.49.0 From d171a61b8ae26f7a94c0f2a23eeeed367fcee6a6 Mon Sep 17 00:00:00 2001 From: Juan Pablo Vial Date: Mon, 22 Sep 2025 15:28:54 -0300 Subject: [PATCH 09/10] Comment whe rejecting or canceling reservation --- .../views/ventas/reservations.blade.php | 34 ++-- .../reservations/modal/comment.blade.php | 157 ++++++++++++++++++ 2 files changed, 176 insertions(+), 15 deletions(-) create mode 100644 app/resources/views/ventas/reservations/modal/comment.blade.php diff --git a/app/resources/views/ventas/reservations.blade.php b/app/resources/views/ventas/reservations.blade.php index 3d61aa0..92d46c9 100644 --- a/app/resources/views/ventas/reservations.blade.php +++ b/app/resources/views/ventas/reservations.blade.php @@ -102,6 +102,7 @@ @include('ventas.reservations.modal.add') + @include('ventas.reservations.modal.comment') @endsection @push('page_styles') @@ -376,6 +377,9 @@ hide() { this.component.style.display = 'none' } + find(id) { + return this.reservations.find(reservation => reservation.id === parseInt(id)) + } send = { get(url) { return APIClient.fetch(url).then(response => response.json()).then(json => { @@ -392,14 +396,6 @@ } }) }, - delete(url) { - const method = 'delete' - return APIClient.fetch(url, {method}).then(response => response.json()).then(json => { - if (json.success) { - window.location.reload() - } - }) - } } actions = {} } @@ -436,9 +432,12 @@ }, remove: event => { event.preventDefault() - const id = event.currentTarget.dataset.id - const url = `{{ $urls->api }}/ventas/reservation/${id}/remove` - this.send.delete(url) + const reservation_id = event.currentTarget.dataset.id + const url = `{{ $urls->api }}/ventas/reservation/${reservation_id}/remove` + const method = 'delete' + const action = 'Cancelar' + const reservation_data = this.find(reservation_id) + reservations.components.modals.comment.show({reservation_id, action, url, method, reservation_data}) return false } } @@ -459,9 +458,12 @@ }, reject: event => { event.preventDefault() - const id = event.currentTarget.dataset.id - const url = `{{ $urls->api }}/ventas/reservation/${id}/reject` - this.send.get(url) + const reservation_id = event.currentTarget.dataset.id + const url = `{{ $urls->api }}/ventas/reservation/${reservation_id}/reject` + const method = 'delete' + const action = 'Rechazar' + const reservation_data = this.find(reservation_id) + reservations.components.modals.comment.show({reservation_id, action, url, method, reservation_data}) return false } } @@ -505,7 +507,8 @@ rejected: null }, modals: { - add: null + add: null, + comment: null, } }, display: { @@ -645,6 +648,7 @@ this.show.projects() this.components.modals.add = new AddReservationModal(configuration.ids.projects) + this.components.modals.comment = new CommentModal() const project_id = {{ $project_id ?? 'null' }}; if (project_id !== null) { diff --git a/app/resources/views/ventas/reservations/modal/comment.blade.php b/app/resources/views/ventas/reservations/modal/comment.blade.php new file mode 100644 index 0000000..55eb4fb --- /dev/null +++ b/app/resources/views/ventas/reservations/modal/comment.blade.php @@ -0,0 +1,157 @@ +
+ + + + + + + + + + + + + + +
Unidades
Cliente
Fecha
+
+ + +
+ +
+
+
+ Cancelar +
+
+ Comentar y Guardar +
+
+
+ +@push('page_scripts') + +@endpush -- 2.49.0 From 496dca9133737b9387247da06af5a74f9d801332 Mon Sep 17 00:00:00 2001 From: Juan Pablo Vial Date: Tue, 23 Sep 2025 15:37:45 -0300 Subject: [PATCH 10/10] Fetch reservation with unit --- .../Controller/API/Ventas/Reservations.php | 4 +- app/src/Repository/Venta/Reservation.php | 46 +++++++++++++++++-- app/src/Service/Venta/Reservation.php | 2 +- 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/app/src/Controller/API/Ventas/Reservations.php b/app/src/Controller/API/Ventas/Reservations.php index 607be0f..6d92b97 100644 --- a/app/src/Controller/API/Ventas/Reservations.php +++ b/app/src/Controller/API/Ventas/Reservations.php @@ -71,9 +71,9 @@ class Reservations $output['errors'] []= $this->parseError($exception); }*/ - if (count($input['reservations']) === count($output['reservations'])) { + /*if (count($input['reservations']) === count($output['reservations'])) { $output['success'] = true; - } + }*/ return $this->withJson($response, $output); } diff --git a/app/src/Repository/Venta/Reservation.php b/app/src/Repository/Venta/Reservation.php index bd457f4..a59feaa 100644 --- a/app/src/Repository/Venta/Reservation.php +++ b/app/src/Repository/Venta/Reservation.php @@ -92,18 +92,57 @@ class Reservation extends Common\Ideal\Repository /** * @param int $buyer_rut + * @param int $unit_id * @param DateTimeInterface $date * @return Model\Venta\Reservation - * @throws Common\Implement\Exception\EmptyResult + * @throws EmptyResult */ - public function fetchByBuyerAndDate(int $buyer_rut, DateTimeInterface $date): Model\Venta\Reservation + public function fetchByBuyerAndUnitAndDate(int $buyer_rut, int $unit_id, DateTimeInterface $date): Model\Venta\Reservation + { + $query = $this->connection->getQueryBuilder() + ->select('a.*') + ->from('reservations a') + ->joined('INNER JOIN reservation_details rd ON a.id = rd.reservation_id') + ->where('a.buyer_rut = :buyer_rut AND rd.unit_id = :unit_id AND a.date >= :date'); + return $this->fetchOne($query, ['buyer_rut' => $buyer_rut, 'unit_id' => $unit_id, 'date' => $date->sub(new DateInterval('P10D'))->format('Y-m-d')]); + } + + /** + * @param int $buyer_rut + * @param int $project_id + * @param DateTimeInterface $date + * @return array + * @throws EmptyResult + */ + public function fetchByBuyerAndProjectAndDate(int $buyer_rut, int $project_id, DateTimeInterface $date): array + { + $query = $this->connection->getQueryBuilder() + ->select() + ->from('reservations') + ->where('buyer_rut = :buyer_rut AND project_id = :project_id AND date >= :date'); + return $this->fetchMany($query, ['buyer_rut' => $buyer_rut, 'project_id' => $project_id, 'date' => $date->sub(new DateInterval('P10D'))->format('Y-m-d')]); + } + + /** + * @param int $buyer_rut + * @param DateTimeInterface $date + * @return array + * @throws EmptyResult + */ + public function fetchByBuyerAndDate(int $buyer_rut, DateTimeInterface $date): array { $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')]); + return $this->fetchMany($query, ['buyer_rut' => $buyer_rut, 'date' => $date->sub(new DateInterval('P10D'))->format('Y-m-d')]); } + + /** + * @param int $project_id + * @return array + * @throws EmptyResult + */ public function fetchByProject(int $project_id): array { $query = $this->connection->getQueryBuilder() @@ -145,6 +184,7 @@ class Reservation extends Common\Ideal\Repository return $this->fetchMany($query, ['project_id' => $project_id, 'state' => $state]); } + /** * @param int $project_id * @return array diff --git a/app/src/Service/Venta/Reservation.php b/app/src/Service/Venta/Reservation.php index 6326cca..f6d3141 100644 --- a/app/src/Service/Venta/Reservation.php +++ b/app/src/Service/Venta/Reservation.php @@ -123,7 +123,7 @@ class Reservation extends Ideal\Service\API $date = new DateTimeImmutable($data['date']); } catch (DateMalformedStringException) {} try { - $reservation = $this->reservationRepository->fetchByBuyerAndDate($data['buyer_rut'], $date); + $reservation = $this->reservationRepository->fetchByBuyerAndUnitAndDate($data['buyer_rut'], (int) $data['units'][0], $date); if (array_key_exists('broker_rut', $data) and $data['broker_rut'] !== '') { try { -- 2.49.0