diff --git a/app/resources/views/contabilidad/cartolas/diaria.blade.php b/app/resources/views/contabilidad/cartolas/diaria.blade.php index 930198a..9750f1e 100644 --- a/app/resources/views/contabilidad/cartolas/diaria.blade.php +++ b/app/resources/views/contabilidad/cartolas/diaria.blade.php @@ -15,47 +15,6 @@
- {{--
-
- - -
-
- - -
-
- -
-
- - -
-
-
-
- - - -
-
--}}
@@ -99,6 +58,61 @@
+ @endsection @include('layout.head.styles.datatables') @@ -173,27 +187,27 @@ } draw() { return { - form: (form, inmobiliarias, first = false) => { - const fields = $('
').addClass('fields cartola').attr('data-cartola', this.idx) - const inmobiliarias_menu = $('
').addClass('menu') + form: ($form, inmobiliarias, first = false) => { + const $fields = $('
').addClass('fields cartola').attr('data-cartola', this.idx) + const $inmobiliarias_menu = $('
').addClass('menu') inmobiliarias.forEach(inmobiliaria => { - inmobiliarias_menu.append( + $inmobiliarias_menu.append( $('
').addClass('item').attr('data-value', inmobiliaria.rut).html(inmobiliaria.razon) ) }) - const inmobiliarias_dropdown = $('
').addClass('ui search selection dropdown').attr('id', 'inmobiliaria' + this.idx).append( + const $inmobiliarias_dropdown = $('
').addClass('ui search selection dropdown').attr('id', 'inmobiliaria' + this.idx).append( $('').attr('type', 'hidden')//.attr('name', 'inmobiliaria_rut' + this.idx) ).append( $('').addClass('dropdown icon') ).append( $('
').addClass('default text').html('Inmobiliaria') - ).append(inmobiliarias_menu) - fields.append( + ).append($inmobiliarias_menu) + $fields.append( $('
').addClass('six wide field').append( $('').attr('for', 'inmobiliaria' + this.idx).html('Sociedad') - ).append(inmobiliarias_dropdown) + ).append($inmobiliarias_dropdown) ) - const cuentas_dropdown = $('
').addClass('ui search selection dropdown').attr('id', 'cuenta' + this.idx).append( + const $cuentas_dropdown = $('
').addClass('ui search selection dropdown').attr('id', 'cuenta' + this.idx).append( $('').attr('type', 'hidden').attr('name', 'cuenta_id' + this.idx) ).append( $('').addClass('dropdown icon') @@ -202,35 +216,47 @@ ).append( $('
').addClass('menu') ) - fields.append( + $fields.append( $('
').addClass('four wide field').append( $('').html('Banco - Cuenta') - ).append(cuentas_dropdown) + ).append($cuentas_dropdown) ) - const fecha_calendar = $('
').addClass('ui calendar').attr('id', 'fecha' + this.idx).append( + const $fecha_calendar = $('
').addClass('ui calendar').attr('id', 'fecha' + this.idx).append( $('
').addClass('ui left icon input').append( $('').addClass('calendar icon') ).append( $('').attr('type', 'text') ) ) - fields.append( + $fields.append( $('
').addClass('three wide field').append( $('').attr('for', 'fecha' + this.idx).html('Fecha') - ).append(fecha_calendar) + ).append($fecha_calendar) ) - const file_field = $('
').addClass('field').append( - $('').attr('for', 'file' + this.idx).html('Cartola') - ).append( - $('').addClass('ui invisible file input').attr('type', 'file').attr('name', 'file' + this.idx).attr('id', 'file' + this.idx) - ).append( - $('').addClass('ui icon button').attr('for', 'file' + this.idx).append( - $('').addClass('file icon') - ).append('Cargar') + $fields.append( + $('
').addClass('field').append( + $('').html('Cartola') + ).append( + $('').addClass('ui invisible file input').attr('type', 'file').attr('name', 'file' + this.idx).attr('id', 'file' + this.idx) + ).append( + $('').addClass('ui icon button').attr('for', 'file' + this.idx).append( + $('').addClass('file icon') + ).append('Cargar') + ) ) - fields.append(file_field) + const $manual_checkbox = $('
').addClass('ui invisible checkbox').append( + $('').attr('type', 'checkbox').attr('name', 'manual' + this.idx).attr('id', 'manual' + this.idx) + ).append( + $('').addClass('image').attr('for', 'manual' + this.idx).append( + $('').addClass('large orange keyboard icon') + ) + ) + + $fields.append($('
').addClass('field').append( + $('').html('Manual') + ).append($manual_checkbox)) if (!first) { - fields.append( + $fields.append( $('
').addClass('field').append( $('').html('Eliminar') ).append( @@ -243,25 +269,7 @@ ) ) } - form.append(fields) - - inmobiliarias_dropdown.dropdown({ - fireOnInit: true, - onChange: (value, text, $choice) => { - this.inmobiliaria.rut = value - this.inmobiliaria.razon = text - this.get().bancos(value).then(() => { - cuentas_dropdown.dropdown('change values', this.bancos) - }) - }, - }) - cuentas_dropdown.dropdown({ - fireOnInit: true, - onChange: (value, text, $choice) => { - this.cuenta.id = value - this.cuenta.descripcion = text - } - }) + $form.append($fields) const cdo = JSON.parse(JSON.stringify(calendar_date_options)) cdo['initialDate'] = new Date() @@ -270,10 +278,48 @@ this.fecha = date } this.fecha = cdo['initialDate'] - fecha_calendar.calendar(cdo) + + $inmobiliarias_dropdown.dropdown({ + fireOnInit: true, + onChange: (value, text, $choice) => { + this.inmobiliaria.rut = value + this.inmobiliaria.razon = text + this.get().bancos(value).then(() => { + $cuentas_dropdown.dropdown('change values', this.bancos) + }) + }, + }) + $cuentas_dropdown.dropdown({ + fireOnInit: true, + onChange: (value, text, $choice) => { + this.cuenta.id = value + this.cuenta.descripcion = text + } + }) + $fecha_calendar.calendar(cdo) + $manual_checkbox.change(event => { + const $element = $(event.currentTarget) + const status = $element.checkbox('is checked') + const $field = $element.parent().parent() + const $file = $field.find('#file' + this.idx).parent() + if (status) { + $file.find('input').attr('type', 'hidden') + $file.hide() + + manual.data.inmobiliaria = $inmobiliarias_dropdown.dropdown('get text') + manual.data.cuenta = $cuentas_dropdown.dropdown('get text') + const fecha = $fecha_calendar.calendar('get date') + manual.data.fecha = [fecha.getDate(), (fecha.getMonth()+1).toString().padStart(2, '0'), fecha.getFullYear()].join('-') + manual.data.field = this.idx + manual.$modal.modal('show') + return + } + $file.find('input').attr('type', 'file') + $file.show() + }) }, - diferencia: (tbody, dateFormatter, numberFormatter) => { - tbody.append( + diferencia: ($tbody, dateFormatter, numberFormatter) => { + $tbody.append( $('').append( $('').html(this.inmobiliaria.razon) ).append( @@ -289,9 +335,9 @@ ) ) }, - cartola: (tbody, dateFormatter, numberFormatter) => { + cartola: ($tbody, dateFormatter, numberFormatter) => { this.movimientos.forEach((row, idx) => { - tbody.append( + $tbody.append( $('').append( $('').html(this.inmobiliaria.razon) ).append( @@ -402,9 +448,9 @@ Object.values(this.ids.table).forEach(id => $(id).find('tbody').html('')) }, diferencia: () => { - const table = $(this.ids.table.diferencia) - const tbody = table.find('tbody') - tbody.html('') + const $table = $(this.ids.table.diferencia) + const $tbody = $table.find('tbody') + $tbody.html('') const dateFormatter = new Intl.DateTimeFormat('es-CL', { year: 'numeric', month: 'numeric', @@ -412,15 +458,15 @@ }) const numberFormatter = new Intl.NumberFormat('es-CL', {minimumFractionDigits: 0, maximumFractionDigits: 0}) this.data.cartolas.forEach(cartola => { - cartola.draw().diferencia(tbody, dateFormatter, numberFormatter) + cartola.draw().diferencia($tbody, dateFormatter, numberFormatter) }) }, cartola: () => { - const table = $(this.ids.table.base) - table.DataTable().clear() - table.DataTable().destroy() - const tbody = $(this.ids.table.body) - tbody.html('') + const $table = $(this.ids.table.base) + $table.DataTable().clear() + $table.DataTable().destroy() + const $tbody = $(this.ids.table.body) + $tbody.html('') const dateFormatter = new Intl.DateTimeFormat('es-CL', { year: 'numeric', month: 'numeric', @@ -428,9 +474,9 @@ }) const numberFormatter = new Intl.NumberFormat('es-CL', {minimumFractionDigits: 0, maximumFractionDigits: 0}) this.data.cartolas.forEach(cartola => { - cartola.draw().cartola(tbody, dateFormatter, numberFormatter) + cartola.draw().cartola($tbody, dateFormatter, numberFormatter) }) - table.DataTable(this.dataTableConfig) + $table.DataTable(this.dataTableConfig) }, } }, @@ -445,7 +491,7 @@ diaria.loader().show() fetchAPI(url, {method: 'post', body}).then(response => { diaria.loader().hide() - this.draw().empty() + this.draw().empty() if (!response) { return } @@ -455,6 +501,7 @@ } Object.entries(json.cartolas).forEach(entry => { const cartolaIdx = this.data.cartolas.findIndex(cartola => cartola.idx === parseInt(entry[0])) + this.data.cartolas[cartolaIdx].movimientos = [] entry[1].movimientos.forEach((row, idx) => { const fecha = new Date(row.fecha) fecha.setDate(fecha.getDate() + 1) @@ -498,6 +545,170 @@ this.cartolas().add() } } + const manual = { + ids: {}, + $modal: null, + data: { + inmobiliaria: '', + cuenta: '', + fecha: '', + field: 0, + movimientos: [ + {idx: 1} + ] + }, + get movimientosIdx() { + const $movimientosIdx = $(this.ids.form).find("[name='movimientos']") + return JSON.parse($movimientosIdx.val()) + }, + set movimientosIdx(list) { + const $movimientosIdx = $(this.ids.form).find("[name='movimientos']") + $movimientosIdx.val(JSON.stringify(list)) + }, + update() { + return { + file: movimientos => { + const $file = $("[name='file" + this.data.field + "']") + $file.val(JSON.stringify(movimientos)) + } + } + }, + parse() { + return { + movimientos: () => { + const $fields = $(this.ids.movimientos).find('.fields') + const movimientos = [] + $fields.each((i, fields) => { + const idx = $(fields).data('movimiento') + const inputs = [ + 'glosa', + 'cargo', + 'abono', + 'saldo' + ] + const data = {} + inputs.forEach(name => { + data[name] = $(fields).find("[name='"+name+idx+"']").val() + if (name !== 'glosa') { + data[name] = parseInt(data[name]) || 0 + } + }) + + movimientos.push(data) + }) + this.update().file(movimientos) + } + } + }, + movimiento() { + return { + add: () => { + const idx = this.data.movimientos.reduce((prev, movimiento) => Math.max(prev, movimiento.idx), 0) + 1 + const movimiento = { + idx + } + this.data.movimientos.push(movimiento) + const movimientosidx = this.movimientosIdx + movimientosidx.push(idx) + this.movimientosIdx = movimientosidx + this.draw().movimiento(idx) + }, + remove: idx => { + const movimientosIdx = this.movimientosIdx + const i = movimientosIdx.findIndex(n => n === idx) + movimientosIdx.splice(i, 1) + const movimientoIdx = this.data.movimientos.findIndex(movimiento => movimiento.idx === idx) + this.data.movimientos.splice(movimientoIdx, 1) + $(this.ids.movimientos).find("[data-idx='"+idx+"']").parent().parent().remove() + this.movimientosIdx = movimientosIdx + } + } + }, + draw() { + return { + movimiento: idx => { + $(this.ids.movimientos).append( + $('
').addClass('fields').attr('data-movimiento', idx).append( + $('
').addClass('field').append( + $('').html('Glosa') + ).append( + $('').attr('type', 'text').attr('name', 'glosa' + idx) + ) + ).append( + $('
').addClass('field').append( + $('').html('Cargo') + ).append( + $('
').addClass('ui left labeled input').append( + $('
').addClass('ui basic label').html('$') + ).append( + $('').attr('type', 'text').attr('name', 'cargo' + idx) + ) + ) + ).append( + $('
').addClass('field').append( + $('').html('Abono') + ).append( + $('
').addClass('ui left labeled input').append( + $('
').addClass('ui basic label').html('$') + ).append( + $('').attr('type', 'text').attr('name', 'abono' + idx) + ) + ) + ).append( + $('
').addClass('field').append( + $('').html('Saldo') + ).append( + $('
').addClass('ui left labeled input').append( + $('
').addClass('ui basic label').html('$') + ).append( + $('').attr('type', 'text').attr('name', 'saldo' + idx) + ) + ) + ).append( + $('
').addClass('field').append( + $('').html('Eliminar') + ).append( + $('').addClass('ui red icon button').attr('type', 'button').attr('data-idx', idx).append( + $('').addClass('remove icon') + ).click(event => { + const idx = $(event.currentTarget).data('idx') + manual.movimiento().remove(idx) + }) + ) + ) + ) + } + } + }, + setup(ids) { + this.ids = ids + + $(this.ids.modal).modal({ + onShow: () => { + $(this.ids.inmobiliaria).html(this.data.inmobiliaria) + $(this.ids.cuenta).html(this.data.cuenta) + $(this.ids.fecha).html(this.data.fecha) + this.movimientos = [] + $(this.ids.form).trigger('reset') + }, + onApprove: $element => { + this.parse().movimientos() + }, + onHide: $element => { + this.parse().movimientos() + } + }) + this.$modal = $(this.ids.modal) + $(this.ids.button).click(event => { + this.movimiento().add() + }) + $(this.ids.form).submit(event => { + event.preventDefault() + this.$modal.modal('hide') + return false + }) + } + } $(document).ready(() => { diaria.setup({ table: { @@ -513,6 +724,15 @@ }, loader: '#loader' }) + manual.setup({ + modal: '#manual_modal', + button: '#add_manual', + inmobiliaria: '#modal_inmobiliaria', + cuenta: '#modal_cuenta', + fecha: '#modal_fecha', + form: '#modal_form', + movimientos: '#modal_movimientos' + }) }) @endpush diff --git a/app/src/Controller/API/Contabilidad/Cartolas.php b/app/src/Controller/API/Contabilidad/Cartolas.php index 51864ef..e8668af 100644 --- a/app/src/Controller/API/Contabilidad/Cartolas.php +++ b/app/src/Controller/API/Contabilidad/Cartolas.php @@ -66,6 +66,11 @@ class Cartolas extends Controller try { $cuenta = $cuentaRepository->fetchById($body["cuenta_id{$field}"]); $fecha = new DateTimeImmutable($body["fecha{$field}"]); + if (array_key_exists("manual{$field}", $body)) { + $file = json_decode($body["file{$field}"], JSON_OBJECT_AS_ARRAY); + $output['cartolas'][$field] = $cartolaService->diariaManual($cuenta, $fecha, $file); + continue; + } $file = $request->getUploadedFiles()["file{$field}"]; $output['cartolas'][$field] = $cartolaService->diaria($cuenta, $fecha, $file); diff --git a/app/src/Repository/Movimiento.php b/app/src/Repository/Movimiento.php index f74704e..48a715c 100644 --- a/app/src/Repository/Movimiento.php +++ b/app/src/Repository/Movimiento.php @@ -61,12 +61,12 @@ class Movimiento extends Ideal\Repository ->where('cuenta_id = ? AND fecha = ?'); return $this->fetchMany($query, [$cuenta_id, $fecha->format('Y-m-d')]); } - public function fetchByCuentaAndFechaAndMonto(int $cuenta_id, DateTimeInterface $fecha, int $monto): Model\Movimiento + public function fetchByCuentaAndFechaAndCargoAndAbonoAndSaldo(int $cuenta_id, DateTimeInterface $fecha, int $cargo, int $abono, int $saldo): Model\Movimiento { $query = $this->connection->getQueryBuilder() ->select() ->from($this->getTable()) - ->where('cuenta_id = ? AND fecha = ? AND (cargo = ? OR abono = ?)'); - return $this->fetchOne($query, [$cuenta_id, $fecha->format('Y-m-d'), $monto, $monto]); + ->where('cuenta_id = ? AND fecha = ? AND cargo = ? AND abono = ? AND saldo = ?'); + return $this->fetchOne($query, [$cuenta_id, $fecha->format('Y-m-d'), $cargo, $abono, $saldo]); } } diff --git a/app/src/Service/Cartola.php b/app/src/Service/Cartola.php index 3545cce..c566604 100644 --- a/app/src/Service/Cartola.php +++ b/app/src/Service/Cartola.php @@ -65,6 +65,28 @@ class Cartola extends Service $cartola = $this->buildCartola($cuenta, $fecha, $cartolaData); return compact('cartola', 'movimientos'); } + public function diariaManual(Model\Inmobiliaria\Cuenta $cuenta, DateTimeInterface $fecha, array $data): array + { + $cartolaData = [ + 'cargos' => 0, + 'abonos' => 0, + 'saldos' => 0 + ]; + $movimientos = []; + foreach ($data as $row) { + $dataMovimiento = $row; + $dataMovimiento['fecha'] = $fecha->format('Y-m-d'); + $dataMovimiento['documento'] = ''; + $movimiento = $this->buildMovimiento($cuenta, $dataMovimiento); + + $movimientos []= $movimiento; + $cartolaData['cargos'] += $movimiento->cargo; + $cartolaData['abonos'] += $movimiento->abono; + $cartolaData['saldo'] = $movimiento->saldo; + } + $cartola = $this->buildCartola($cuenta, $fecha, $cartolaData); + return compact('cartola', 'movimientos'); + } protected function getMovimientosDiarios(Model\Banco $banco, UploadedFileInterface $file): array { @@ -85,12 +107,13 @@ class Cartola extends Service protected function buildMovimiento(Model\Inmobiliaria\Cuenta $cuenta, array $data): Model\Movimiento { try { - $valor = ($data['cargo'] !== 0 and $data['cargo'] !== null) ? $data['cargo'] : $data['abono']; return $this->movimientoRepository - ->fetchByCuentaAndFechaAndMonto( + ->fetchByCuentaAndFechaAndCargoAndAbonoAndSaldo( $cuenta->id, new DateTimeImmutable($data['fecha']), - $valor + $data['cargo'] ?? 0, + $data['abono'] ?? 0, + $data['saldo'] ); } catch (Exception\EmptyResult $exception) { $data['cuenta_id'] = $cuenta->id;