diff --git a/app/resources/routes/api/ventas/reservations.php b/app/resources/routes/api/ventas/reservations.php
index d0dedcd..31ce261 100644
--- a/app/resources/routes/api/ventas/reservations.php
+++ b/app/resources/routes/api/ventas/reservations.php
@@ -12,7 +12,10 @@ $app->group('/reservations', function($app) {
});
$app->post('/reservation/add[/]', [Reservations::class, 'addOne']);
$app->group('/reservation/{reservation_id}', function($app) {
+ $app->get('/approve[/]', [Reservations::class, 'approve']);
+ $app->get('/reject[/]', [Reservations::class, 'reject']);
$app->post('/edit[/]', [Reservations::class, 'edit']);
+ $app->delete('/remove[/]', [Reservations::class, 'remove']);
$app->delete('[/]', [Reservations::class, 'delete']);
$app->get('[/]', [Reservations::class, 'get']);
});
diff --git a/app/resources/views/ventas/reservations.blade.php b/app/resources/views/ventas/reservations.blade.php
index a5e52c6..a7f2cc4 100644
--- a/app/resources/views/ventas/reservations.blade.php
+++ b/app/resources/views/ventas/reservations.blade.php
@@ -257,7 +257,6 @@
date: null,
ufs: null
}
-
columnNames = []
reservations = []
@@ -294,10 +293,9 @@
return this
}
}
-
columnsData() {
return this.reservations.map(reservation => {
- const date = new Date(Date.parse(reservation.fecha) + 24 * 60 * 60 * 1000)
+ const date = new Date(Date.parse(reservation.date) + 24 * 60 * 60 * 1000)
return {
id: reservation.id,
unidades: reservation.summary,
@@ -309,7 +307,6 @@
}
})
}
-
draw() {
if (this.reservations.length === 0) {
this.empty()
@@ -332,8 +329,9 @@
tbody.appendChild(tr)
})
this.show()
- }
+ this.watch()
+ }
drawActions(id) {
return `
@@ -345,7 +343,23 @@
| `
}
-
+ watch() {
+ if (Object.keys(this.actions).length === 0) {
+ return
+ }
+ const actionNames = Object.keys(this.actions)
+ const tbody = this.component.querySelector('tbody')
+ const trs = tbody.querySelectorAll('tr')
+ trs.forEach(tr => {
+ actionNames.forEach(actionName => {
+ const button = tr.querySelector(`button.${actionName}`)
+ if (!button) {
+ return
+ }
+ button.addEventListener('click', this.actions[actionName].bind(this))
+ })
+ })
+ }
empty() {
const tbody = this.component.querySelector('tbody')
tbody.innerHTML = ''
@@ -356,14 +370,38 @@
this.show()
}
-
show() {
this.component.style.display = this.display.reservations
}
-
hide() {
this.component.style.display = 'none'
}
+ send = {
+ get(url) {
+ return APIClient.fetch(url).then(response => response.json()).then(json => {
+ if (json.success) {
+ window.location.reload()
+ }
+ })
+ },
+ post(url, body) {
+ const method = 'post'
+ return APIClient.fetch(url, {method, body}).then(response => response.json()).then(json => {
+ if (json.success) {
+ window.location.reload()
+ }
+ })
+ },
+ delete(url) {
+ const method = 'delete'
+ return APIClient.fetch(url, {method}).then(response => response.json()).then(json => {
+ if (json.success) {
+ window.location.reload()
+ }
+ })
+ }
+ }
+ actions = {}
}
class ActiveReservations extends Reservations {
@@ -378,7 +416,6 @@
return row
})
}
-
drawActions(id) {
return `
@@ -390,12 +427,44 @@
| `
}
+ actions = {
+ edit: event => {
+ event.preventDefault()
+ const id = event.currentTarget.dataset.id
+ reservations.components.modals.edit.load(id)
+ return false
+ },
+ remove: event => {
+ event.preventDefault()
+ const id = event.currentTarget.dataset.id
+ const url = `{{ $urls->api }}/ventas/reservation/${id}/remove`
+ this.send.delete(url)
+ return false
+ }
+ }
}
class PendingReservations extends Reservations {
constructor({component_id, formatters = {date, ufs}}) {
super({component_id, formatters})
}
+
+ actions = {
+ approve: event => {
+ event.preventDefault()
+ const id = event.currentTarget.dataset.id
+ const url = `{{ $urls->api }}/ventas/reservation/${id}/approve`
+ this.send.get(url)
+ return false
+ },
+ reject: event => {
+ event.preventDefault()
+ const id = event.currentTarget.dataset.id
+ const url = `{{ $urls->api }}/ventas/reservation/${id}/reject`
+ this.send.get(url)
+ return false
+ }
+ }
}
class RejectedReservations extends Reservations {
@@ -411,10 +480,10 @@
return data[idx]
})
}
-
drawActions(id) {
return ''
}
+ watch() {}
}
const reservations = {
diff --git a/app/src/Controller/API/Ventas/Reservations.php b/app/src/Controller/API/Ventas/Reservations.php
index 87ef6b4..607be0f 100644
--- a/app/src/Controller/API/Ventas/Reservations.php
+++ b/app/src/Controller/API/Ventas/Reservations.php
@@ -181,4 +181,33 @@ class Reservations
} catch (ServiceAction\Read) {}
return $this->withJson($response, $output);
}
+
+ public function approve(ServerRequestInterface $request, ResponseInterface $response,
+ Service\Venta\Reservation $reservationService, int $reservation_id): ResponseInterface
+ {
+ $output = [
+ 'reservation_id' => $reservation_id,
+ 'success' => false,
+ ];
+ try {
+ $reservation = $reservationService->get($reservation_id);
+ $reservationService->approve($reservation);
+ $output['success'] = true;
+ } catch (ServiceAction\Read | ServiceAction\Update) {}
+ return $this->withJson($response, $output);
+ }
+ public function reject(ServerRequestInterface $request, ResponseInterface $response,
+ Service\Venta\Reservation $reservationService, int $reservation_id): ResponseInterface
+ {
+ $output = [
+ 'reservation_id' => $reservation_id,
+ 'success' => false,
+ ];
+ try {
+ $reservation = $reservationService->get($reservation_id);
+ $reservationService->reject($reservation);
+ $output['success'] = true;
+ } catch (ServiceAction\Read | ServiceAction\Update) {}
+ return $this->withJson($response, $output);
+ }
}
diff --git a/app/src/Model/Venta/Reservation/State/Type.php b/app/src/Model/Venta/Reservation/State/Type.php
index 352b72d..96d60e5 100644
--- a/app/src/Model/Venta/Reservation/State/Type.php
+++ b/app/src/Model/Venta/Reservation/State/Type.php
@@ -7,6 +7,7 @@ enum Type: int
case ACTIVE = 1;
case PROMISED = 2;
case REJECTED = -1;
+ case CANCELLED = -2;
public function jsonSerialize(): array
{
diff --git a/app/src/Repository/Venta/Reservation.php b/app/src/Repository/Venta/Reservation.php
index bb6cdd9..45f005f 100644
--- a/app/src/Repository/Venta/Reservation.php
+++ b/app/src/Repository/Venta/Reservation.php
@@ -134,11 +134,10 @@ class Reservation extends Common\Ideal\Repository
->joined("INNER JOIN ({$sub1}) er0 ON er0.id = er1.id");
$query = $this->connection->getQueryBuilder()
- ->select()
- ->from('reservations')
- ->joined("INNER JOIN ({$sub2}) er ON er.reservation_id = reservations.id")
- ->where('project_id = :project_id AND er.type = :state');
-
+ ->select('a.*')
+ ->from("{$this->getTable()} a")
+ ->joined("INNER JOIN ({$sub2}) er ON er.reservation_id = a.id")
+ ->where('a.project_id = :project_id AND er.type = :state');
return $this->fetchMany($query, ['project_id' => $project_id,
'state' => $state]);
}
@@ -178,7 +177,10 @@ class Reservation extends Common\Ideal\Repository
public function fetchRejected(int $project_id): array
{
try {
- return $this->fetchState($project_id, Model\Venta\Reservation\State\Type::REJECTED->value);
+ return [
+ ...$this->fetchState($project_id, Model\Venta\Reservation\State\Type::REJECTED->value),
+ ...$this->fetchState($project_id, Model\Venta\Reservation\State\Type::CANCELLED->value)
+ ];
} catch (InvalidState $exception) {
throw new Common\Implement\Exception\EmptyResult('Select rejected reservations', $exception);
}
diff --git a/app/src/Service/Venta/Reservation.php b/app/src/Service/Venta/Reservation.php
index 968f76d..a12f442 100644
--- a/app/src/Service/Venta/Reservation.php
+++ b/app/src/Service/Venta/Reservation.php
@@ -132,6 +132,9 @@ class Reservation extends Ideal\Service\API
} catch (ServiceAction\Read) {}
}
} catch (Implement\Exception\EmptyResult) {
+ if (!$this->reservationRepository->getConnection()->getPDO()->inTransaction()) {
+ $this->reservationRepository->getConnection()->getPDO()->beginTransaction();
+ }
$buyerData = [];
foreach ($data as $key => $value) {
if (!str_starts_with($key, 'buyer_')) {
@@ -147,34 +150,38 @@ class Reservation extends Ideal\Service\API
$reservation = $this->reservationRepository->create($reservationData);
$reservation = $this->reservationRepository->save($reservation);
- try {
- $stateType = Model\Venta\Reservation\State\Type::ACTIVE;
- $stateData = [
- 'reservation_id' => $reservation->id,
- 'date' => $data['date'],
- 'type' => $stateType->value,
- ];
- $state = $this->stateRepository->create($stateData);
- $this->stateRepository->save($state);
- } catch (PDOException $exception) {
- $this->logger->warning($exception->getMessage(), ['reservation_id' => $reservation->id, 'exception' => $exception->getTraceAsString()]);
+ $stateType = Model\Venta\Reservation\State\Type::INACTIVE;
+ $stateData = [
+ 'reservation_id' => $reservation->id,
+ 'date' => $data['date'],
+ 'type' => $stateType->value,
+ ];
+ $state = $this->stateRepository->create($stateData);
+ $this->stateRepository->save($state);
+
+ $units = array_combine($data['units'], $data['units_value']);
+ $this->addUnits($reservation, $units);
+
+ if (array_key_exists('broker_rut', $data) and !empty($data['broker_rut'])) {
+ $this->addBroker($reservation, $data['broker_rut']);
+ }
+
+ if (array_key_exists('promotions', $data)) {
+ $this->addPromotions($reservation, $data['promotions']);
+ }
+
+ if ($this->reservationRepository->getConnection()->getPDO()->inTransaction()) {
+ $this->reservationRepository->getConnection()->getPDO()->commit();
}
} catch (PDOException $exception) {
+ $this->logger->warning($exception->getMessage(), ['exception' => $exception->getTraceAsString()]);
+ if ($this->reservationRepository->getConnection()->getPDO()->inTransaction()) {
+ $this->reservationRepository->getConnection()->getPDO()->rollBack();
+ }
throw new ServiceAction\Create(__CLASS__, $exception);
}
}
- $units = array_combine($data['units'], $data['units_value']);
- $this->addUnits($reservation, $units);
-
- if (array_key_exists('broker_rut', $data) and !empty($data['broker_rut'])) {
- $this->addBroker($reservation, $data['broker_rut']);
- }
-
- if (array_key_exists('promotions', $data)) {
- $this->addPromotions($reservation, $data['promotions']);
- }
-
return $this->process($reservation);
}
public function edit(Define\Model $model, array $new_data): Model\Venta\Reservation
@@ -195,6 +202,41 @@ class Reservation extends Ideal\Service\API
throw new ServiceAction\Delete(__CLASS__, $exception);
}
}
+
+ /**
+ * @param Model\Venta\Reservation $reservation
+ * @return void
+ * @throws ServiceAction\Update
+ */
+ public function approve(Model\Venta\Reservation $reservation): void
+ {
+ try {
+ $stateData = [
+ 'reservation_id' => $reservation->id,
+ 'date' => new DateTimeImmutable(),
+ 'type' => Model\Venta\Reservation\State\Type::ACTIVE->value,
+ ];
+ $state = $this->stateRepository->create($stateData);
+ $this->stateRepository->save($state);
+ } catch (PDOException $exception) {
+ throw new ServiceAction\Update(__CLASS__, $exception);
+ }
+ }
+ public function reject(Model\Venta\Reservation $reservation): void
+ {
+ try {
+ $stateData = [
+ 'reservation_id' => $reservation->id,
+ 'date' => new DateTimeImmutable(),
+ 'type' => Model\Venta\Reservation\State\Type::REJECTED->value,
+ ];
+ $state = $this->stateRepository->create($stateData);
+ $this->stateRepository->save($state);
+ } catch (PDOException $exception) {
+ throw new ServiceAction\Update(__CLASS__, $exception);
+ }
+ }
+
protected function process(Define\Model $model): Model\Venta\Reservation
{
$model->addFactory('states', new Implement\Repository\Factory()