From 5f31bff6e5b8e8e7683cfbc91b2b041eba3d92b1 Mon Sep 17 00:00:00 2001 From: Juan Pablo Vial Date: Thu, 16 Jan 2025 19:36:28 -0300 Subject: [PATCH] Nueva estructura --- app/src/Model/Venta/Factura.php | 112 ++++++++++-------- app/src/Repository/Venta/Factura.php | 171 +++++++++++++++++---------- 2 files changed, 172 insertions(+), 111 deletions(-) diff --git a/app/src/Model/Venta/Factura.php b/app/src/Model/Venta/Factura.php index cb0b259..e1058c0 100644 --- a/app/src/Model/Venta/Factura.php +++ b/app/src/Model/Venta/Factura.php @@ -8,30 +8,16 @@ use Incoviba\Model; class Factura extends Ideal\Model { public Model\Venta $venta; + public int $index; public float $proporcion; - public string $emisorRut; - public string $emisorNombre; - public string $emisorDireccion; - public string $receptorRut; - public string $receptorNombre; - public string $receptorDireccion; - public string $receptorComuna; + public Model\Persona $cliente; + public DateTimeInterface $fecha; - public array $unidades; - public int $detalleBase; - public int $detalleTerreno; - public int $detalleNeto; - public int $detalleIva; - public int $detalleBruto; - public float $detalleDescuento; - public int $detalleTotal; - public int $totalNeto; - public int $totalExento; - public int $totalIva; - public int $totalTotal; - public DateTimeInterface $fechaUF; - public float $valorUF; + public array $unidades; // [[unidad, descripcion, precio, prorrateo]] + public int $terreno; + public object $uf; // [fecha, valor] + public object $ipc; // [fecha, valor] protected array $estados; public function estados(): array @@ -42,6 +28,52 @@ class Factura extends Ideal\Model return $this->estados ?? []; } + public function total(): int + { + return round($this->venta->valor * $this->uf->valor * $this->proporcion); + } + public function bruto(): int + { + return round($this->total() - $this->terreno * $this->proporcion); + } + public function iva(): int + { + return round($this->bruto() / 1.19 * .19); + } + public function neto(): int + { + return round($this->bruto() / 1.19); + } + public function base(): int + { + return $this->neto() + $this->terreno * $this->proporcion; + } + public function detalle(): array + { + return [ + 'base' => $this->base(), + 'terreno' => $this->terreno * $this->proporcion, + 'neto' => $this->neto(), + 'iva' => $this->iva(), + 'bruto' => $this->bruto(), + 'total' => $this->total(), + 'descuento' => array_reduce($this->unidades, function($sum, $unidad) { + return $sum + $unidad->prorrateo * $this->proporcion; + }) + ]; + } + public function totales(): array + { + return [ + 'neto' => array_reduce($this->unidades, function($sum, $unidad) { + return $sum + $unidad->precio * $this->proporcion; + }), + 'exento' => $this->terreno * $this->proporcion, + 'iva' => $this->iva(), + 'total' => $this->total() + ]; + } + public function jsonSerialize(): mixed { return array_merge(parent::jsonSerialize(), [ @@ -49,37 +81,23 @@ class Factura extends Ideal\Model 'index' => $this->index, 'proporcion' => $this->proporcion, 'emisor' => [ - 'rut' => $this->emisorRut, - 'nombre' => $this->emisorNombre, - 'direccion' => $this->emisorDireccion + 'rut' => $this->venta->proyecto()->inmobiliaria()->rut(), + 'nombre' => $this->venta->proyecto()->inmobiliaria()->nombreCompleto(), + 'direccion' => $this->venta->proyecto()->direccion(), + 'comuna' => $this->venta->proyecto()->direccion()->comuna->descripcion ], 'receptor' => [ - 'rut' => $this->receptorRut, - 'nombre' => $this->receptorNombre, - 'direccion' => $this->receptorDireccion, - 'comuna' => $this->receptorComuna + 'rut' => $this->cliente->rutCompleto(), + 'nombre' => $this->cliente->nombreCompleto(), + 'direccion' => $this->cliente->datos()->direccion->simple(), + 'comuna' => $this->cliente->datos()->direccion->comuna->descripcion ], 'fecha' => $this->fecha->format('Y-m-d'), 'unidades' => $this->unidades, - 'detalle' => [ - 'base' => $this->detalleBase, - 'terreno' => $this->detalleTerreno, - 'neto' => $this->detalleNeto, - 'iva' => $this->detalleIva, - 'bruto' => $this->detalleBruto, - 'descuento' => $this->detalleDescuento, - 'total' => $this->detalleTotal - ], - 'total' => [ - 'neto' => $this->totalNeto, - 'exento' => $this->totalExento, - 'iva' => $this->totalIva, - 'total' => $this->totalTotal - ], - 'uf' => [ - 'fecha' => $this->fechaUF->format('Y-m-d'), - 'valor' => $this->valorUF - ], + 'detalle' => $this->detalle(), + 'total' => $this->totales(), + 'uf' => $this->uf, + 'ipc' => $this->ipc, 'estados' => $this->estados() ]); } diff --git a/app/src/Repository/Venta/Factura.php b/app/src/Repository/Venta/Factura.php index 0bd8716..8b529ec 100644 --- a/app/src/Repository/Venta/Factura.php +++ b/app/src/Repository/Venta/Factura.php @@ -1,6 +1,7 @@ setTable('facturas'); @@ -19,89 +21,130 @@ class Factura extends Ideal\Repository public function create(?array $data = null): Model\Venta\Factura { - $map = (new Implement\Repository\MapperParser(['index'])) + $map = (new Implement\Repository\MapperParser(['index', 'proporcion'])) ->register('venta_id', (new Implement\Repository\Mapper()) ->setProperty('venta') ->setFunction(function($data) { return $this->ventaRepository->fetchById($data['venta_id']); + })) + ->register('cliente_rut', (new Implement\Repository\Mapper()) + ->setProperty('cliente') + ->setFunction(function($data) { + return $this->personaRepository->fetchById($data['cliente_rut']); })); $factura = $this->parseData(new Model\Venta\Factura(), $data, $map); - $json = json_decode($data['data']); - $factura->proporcion = $json->proporcion; - $factura->emisorRut = $json->emisor->rut; - $factura->emisorNombre = $json->emisor->nombre; - $factura->emisorDireccion = $json->emisor->direccion; - $factura->receptorRut = $json->receptor->rut; - $factura->receptorNombre = $json->receptor->nombre; - $factura->receptorDireccion = $json->receptor->direccion; - $factura->receptorComuna = $json->receptor->comuna; - $factura->fecha = new DateTimeImmutable($json->fecha); - $factura->unidades = $json->unidades; - $factura->detalleBase = $json->detalle->base; - $factura->detalleTerreno = $json->detalle->terreno; - $factura->detalleNeto = $json->detalle->neto; - $factura->detalleIva = $json->detalle->iva; - $factura->detalleBruto = $json->detalle->bruto; - $factura->detalleDescuento = $json->detalle->descuento; - $factura->detalleTotal = $json->detalle->total; - $factura->totalNeto = $json->total->neto; - $factura->totalExento = $json->total->exento; - $factura->totalIva = $json->total->iva; - $factura->totalTotal = $json->total->total; - $factura->fechaUF = new DateTimeImmutable($json->uf->fecha); - $factura->valorUF = $json->uf->valor; + return $this->createDatos($factura); + } + public function createDatos(Model\Venta\Factura &$factura): Model\Venta\Factura + { + try { + $result = $this->getDatos($factura->venta->id); + $factura->fecha = new DateTimeImmutable($result['fecha']); + $factura->unidades = array_map(function($datos) { + $unidad = $this->unidadRepository->fetchById($datos->unidad_id); + return (object) [ + 'unidad' => $unidad, + 'descripcion' => implode(' ', [ucwords($unidad->proyectoTipoUnidad->tipoUnidad->descripcion), $unidad->descripcion]), + 'precio' => $datos->precio, + 'prorrateo' => $datos->prorrateo + ]; + }, json_decode($result['unidades'])); + $factura->terreno = $result['terreno']; + $factura->uf = json_decode($result['uf']); + $factura->ipc = json_decode($result['ipc']); + } catch (EmptyResult) {} + return $factura; } + protected function getDatos(int $venta_id): array + { + $query = $this->connection->getQueryBuilder() + ->select() + ->from('venta_datos_facturas') + ->where('venta_id = :venta_id'); + $result = $this->connection->execute($query, ['venta_id' => $venta_id])->fetch(PDO::FETCH_ASSOC); + if ($result === false) { + throw new EmptyResult($query); + } + return $result; + } public function save(Define\Model $model): Model\Venta\Factura { $model->id = $this->saveNew([ 'venta_id', 'index', - 'data' + 'proporcion', + 'cliente_rut' ], [ $model->venta->id, $model->index, - json_encode([ - 'proporcion' => $model->proporcion, - 'emisor' => [ - 'rut' => $model->emisorRut, - 'nombre' => $model->emisorNombre, - 'direccion' => $model->emisorDireccion - ], - 'receptor' => [ - 'rut' => $model->receptorRut, - 'nombre' => $model->receptorNombre, - 'direccion' => $model->receptorDireccion, - 'comuna' => $model->receptorComuna - ], - 'fecha' => $model->fecha->format('Y-m-d'), - 'unidades' => $model->unidades, - 'detalle' => [ - 'base' => $model->detalleBase, - 'terreno' => $model->detalleTerreno, - 'neto' => $model->detalleNeto, - 'iva' => $model->detalleIva, - 'bruto' => $model->detalleBruto, - 'descuento' => $model->detalleDescuento, - 'total' => $model->detalleTotal - ], - 'total' => [ - 'neto' => $model->totalNeto, - 'exento' => $model->totalExento, - 'iva' => $model->totalIva, - 'total' => $model->totalTotal - ], - 'uf' => [ - 'fecha' => $model->fechaUF->format('Y-m-d'), - 'valor' => $model->valorUF - ] - ]) + $model->proporcion, + $model->cliente->rut ]); - return $model; + return $this->saveDatos($model); + } + protected function saveDatos(Model\Venta\Factura $factura): Model\Venta\Factura + { + try { + $this->getDatos($factura->venta->id); + } catch (EmptyResult) { + $query = $this->connection->getQueryBuilder() + ->insert() + ->into('venta_datos_facturas') + ->values([ + 'venta_id' => $factura->venta->id, + 'index' => $factura->index, + 'proporcion' => $factura->proporcion, + 'unidades' => json_encode(array_map(function($unidad) { + return [ + 'unidad_id' => $unidad->unidad->id, + 'precio' => $unidad->precio, + 'prorrateo' => $unidad->prorrateo + ]; + }, $factura->unidades)), + 'terreno' => $factura->terreno, + 'uf' => json_encode($factura->uf), + 'ipc' => json_encode($factura->ipc) + ]); + $this->connection->execute($query); + } + + return $factura; } public function edit(Define\Model $model, array $new_data): Model\Venta\Factura { - return $this->update($model, ['venta_id', 'index', 'data'], $new_data); + $model = $this->editDatos($model, $new_data); + return $this->update($model, ['venta_id', 'index', 'proporcion', 'cliente_rut'], $new_data); + } + protected function editDatos(Model\Venta\Factura $factura, array $new_data): Model\Venta\Factura + { + $dataFields = [ + 'fecha', + 'unidades', + 'terreno', + 'uf', + 'ipc' + ]; + $fields = []; + $values = []; + foreach ($dataFields as $field) { + if (isset($new_data[$field])) { + $fields[] = "{$field} = ?"; + $values[] = is_array($new_data[$field]) ? json_encode($new_data[$field]) : $new_data[$field]; + } + } + if (count($fields) === 0) { + return $factura; + } + + $query = $this->connection->getQueryBuilder() + ->update('venta_datos_facturas') + ->set($fields) + ->where('venta_id = ?') + ->limit(1); + $this->connection->execute($query, array_merge($values, [$factura->venta->id])); + + return $this->fetchById($factura->id); } /**