diff --git a/app/common/Implement/Database/Query/Select.php b/app/common/Implement/Database/Query/Select.php index 0f7a88b..aa4874a 100644 --- a/app/common/Implement/Database/Query/Select.php +++ b/app/common/Implement/Database/Query/Select.php @@ -126,7 +126,7 @@ class Select extends Ideal\Query implements Define\Query\Select } protected function addCondition(string $condition): Select { - if (!isset($this->coditions)) { + if (!isset($this->conditions)) { $this->conditions = []; } $this->conditions []= $condition; diff --git a/app/resources/views/contabilidad/cartolas/import.blade.php b/app/resources/views/contabilidad/cartolas/import.blade.php index 365f734..e840d50 100644 --- a/app/resources/views/contabilidad/cartolas/import.blade.php +++ b/app/resources/views/contabilidad/cartolas/import.blade.php @@ -42,6 +42,7 @@ RUT Nombres Identificador + @@ -179,9 +180,10 @@ } class Movimiento { props - constructor({sociedad, fecha, glosa, cargo, abono, saldo, categoria, detalle, centro_costo, rut, nombres, - identificador, relacionado, relacionadoType}) { + constructor({id, sociedad, fecha, glosa, cargo, abono, saldo, categoria, detalle, centro_costo, rut, nombres, + identificador, relacionado, relacionadoType, nuevo = false, obsoleto = false}) { this.props = { + id, sociedad, fecha, glosa, @@ -195,7 +197,9 @@ nombres, identificador, relacionado, - relacionadoType + relacionadoType, + nuevo, + obsoleto } } draw({formatters}) { @@ -210,8 +214,17 @@ nombre = this.props.nombres } } + let edit = '' + let color = '' + if (this.props.nuevo) { + color = ' class="green"' + } + if (this.props.obsoleto) { + color = ' class="red"' + edit = `` + } return [ - '', + ``, `${this.props.sociedad.sigla}`, `${formatters.date.format(fecha)}`, `${this.props.glosa}`, @@ -224,6 +237,7 @@ `${this.props.rut ?? ''}`, `${nombre}`, `${this.props.identificador ?? ''}`, + `${edit}`, '' ].join("\n") } @@ -250,6 +264,22 @@ } } }, + remove() { + return { + movimiento: id => { + const url = `{{$urls->api}}/contabilidad/movimiento/${id}` + const method = 'delete' + APIClient.fetch(url, {method}).then(response => { + if (!response.status) { + return + } + const index = this.data.movimientos.findIndex(movimiento => movimiento.id === response.movimiento.id) + this.data.movimientos.splice(index, 1) + this.draw().movimientos() + }) + } + } + }, draw() { return { form: () => { @@ -269,6 +299,12 @@ tbody.append(movimiento.draw({formatters: this.formatters})) }) table.show() + Object.values(document.getElementsByClassName('remove_movimiento')).forEach(element => { + element.addEventListener('click', clickEvent => { + const id = clickEvent.currentTarget.dataset['id'] + this.remove().movimiento(id) + }) + }) } } }, @@ -293,7 +329,7 @@ }) }) - fetchAPI(url, {method, body}).then(response => { + APIClient.fetch(url, {method, body}).then(response => { if (!response) { return } diff --git a/app/src/Repository/Contabilidad/Movimiento.php b/app/src/Repository/Contabilidad/Movimiento.php index a59f1a9..84313a6 100644 --- a/app/src/Repository/Contabilidad/Movimiento.php +++ b/app/src/Repository/Contabilidad/Movimiento.php @@ -99,4 +99,18 @@ class Movimiento extends Ideal\Repository } return $this->fetchMany($query, [$sociedad_rut, $mes->format('Y-m-01'), $mes->format('Y-m-t')]); } + public function fetchMissingInDateRange(int $cuenta_id, DateTimeInterface $startDate, DateTimeInterface $endDate, array $idList = []): array + { + $query = $this->connection->getQueryBuilder() + ->select() + ->from($this->getTable()) + ->where('cuenta_id = ? AND fecha BETWEEN ? AND ?'); + if (count($idList) > 0) { + $idString = implode(', ', array_map(function(int $id) { + return $this->connection->getPDO()->quote($id); + }, $idList)); + $query->where("id NOT IN ({$idString})"); + } + return $this->fetchMany($query, [$cuenta_id, $startDate->format('Y-m-d'), $endDate->format('Y-m-d')]); + } } diff --git a/app/src/Service/Contabilidad/Cartola.php b/app/src/Service/Contabilidad/Cartola.php index 61a29f4..c525580 100644 --- a/app/src/Service/Contabilidad/Cartola.php +++ b/app/src/Service/Contabilidad/Cartola.php @@ -91,12 +91,16 @@ class Cartola extends Service $cartola = $this->buildCartola($cuenta, $fecha, $cartolaData); return compact('cartola', 'movimientos'); } + public function import(int $cuenta_id, UploadedFileInterface $file): array { $cuenta = $this->cuentaRepository->fetchById($cuenta_id); $movimientos = $this->process($cuenta->banco, $file); - foreach ($movimientos as $dataMovimiento) { + $inmobiliaria = $cuenta->inmobiliaria; + + $addedMovimientos = []; + foreach ($movimientos as &$dataMovimiento) { $dataMovimiento['cuenta_id'] = $cuenta->id; if (array_key_exists('centro_costo', $dataMovimiento) and $dataMovimiento['centro_costo'] !== 0) { $dataMovimiento['centro_costo_id'] = $dataMovimiento['centro_costo']; @@ -112,10 +116,21 @@ class Cartola extends Service $dataMovimiento['digito'] = $ruts[0]['digito']; } } - $this->movimientoService->add($dataMovimiento); + try { + $movimiento = $this->movimientoRepository + ->fetchByCuentaAndFechaAndGlosaAndCargoAndAbonoAndSaldo($dataMovimiento['cuenta_id'], $dataMovimiento['fecha'], + $dataMovimiento['glosa'], $dataMovimiento['cargo'] ?? 0, + $dataMovimiento['abono'] ?? 0, $dataMovimiento['saldo']); + } catch (Exception\EmptyResult) { + $movimiento = $this->movimientoService->add($dataMovimiento); + $dataMovimiento['nuevo'] = true; + } + $dataMovimiento['id'] = $movimiento->id; + $dataMovimiento['sociedad'] = $inmobiliaria; + $addedMovimientos []= $movimiento->id; } $fechas = array_unique(array_map(function($movimiento) { - return $movimiento['fecha']; + return $movimiento['fecha']->format('Y-m-d'); }, $movimientos)); foreach ($fechas as $dia) { try { @@ -140,11 +155,25 @@ class Cartola extends Service $this->buildCartola($cuenta, new DateTimeImmutable($dia), $cartolaData); } - $inmobiliaria = $cuenta->inmobiliaria; - return array_map(function($movimiento) use ($inmobiliaria) { - $movimiento['sociedad'] = $inmobiliaria; + $startDate = new DateTimeImmutable(min($fechas)); + $endDate = new DateTimeImmutable(max($fechas)); + $movimientosFaltantes = $this->movimientoService->findMissing($cuenta, $addedMovimientos, $startDate, $endDate); + $movimientosObsoletos = []; + if (count($movimientosFaltantes) > 0) { + $movimientosObsoletos = array_map(function(&$movimiento) { + $arr = (array) $movimiento; + $arr['sociedad'] = $movimiento->cuenta->inmobiliaria; + $arr['obsoleto'] = true; + return $arr; + }, $movimientosFaltantes); + } + + return array_map(function($movimiento) { + if (is_a($movimiento['fecha'], DateTimeInterface::class)) { + $movimiento['fecha'] = $movimiento['fecha']->format('Y-m-d'); + } return $movimiento; - }, $movimientos); + }, array_merge($movimientos, $movimientosObsoletos)); } public function check(): array { diff --git a/app/src/Service/Contabilidad/Movimiento.php b/app/src/Service/Contabilidad/Movimiento.php index 8e4ee2e..97aee84 100644 --- a/app/src/Service/Contabilidad/Movimiento.php +++ b/app/src/Service/Contabilidad/Movimiento.php @@ -85,6 +85,14 @@ class Movimiento extends Service { return $this->detalleService->findRut($rut); } + public function findMissing(Model\Inmobiliaria\Cuenta $cuenta, array $currentIdList, DateTimeInterface $startDate, DateTimeInterface $endDate): array + { + try { + return $this->movimientoRepository->fetchMissingInDateRange($cuenta->id, $startDate, $endDate, $currentIdList); + } catch (EmptyResult) { + return []; + } + } public function process(Model\Contabilidad\Movimiento $movimiento): Model\Contabilidad\Movimiento {