Nueva estructura
This commit is contained in:
@ -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()
|
||||
]);
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace Incoviba\Repository\Venta;
|
||||
|
||||
use PDO;
|
||||
use DateTimeImmutable;
|
||||
use Incoviba\Common\Define;
|
||||
use Incoviba\Common\Ideal;
|
||||
@ -11,7 +12,8 @@ use Incoviba\Repository;
|
||||
|
||||
class Factura extends Ideal\Repository
|
||||
{
|
||||
public function __construct(Implement\Connection $connection, protected Repository\Venta $ventaRepository)
|
||||
public function __construct(Implement\Connection $connection, protected Repository\Venta $ventaRepository,
|
||||
protected Repository\Persona $personaRepository, protected Unidad $unidadRepository)
|
||||
{
|
||||
parent::__construct($connection);
|
||||
$this->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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user