This commit is contained in:
2021-12-06 22:10:57 -03:00
parent 8ef4ab1c7d
commit 9d2504f016
35 changed files with 1374 additions and 239 deletions

View File

@ -0,0 +1,12 @@
<?php
namespace Contabilidad\Common\Controller;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
use Slim\Views\Blade as View;
class Config {
public function __invoke(Request $request, Response $response, View $view): Response {
return $view->render($response, 'config.list');
}
}

View File

@ -9,4 +9,7 @@ class Home {
public function __invoke(Request $request, Response $response, View $view): Response { public function __invoke(Request $request, Response $response, View $view): Response {
return $view->render($response, 'home'); return $view->render($response, 'home');
} }
public function info(Request $request, Response $response, View $view): Response {
return $view->render($response, 'info');
}
} }

View File

@ -0,0 +1,12 @@
<?php
namespace Contabilidad\Common\Controller;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
use Slim\Views\Blade as View;
class TiposCategorias {
public function __invoke(Request $request, Response $response, View $view): Response {
return $view->render($response, 'categorias.tipos.list');
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace Contabilidad\Common\Controller;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
use Slim\Views\Blade as View;
class TiposCuentas {
public function __invoke(Request $request, Response $response, View $view): Response {
return $view->render($response, 'cuentas.tipos.list');
}
}

4
ui/php.ini Normal file
View File

@ -0,0 +1,4 @@
[PHP]
display_errors = E_ALL
log_errors = true
error_log = /var/log/php/error.log

View File

@ -1,28 +1,92 @@
class Categoria {
constructor({id, nombre, tipo_id, tipo, saldo, saldoFormateado}) {
this.id = id
this.nombre = nombre
this.tipo_id = tipo_id
this.tipo = tipo
this.modal = null
}
setModal(modal) {
this.modal = modal
}
draw() {
return $('<tr></tr>').append(
$('<td></td>').html(this.nombre)
).append(
$('<td></td>').html(this.tipo.descripcion)
).append(
$('<td></td>').attr('class', 'right aligned').append(
$('<button></button>').attr('class', 'ui tiny circular icon button').attr('data-id', this.id).append(
$('<i></i>').attr('class', 'edit icon')
).click((e) => {
e.preventDefault()
this.edit()
return false
})
).append(
$('<button></button>').attr('class', 'ui tiny circular red icon button').attr('data-id', this.id).append(
$('<i></i>').attr('class', 'remove icon')
).click((e) => {
e.preventDefault()
this.remove()
return false
})
)
)
}
edit() {
this.modal.find('form').trigger('reset')
this.modal.find('form').find("[name='id']").val(this.id)
this.modal.find('form').find("[name='nombre']").val(this.nombre)
this.modal.find('form').find("#tipos").dropdown('set selected', this.tipo.id)
modalToEdit(this.modal)
this.modal.modal('show')
}
remove() {
sendDelete(_urls.api + '/categoria/' + this.id + '/delete').then(() => {
categorias.getCategorias()
})
}
}
const categorias = { const categorias = {
id: '#categorias', id: '#categorias',
categorias: [], categorias: [],
modal: null, modal: null,
getCategorias: function() { getCategorias: function() {
return $.ajax({ this.categorias = []
url: _urls.api + '/categorias', return sendGet(_urls.api + '/categorias').then((data) => {
method: 'GET', if (data.categorias === null || data.categorias.length === 0) {
dataType: 'json'
}).then((data) => {
if (data.categorias === null || data.categorias.length == 0) {
return return
} }
this.categorias = data.categorias $.each(data.categorias, (i, el) => {
const cat = new Categoria(el)
cat.setModal(this.modal)
this.categorias.push(cat)
})
}).then(() => { }).then(() => {
this.draw() this.draw()
}) })
}, },
getTipos: function() {
sendGet(_urls.api + '/tipos/categorias').then((data) => {
this.modal.find('#tipos').dropdown()
let values = []
$.each(data.tipos, (i, el) => {
values.push({value: el.id, text: el.descripcion, name: el.descripcion})
})
this.modal.find('#tipos').dropdown('change values', values)
})
},
getParent: function() { getParent: function() {
let parent = $(this.id).find('tbody') let parent = $(this.id).find('tbody')
if (parent.length == 0) { if (parent.length === 0) {
const table = $('<table></table>').attr('class', 'ui table').append( const table = $('<table></table>').attr('class', 'ui table').append(
$('<thead></thead>').append( $('<thead></thead>').append(
$('<tr></tr>').append( $('<tr></tr>').append(
$('<th></th>').html('Categoría') $('<th></th>').html('Categoría')
).append(
$('<th></th>').html('Tipo')
).append( ).append(
$('<th></th>').attr('class', 'right aligned').append( $('<th></th>').attr('class', 'right aligned').append(
$('<button></button>').attr('class', 'ui tiny green circular icon button').append( $('<button></button>').attr('class', 'ui tiny green circular icon button').append(
@ -47,27 +111,31 @@ const categorias = {
const parent = this.getParent() const parent = this.getParent()
parent.html('') parent.html('')
$.each(this.categorias, (i, el) => { $.each(this.categorias, (i, el) => {
parent.append( parent.append(el.draw())
$('<tr></tr>').append(
$('<td></td>').html(el.nombre)
)
)
}) })
}, },
add: function() { add: function() {
this.modal.find('form').trigger('reset') this.modal.find('form').trigger('reset')
modalToAdd(this.modal)
this.modal.modal('show') this.modal.modal('show')
}, },
doAdd: function() { doAdd: function() {
const data = JSON.stringify({ const data = JSON.stringify({
nombre: $("[name='nombre']").val() nombre: $("[name='nombre']").val(),
tipo_id: $("[name='tipo']").val()
}) })
return $.ajax({ return sendPost(_urls.api + '/categorias/add', data).then((data) => {
url: _urls.api + '/categorias/add', this.modal.modal('hide')
method: 'POST', this.getCategorias()
data: data, })
dataType: 'json' },
}).then((data) => { doEdit: function() {
const id = $("[name='id']").val()
const data = JSON.stringify({
nombre: $("[name='nombre']").val(),
tipo_id: $("[name='tipo']").val()
})
return sendPut(_urls.api + '/categoria/' + id +'/edit', data).then((data) => {
this.modal.modal('hide') this.modal.modal('hide')
this.getCategorias() this.getCategorias()
}) })
@ -80,9 +148,16 @@ const categorias = {
}) })
this.modal.find('form').submit((e) => { this.modal.find('form').submit((e) => {
e.preventDefault() e.preventDefault()
const add = $(e.currentTarget).find('.plus.icon')
if (add.length > 0) {
this.doAdd() this.doAdd()
} else {
this.doEdit()
}
return false return false
}) })
this.getTipos()
}, },
setup: function() { setup: function() {
this.setupModal() this.setupModal()

View File

@ -0,0 +1,80 @@
class Color {
constructor({hex, red, green, blue}) {
this.hex = hex ?? 'ffffff'
this.red = red ?? 255
this.green = green ?? 255
this.blue = blue ?? 255
}
toHex() {
this.hex = this.red.toString(16).padStart(2, '0') + this.green.toString(16).padStart(2, '0') + this.blue.toString(16).padStart(2, '0')
return this.hex
}
toRGB() {
this.red = parseInt(this.hex.substring(0,2), 16)
this.green = parseInt(this.hex.substring(2,4), 16)
this.blue = parseInt(this.hex.substring(4), 16)
return [this.red, this.green, this.blue]
}
}
class ColorPicker {
constructor(elem) {
this.setup(elem)
}
setup(elem) {
this.elem = elem
this.color = new Color({})
this.color.hex = elem.val()
this.color.toRGB()
this.holder = $('<div></div>').attr('class', 'color_picker_holder ui horizontal segments')
const red = $('<div></div>').attr('class', 'ui basic segment').append($('<div></div>').attr('class', 'ui red slider').slider({
max: 255,
start: this.color.red,
onMove: (content) => {
this.color.red = content
this.update()
}
}))
const green = $('<div></div>').attr('class', 'ui basic segment').append($('<div></div>').attr('class', 'ui green slider').slider({
max: 255,
start: this.color.green,
onMove: (content) => {
this.color.green = content
this.update()
}
}))
const blue = $('<div></div>').attr('class', 'ui basic segment').append($('<div></div>').attr('class', 'ui blue slider').slider({
max: 255,
start: this.color.blue,
onMove: (content) => {
this.color.blue = content
this.update()
}
}))
const color_cell = $('<div></div>').attr('class', 'ui center aligned compact basic segment').append(
$('<i></i>').attr('class', 'massive icons').append(
$('<i></i>').attr('class', 'square icon color_cell').css('color', '#' + this.color.toHex())
).append(
$('<i></i>').attr('class', 'square outline icon')
)
)
this.holder.append(color_cell)
const vseg = $('<div></div>').attr('class', 'ui basic segments')
vseg.append(red)
vseg.append(green)
vseg.append(blue)
this.holder.append($('<div></div>').attr('class', 'ui basic segment').append(vseg))
this.elem.after(this.holder)
}
setColor(color) {
this.color.hex = color
this.color.toRGB()
this.update()
}
update() {
this.elem.val(this.color.toHex())
this.holder.find('.red').slider('set value', this.color.red, false)
this.holder.find('.green').slider('set value', this.color.green, false)
this.holder.find('.blue').slider('set value', this.color.blue, false)
this.holder.find('.color_cell').css('color', '#' + this.color.toHex())
}
}

View File

@ -1,43 +1,127 @@
class Cuenta {
constructor({id, nombre, categoria_id, tipo_id, moneda_id, categoria, tipo, moneda, saldo, saldoFormateado}) {
this.id = id
this.nombre = nombre
this.categoria_id = categoria_id
this.tipo_id = tipo_id
this.moneda_id = moneda_id
this.categoria = categoria
this.tipo = tipo
this.moneda = moneda
this.modal = null
}
setModal(modal) {
this.modal = modal
}
draw() {
return $('<tr></tr>').append(
$('<td></td>').html(this.nombre)
).append(
$('<td></td>').html(this.categoria.nombre + ' - ' + this.categoria.tipo.descripcion)
).append(
$('<td></td>').css('color', '#' + this.tipo.color).html(this.tipo.descripcion)
).append(
$('<td></td>').html(this.moneda.codigo)
).append(
$('<td></td>').attr('class', 'right aligned').append(
$('<button></button>').attr('class', 'ui tiny circular icon button').attr('data-id', this.id).append(
$('<i></i>').attr('class', 'edit icon')
).click((e) => {
e.preventDefault()
this.edit()
return false
})
).append(
$('<button></button>').attr('class', 'ui tiny circular red icon button').attr('data-id', this.id).append(
$('<i></i>').attr('class', 'remove icon')
).click((e) => {
e.preventDefault()
this.remove()
return false
})
)
)
}
edit() {
const form = this.modal.find('form')
form.trigger('reset')
form.find("[name='id']").val(this.id)
form.find("[name='nombre']").val(this.nombre)
form.find("[name='categoria']").dropdown('set selected', this.categoria.id)
form.find("[name='tipo']").dropdown('set selected', this.tipo.id)
form.find("[name='moneda']").dropdown('set selected', this.moneda.id)
modalToEdit(this.modal)
this.modal.modal('show')
}
remove() {
sendDelete(_urls.api + '/cuenta/' + this.id + '/delete').then(() => {
cuentas.get().cuentas()
})
}
}
const cuentas = { const cuentas = {
id: '#cuentas', id: '#cuentas',
cuentas: [], cuentas: [],
categorias: [], categorias: [],
getCuentas: function() { tipos: [],
return $.ajax({ get: function() {
url: _urls.api + '/cuentas', return {
method: 'GET', cuentas: () => {
dataType: 'json' this.cuentas = []
}).then((data) => { return sendGet(_urls.api + '/cuentas').then((data) => {
if (data.cuentas === null || data.cuentas.length == 0) { if (data.cuentas === null || data.cuentas.length === 0) {
return return
} }
this.cuentas = data.cuentas $.each(data.cuentas, (i, el) => {
const cuenta = new Cuenta(el)
cuenta.setModal(this.modal)
this.cuentas.push(cuenta)
})
}).then(() => { }).then(() => {
this.draw() this.draw().cuentas()
}) })
}, },
getCategorias: function() { categorias: () => {
return $.ajax({ return sendGet(_urls.api + '/categorias').then((data) => {
url: _urls.api + '/categorias', if (data.categorias === null || data.categorias.length === 0) {
method: 'GET',
dataType: 'json'
}).then((data) => {
if (data.categorias === null || data.categorias.length == 0) {
return return
} }
this.categorias = data.categorias this.categorias = data.categorias
}).then(() => { }).then(() => {
this.drawCategorias() this.draw().categorias()
}) })
}, },
drawCategorias: function() { tipos: () => {
const select = $("[name='categoria']") return sendGet(_urls.api + '/tipos/cuentas').then((data) => {
$.each(this.categorias, (i, el) => { if (data.tipos === null || data.tipos.length === 0) {
select.append( return
$('<option></option>').attr('value', el.id).html(el.nombre) }
) this.tipos = data.tipos
}).then(() => {
this.draw().tipos()
}) })
}, },
monedas: () => {
return sendGet(_urls.api + '/monedas').then((data) => {
if (data.monedas === null || data.monedas.length === 0) {
return
}
this.monedas = data.monedas
}).then(() => {
this.draw().monedas()
})
},
parent: () => {
const segment = $(this.id)
let parent = segment.find('tbody')
if (parent.length === 0) {
parent = this.buildParent(segment)
}
return parent
}
}
},
buildParent: function(segment) { buildParent: function(segment) {
const table = $('<table></table>').attr('class', 'ui table').append( const table = $('<table></table>').attr('class', 'ui table').append(
$('<thead></thead>').append( $('<thead></thead>').append(
@ -45,6 +129,10 @@ const cuentas = {
$('<th></th>').html('Cuenta') $('<th></th>').html('Cuenta')
).append( ).append(
$('<th></th>').html('Categoría') $('<th></th>').html('Categoría')
).append(
$('<th></th>').html('Tipo')
).append(
$('<th></th>').html('Moneda')
).append( ).append(
$('<th></th>').attr('class', 'right aligned').append( $('<th></th>').attr('class', 'right aligned').append(
$('<button></button>').attr('class', 'ui tiny green circular icon button').append( $('<button></button>').attr('class', 'ui tiny green circular icon button').append(
@ -64,44 +152,73 @@ const cuentas = {
segment.append(table) segment.append(table)
return parent return parent
}, },
getParent: function() {
const segment = $(this.id)
let parent = segment.find('tbody')
if (parent.length == 0) {
parent = this.buildParent(segment)
}
return parent
},
draw: function() { draw: function() {
const parent = this.getParent() return {
cuentas: () => {
const parent = this.get().parent()
parent.html('') parent.html('')
$.each(this.cuentas, (i, el) => { $.each(this.cuentas, (i, el) => {
parent.append( parent.append(el.draw())
$('<tr></tr>').append( })
$('<td></td>').html(el.nombre) },
).append( categorias: () => {
$('<td></td>').html(el.categoria.nombre) const select = $("[name='categoria']")
) $.each(this.categorias, (i, el) => {
select.append(
$('<option></option>').attr('value', el.id).html(el.nombre + ' - ' + el.tipo.descripcion)
) )
}) })
}, },
tipos: () => {
const select = $("[name='tipo']")
$.each(this.tipos, (i, el) => {
select.append($('<option></option>').attr('value', el.id).html(el.descripcion))
})
},
monedas: () => {
const select = $("[name='moneda']")
$.each(this.monedas, (i, el) => {
const opt = $('<option></option>').attr('value', el.id).html(el.denominacion)
if (el.codigo === 'CLP') {
opt.attr('selected', 'selected')
}
select.append(opt)
})
}
}
},
add: function() { add: function() {
this.modal.find('form').trigger('reset') this.modal.find('form').trigger('reset')
modalToAdd(this.modal)
this.modal.modal('show') this.modal.modal('show')
}, },
doAdd: function() { doAdd: function() {
const data = JSON.stringify({ const data = JSON.stringify({
categoria_id: $("[name='categoria']").val(), categoria_id: $("[name='categoria']").val(),
nombre: $("[name='nombre']").val() nombre: $("[name='nombre']").val(),
tipo_id: $("[name='tipo']").val(),
moneda_id: $("[name='moneda']").val()
}) })
return $.ajax({ return sendPost(
url: _urls.api + '/cuentas/add', _urls.api + '/cuentas/add',
method: 'POST', data
data: data, ).then((data) => {
dataType: 'json'
}).then((data) => {
this.modal.modal('hide') this.modal.modal('hide')
this.getCuentas() this.get().cuentas()
})
},
doEdit: function() {
form = this.modal.find('form')
const id = form.find("[name='id']").val()
const data = JSON.stringify({
nombre: form.find("[name='nombre']").val(),
categoria_id: form.find("[name='categoria']").val(),
tipo_id: form.find("[name='tipo']").val(),
moneda_id: form.find("[name='moneda']").val()
})
sendPut(_urls.api + '/cuenta/' + id + '/edit', data).then(() => {
this.modal.modal('hide')
this.get().cuentas()
}) })
}, },
setupModal: function() { setupModal: function() {
@ -112,14 +229,23 @@ const cuentas = {
}) })
this.modal.find('form').submit((e) => { this.modal.find('form').submit((e) => {
e.preventDefault() e.preventDefault()
const add = $(e.currentTarget).find('.ui.button').find('.plus.icon')
if (add.length > 0) {
this.doAdd() this.doAdd()
} else {
this.doEdit()
}
return false return false
}) })
}, },
setup: function() { setup: function() {
this.setupModal() this.setupModal()
this.getCuentas().then(() => { this.get().cuentas().then(() => {
this.getCategorias() this.get().categorias().then(() => {
this.get().tipos().then(() => {
this.get().monedas()
})
})
}) })
} }
} }

View File

@ -1,3 +1,85 @@
class Transaccion {
constructor({id, debito_id, credito_id, fecha, glosa, detalle, valor, debito, credito, fechaFormateada, valorFormateado}) {
this.id = id
this.debito_id = debito_id
this.credito_id = credito_id
this.fecha = {
fecha,
formateada: fechaFormateada
}
this.glosa = glosa
this.detalle = detalle
this.valor = {
valor,
formateado: valorFormateado
}
this.debito = debito
this.credito = credito
this.modal = null
}
setCuenta(cuenta) {
this.cuenta = cuenta
}
setModal(modal) {
this.modal = modal
}
isDebito() {
return this.debito.id === this.cuenta.id;
}
isIncrement() {
const debits = ['Activo', 'Perdida']
if (debits.indexOf(this.cuenta.tipo.descripcion)) {
return this.isDebito()
}
return !this.isDebito()
}
draw({saldo, format}) {
const fuente = (this.isDebito()) ? this.credito : this.debito
return $('<tr></tr>').append(
$('<td></td>').html(this.fecha.formateada)
).append(
$('<td></td>').append(
$('<a></a>').attr('href', _urls.base + 'cuenta/' + fuente.id).html(fuente.nombre + ' (' + fuente.categoria.nombre + ')')
)
).append(
$('<td></td>').html(this.glosa + '<br />' + this.detalle)
).append(
$('<td></td>').attr('class', 'right aligned').html((this.isIncrement()) ? '' : format.format(this.valor.valor))
).append(
$('<td></td>').attr('class', 'right aligned').html((this.isIncrement()) ? format.format(this.valor.valor) : '')
).append(
$('<td></td>').attr('class', 'right aligned').html(format.format(saldo))
).append(
$('<td></td>').attr('class', 'right aligned')/*.append(
$('<button></button>').attr('class', 'ui tiny circular icon button').append(
$('<i></i>').attr('class', 'edit icon')
).click((e) => {
e.preventDefault()
this.edit()
return false
})
)*/.append(
$('<button></button>').attr('class', 'ui tiny circular red icon button').append(
$('<i></i>').attr('class', 'remove icon')
).click((e) => {
e.preventDefault()
this.remove()
return false
})
)
)
}
edit() {
const form = this.modal.find('form')
form.find("[name='fecha']")
}
remove() {
sendDelete(_urls.api + '/transaccion/' + this.id + '/delete').then(() => {
transacciones.get().transacciones()
})
}
}
const transacciones = { const transacciones = {
id: '#transacciones', id: '#transacciones',
cuenta_id: 0, cuenta_id: 0,
@ -9,33 +91,35 @@ const transacciones = {
return { return {
transacciones: () => { transacciones: () => {
let promises = [] let promises = []
$.ajax({ sendGet(_urls.api + '/cuenta/' + this.cuenta_id + '/transacciones/amount').then((data) => {
url: _urls.api + '/cuenta/' + this.cuenta_id + '/transacciones/amount', if (data.cuenta === null) {
method: 'GET',
dataType: 'json'
}).then((data) => {
const amount = data.transacciones
const step = 100
for (let i = 0; i < amount; i += step) {
promises.push($.ajax({
url: _urls.api + '/cuenta/' + this.cuenta_id + '/transacciones/' + step + '/' + i,
method: 'GET',
dataType: 'json'
}))
}
Promise.all(promises).then((data_arr) => {
if (data_arr[0].cuenta === null) {
return return
} }
this.cuenta = data_arr[0].cuenta this.cuenta = data.cuenta
this.saldo = this.cuenta.saldo this.saldo = this.cuenta.saldo
$('#cuenta').html(this.cuenta.nombre + ' (' + this.cuenta.categoria.nombre + ')') $('#cuenta').html(this.cuenta.nombre + ' (' + this.cuenta.categoria.nombre + ')').append(
$('<i></i>').attr('class', 'square full icon').css('color', '#' + this.cuenta.tipo.color)
)
const amount = data.transacciones
const step = 50
for (let i = 0; i < amount; i += step) {
promises.push(
sendGet(_urls.api + '/cuenta/' + this.cuenta_id + '/transacciones/' + step + '/' + i)
)
}
if (promises.length > 0) {
Promise.all(promises).then((data_arr) => {
this.transacciones = [] this.transacciones = []
data_arr.forEach(data => { data_arr.forEach(data => {
if (data.transacciones === null || data.transacciones.length == 0) { if (data.transacciones === null || data.transacciones.length === 0) {
return return
} }
this.transacciones.push(...data.transacciones) $.each(data.transacciones, (i, el) => {
const tr = new Transaccion(el)
tr.setCuenta(this.cuenta)
tr.setModal(this.modal)
this.transacciones.push(tr)
})
}) })
this.transacciones.sort((a, b) => { this.transacciones.sort((a, b) => {
return (new Date(b.fecha)) - (new Date(a.fecha)) return (new Date(b.fecha)) - (new Date(a.fecha))
@ -43,15 +127,14 @@ const transacciones = {
}).then(() => { }).then(() => {
this.draw() this.draw()
}) })
} else {
this.draw()
}
}) })
}, },
cuentas: () => { cuentas: () => {
return $.ajax({ return sendGet(_urls.api + '/cuentas').then((data) => {
url: _urls.api + '/cuentas', if (data.cuentas === null || data.cuentas.length === 0) {
method: 'GET',
dataType: 'json'
}).then((data) => {
if (data.cuentas === null || data.cuentas.length == 0) {
return return
} }
this.cuentas = data.cuentas this.cuentas = data.cuentas
@ -67,29 +150,12 @@ const transacciones = {
} }
}, },
draw: function() { draw: function() {
const format = Intl.NumberFormat('es-CL', {style: 'currency', currency: 'CLP'}) const format = Intl.NumberFormat('es-CL', {style: 'currency', currency: this.cuenta.moneda.codigo})
const parent = $(this.id) const parent = $(this.id)
parent.html('') parent.html('')
$.each(this.transacciones, (i, el) => { $.each(this.transacciones, (i, el) => {
const fuente = (el.valor < 0) ? el.hasta : el.desde parent.append(el.draw({saldo: this.saldo, format: format}))
parent.append( this.saldo = this.saldo + parseInt(el.valor.valor) * ((el.isIncrement()) ? 1 : -1)
$('<tr></tr>').append(
$('<td></td>').html(el.fechaFormateada)
).append(
$('<td></td>').append(
$('<a></a>').attr('href', _urls.base + 'cuenta/' + fuente.id).html(fuente.nombre + ' (' + fuente.categoria.nombre + ')')
)
).append(
$('<td></td>').html(el.glosa + '<br />' + el.detalle)
).append(
$('<td></td>').attr('class', 'right aligned').html((el.valor < 0) ? '' : el.valorFormateado.replace('-', ''))
).append(
$('<td></td>').attr('class', 'right aligned').html((el.valor < 0) ? el.valorFormateado.replace('-', '') : '')
).append(
$('<td></td>').attr('class', 'right aligned').html(format.format(this.saldo))
)
)
this.saldo -= parseInt(el.valor)
}) })
}, },
add: function() { add: function() {
@ -99,22 +165,26 @@ const transacciones = {
this.modal.modal('show') this.modal.modal('show')
}, },
exec: () => { exec: () => {
const fecha = $("[name='fecha']").val()
const data1 = JSON.stringify({
desde_id: $("[name='moneda']").val(),
hasta_id: 1,
fecha: fecha,
valor: $("[name='cambio']").val()
})
sendPut(_urls.api + '/tipos/cambios/add', data1)
const valor = $("[name='valor']").val() const valor = $("[name='valor']").val()
const cuenta = $("[name='cuenta']").val() const cuenta = $("[name='cuenta']").val()
const data = JSON.stringify({ const data = JSON.stringify({
desde_id: (valor < 0) ? this.cuenta_id : cuenta, debito_id: (valor < 0) ? this.cuenta_id : cuenta,
hasta_id: (valor < 0) ? cuenta : this.cuenta_id, credito_id: (valor < 0) ? cuenta : this.cuenta_id,
fecha: $("[name='fecha']").val(), fecha: fecha,
glosa: $("[name='glosa']").val(), glosa: $("[name='glosa']").val(),
detalle: $("[name='detalle']").val(), detalle: $("[name='detalle']").val(),
valor: (valor < 0) ? -valor : valor valor: (valor < 0) ? -valor : valor
}) })
return $.ajax({ return sendPost(_urls.api + '/transacciones/add', data).then(() => {
url: _urls.api + '/transacciones/add',
method: 'POST',
data: data,
dataType: 'json'
}).then(() => {
this.modal.modal('hide') this.modal.modal('hide')
this.get().transacciones() this.get().transacciones()
}) })

View File

@ -1,19 +1,234 @@
const down_icon = 'right chevron'
const up_icon = 'down chevron'
class Cuenta {
constructor({id, nombre, tipo_id, categoria_id, tipo, saldo, saldoFormateado}) {
this.id = id
this.nombre = nombre
this.tipo_id = tipo_id
this.categoria_id = categoria_id
this.tipo = tipo
this.saldo = {
saldo,
formateado: saldoFormateado
}
}
setTipos(tipos) {
this.tipos = tipos
}
draw() {
const tr = $('<tr></tr>').attr('data-id', this.id).attr('data-class', 'cuenta').append(
$('<td></td>').append(
$('<i></i>').attr('class', 'angle right icon')
)
).append(
$('<td></td>').append(
$('<i></i>').attr('class', 'angle right icon')
)
).append(
$('<td></td>').append(
$('<a></a>').attr('href', _urls.base + 'cuenta/' + this.id).append(
$('<i></i>').attr('class', 'square full icon').css('color', '#' + this.tipo.color)
).append(this.nombre)
)
)
$.each(this.tipos, (i, m) => {
const td = $('<td></td>').attr('class', 'right aligned')
if (m.descripcion === this.tipo.descripcion) {
td.html(this.saldo.formateado)
}
tr.append(td)
})
$("[data-id='" + this.categoria_id + "'][data-class='categoria']").after(tr)
}
remove() {
$("[data-id='" + this.id + "'][data-class='cuenta']").remove()
}
}
class Categoria {
constructor({id, nombre, tipo_id, tipo, activos, pasivos, ganancias, perdidas}) {
this.id = id
this.nombre = nombre
this.tipo_id = tipo_id
this.tipo = tipo
this.activos = activos
this.pasivos = pasivos
this.ganancias = ganancias
this.perdidas = perdidas
this.is_open = false
this.cuentas = []
}
setTipos(tipos) {
this.tipos = tipos
}
draw({format}) {
const button = $('<button></button>').attr('class', 'ui mini compact icon button').append(
$('<i></i>').attr('class', down_icon + ' icon')
).click((e) => {
const plus = button.find('.' + down_icon.replace(' ', '.') + '.icon')
if (plus.length > 0) {
this.loadCuentas()
button.find('i.icon').removeClass(down_icon).addClass(up_icon)
this.is_open = true
} else {
this.removeCuentas()
button.find('i.icon').removeClass(up_icon).addClass(down_icon)
this.is_open = false
}
})
const tr = $('<tr></tr>').attr('data-id', this.id).attr('data-class', 'categoria').append(
$('<td></td>').append($('<span></span>').html('<i class="angle right icon"></i>'))
).append(
$('<td></td>').attr('colspan', 2).append(
$('<div></div>').append(button).append(this.nombre)
)
)
$.each(this.tipos, (i, el) => {
tr.append(
$('<td></td>').attr('class', 'right aligned').html(format.format(this[el.descripcion.toLowerCase() + 's']))
)
})
$("[data-id='" + this.tipo_id + "'][data-class='tipo_categoria']").after(tr)
if (this.is_open) {
button.trigger('click')
}
}
remove() {
this.removeCuentas()
$("[data-id='" + this.id + "'][data-class='categoria']").remove()
}
loadCuentas() {
if (this.cuentas.length === 0) {
sendGet(_urls.api + '/categoria/' + this.id + '/cuentas').then((data) => {
if (data.cuentas === null || data.cuentas.length === 0) {
return
}
$.each(data.cuentas, (i, el) => {
const cuenta = new Cuenta(el)
cuenta.setTipos(this.tipos)
this.cuentas.push(cuenta)
})
}).then(() => {
this.drawCuentas()
})
return
}
this.drawCuentas()
}
drawCuentas() {
if (this.cuentas.length === 0) {
$("[data-id='"+this.id+"'][data-class='categoria']").after(
$('<tr></tr>').attr('data-class', 'cuenta').attr('data-id', 'vacio').append(
$('<td></td>')
).append(
$('<td></td>')
).append(
$('<td></td>').attr('colspan', 5).html('No hay cuentas.')
)
)
return
}
$.each(this.cuentas, (i, el) => {
el.draw()
})
}
removeCuentas() {
if (this.cuentas.length === 0) {
$("tr[data-class='cuenta'][data-id='vacio']").remove()
return
}
$.each(this.cuentas, (i, el) => {
el.remove()
})
}
}
class TipoCategoria {
constructor({id, descripcion, activo, activos, pasivos, ganancias, perdidas}) {
this.id = id
this.descripcion = descripcion
this.activo = activo
this.activos = activos
this.pasivos = pasivos
this.ganancias = ganancias
this.perdidas = perdidas
this.categorias = []
}
setTipos(tipos) {
this.tipos = tipos
}
draw({format}) {
const button = $('<button></button>').attr('class', 'ui mini compact icon button').append(
$('<i></i>').attr('class', down_icon + ' icon')
).click((e) => {
const plus = button.find('.' + down_icon.replace(' ', '.') + '.icon')
if (plus.length > 0) {
this.loadCategorias()
button.find('i.icon').removeClass(down_icon).addClass(up_icon)
} else {
this.removeCategorias()
button.find('i.icon').removeClass(up_icon).addClass(down_icon)
}
})
const tr = $('<tr></tr>').attr('data-id', this.id).attr('data-class', 'tipo_categoria').append(
$('<td></td>').attr('colspan', 3).append(
$('<div></div>').append(button).append(this.descripcion)
)
)
$.each(this.tipos, (i, el) => {
tr.append($('<td></td>').attr('class', 'right aligned').html(format.format(this[el.descripcion.toLowerCase() + 's'])))
})
return tr
}
loadCategorias() {
if (this.categorias.length === 0) {
sendGet(_urls.api + '/tipos/categoria/' + this.id + '/categorias').then((data) => {
if (data.categorias === null || data.categorias.length === 0) {
return
}
$.each(data.categorias, (i, el) => {
const cat = new Categoria(el)
cat.setTipos(this.tipos)
this.categorias.push(cat)
})
}).then(() => {
this.drawCategorias()
})
return
}
this.drawCategorias()
}
drawCategorias() {
const format = Intl.NumberFormat('es-CL', {style: 'currency', currency: 'CLP'})
$.each(this.categorias, (i, el) => {
el.draw({format})
})
}
removeCategorias() {
$.each(this.categorias, (i, el) => {
el.remove()
})
}
}
const cuentas = { const cuentas = {
id: '#cuentas', id: 'cuentas',
categorias: [], balance: 0,
tipos: [],
tipos_categorias: [],
get: function() { get: function() {
return { return {
parent: () => { parent: () => {
let parent = $(this.id) let parent = $('#' + this.id)
if (parent.length === 0) { if (parent.length === 0) {
const tr = $('<tr></tr>').append(
$('<th></th>').attr('colspan', 3).html('Cuenta')
)
$.each(this.tipos, (i, el) => {
tr.append(
$('<th></th>').attr('class', 'right aligned').css('color', '#' + el.color).html(el.descripcion)
)
})
const table = $('<table></table>').attr('class', 'ui striped table').append( const table = $('<table></table>').attr('class', 'ui striped table').append(
$('<thead></thead>').append( $('<thead></thead>').append(tr)
$('<tr></tr>').append(
$('<th></th>').html('Cuenta')
).append(
$('<th></th>').attr('class', 'right aligned').html('Saldo')
)
)
) )
parent = $('<tbody></tbody>').attr('id', this.id) parent = $('<tbody></tbody>').attr('id', this.id)
table.append(parent) table.append(parent)
@ -21,107 +236,74 @@ const cuentas = {
} }
return parent return parent
}, },
categorias: () => { tipos_cuentas: () => {
return $.ajax({ return sendGet(_urls.api + '/tipos/cuentas').then((data) => {
url: _urls.api + '/categorias', if (data.tipos === null || data.tipos.length === 0) {
method: 'GET',
dataType: 'json'
}).then((data) => {
if (data.categorias === null || data.categorias.length == 0) {
return return
} }
this.categorias = data.categorias this.tipos = data.tipos
}).then(() => {
this.draw().categorias()
}) })
}, },
cuentas: (categoria_id) => { tipos_categorias: () => {
return $.ajax({ return sendGet(_urls.api + '/tipos/categorias').then((data) => {
url: _urls.api + '/categoria/' + categoria_id + '/cuentas', if (data.tipos === null || data.tipos.length === 0) {
method: 'GET',
dataType: 'json'
}).then((data) => {
if (data.cuentas === null || data.cuentas.length == 0) {
return return
} }
const idx = this.categorias.findIndex(el => { $.each(data.tipos, (i, el) => {
if (el.id == categoria_id) { tipo = new TipoCategoria(el)
return true tipo.setTipos(this.tipos)
} this.tipos_categorias.push(tipo)
}) })
this.categorias[idx].cuentas = data.cuentas
}).then(() => { }).then(() => {
this.draw().cuentas(categoria_id) this.draw().tipos_categorias()
}) })
}
}
}, },
remove: function() { balance: () => {
return { sendGet(_urls.api + '/balance').then((data) => {
cuentas: (categoria_id) => { this.balance = data
const idx = this.categorias.findIndex(el => { }).then(() => {
if (el.id == categoria_id) { this.draw().balance()
return true
}
}) })
const parent = $("[data-id='" + categoria_id + "']")
for (let i = 0; i < this.categorias[idx].cuentas.length; i ++) {
parent.next().remove()
}
} }
} }
}, },
draw: function() { draw: function() {
return { return {
categorias: () => { tipos_categorias: () => {
const format = Intl.NumberFormat('es-CL', {style: 'currency', currency: 'CLP'})
const parent = this.get().parent() const parent = this.get().parent()
$.each(this.categorias, (i, el) => { $.each(this.tipos_categorias, (i, el) => {
const button = $('<button></button>').attr('class', 'ui mini compact icon button').append( parent.append(el.draw({format, tipos: this.tipos}))
$('<i></i>').attr('class', 'plus icon')
).click((e) => {
const plus = button.find('.plus')
if (plus.length == 0) {
console.debug(e.target)
this.remove().cuentas(el.id)
button.find('i.icon').removeClass('minus').addClass('plus')
} else {
console.debug(e.target)
this.get().cuentas(el.id)
button.find('i.icon').removeClass('plus').addClass('minus')
}
})
const f = $('<tr></tr>').attr('data-id', el.id).append(
$('<td></td>').append(
$('<div></div>').append(button).append(el.nombre)
)
).append(
$('<td></td>').attr('class', 'right aligned').html(el.saldoFormateado)
)
parent.append(f)
}) })
this.get().balance()
}, },
cuentas: (categoria_id) => { balance: () => {
const idx = this.categorias.findIndex(el => { const parent = this.get().parent().parent()
if (el.id == categoria_id) { if (parent.find('tfoot').length === 0) {
return true parent.append(
$('<tfoot></tfoot>')
)
} }
}) const format = Intl.NumberFormat('es-CL', {style: 'currency', currency: 'CLP'})
const parent = $("[data-id='" + categoria_id + "']") const foot = parent.find('tfoot')
$.each(this.categorias[idx].cuentas, (i, el) => { foot.html('')
parent.after( const tr = $('<tr></tr>').append(
$('<tr></tr>').attr('class', 'item').append( $('<th></th>').attr('colspan', 3).html('<b>Total</b>')
$('<td></td>').append(
$('<a></a>').attr('href', _urls.base + 'cuenta/' + el.id).html(el.nombre)
) )
).append( $.each(this.tipos, (i, el) => {
$('<td></td>').attr('class', 'right aligned').html(el.saldoFormateado) tr.append(
$('<th></th>').attr('class', 'right aligned').append(
$('<b></b>').html(format.format(this.balance[el.descripcion.toLowerCase() + 's']))
) )
) )
}) })
foot.append(tr)
} }
} }
}, },
setup: async function() { setup: async function() {
this.get().categorias() this.get().tipos_cuentas().then(() => {
this.get().tipos_categorias()
})
} }
} }

View File

@ -0,0 +1,177 @@
class TipoCategoria {
constructor({id, descripcion, activo}) {
this.id = id
this.descripcion = descripcion
this.activo = activo
this.modal = null
}
setModal(modal) {
this.modal = modal
}
draw() {
const chk = $('<input/>').attr('type', 'checkbox').attr('name', 'activo_' + this.id).attr('value', '1')
if (this.activo === '1') {
chk.parent().addClass('active')
chk.attr('checked', 'checked')
chk.checkbox('check')
}
chk.checkbox({
onChange: () => {
this.changeActivo()
}
})
return $('<tr></tr>').append(
$('<td></td>').html(this.descripcion)
).append(
$('<td></td>').append(
$('<div></div>').attr('class', 'ui checkbox').append(chk).append(
$('<label></label>').html(' ')
)
)
).append(
$('<td></td>').attr('class', 'right aligned').append(
$('<button></button>').attr('class', 'ui tiny circular icon button').attr('data-id', this.id).append(
$('<i></i>').attr('class', 'edit icon')
).click((e) => {
this.edit()
})
).append(
$('<button></button>').attr('class', 'ui tiny circular red icon button').attr('data-id', this.id).append(
$('<i></i>').attr('class', 'remove icon')
).click((e) => {
this.remove()
})
)
)
}
changeActivo() {
const data = JSON.stringify({
descripcion: this.descripcion,
activo: this.activo === '1' ? 0 : 1
})
return sendPut(_urls.api + '/tipos/categoria/' + this.id + '/edit', data).then((data) => {
this.modal.modal('hide')
tipos_categorias.getTipos()
})
}
edit() {
const form = this.modal.find('form')
form.find("[name='id']").val(this.id)
form.find("[name='descripcion']").val(this.descripcion)
if (this.activo === '1') {
form.find("[name='activo']").attr('checked', 'checked')
}
modalToEdit(this.modal)
this.modal.modal('show')
}
remove() {
sendDelete(_urls.api + '/tipos/categoria/' + this.id + '/delete').then(() => {
tipos_categorias.getTipos()
})
}
}
const tipos_categorias = {
id: '#tipos_categorias',
tipos: [],
modal: null,
getTipos: function() {
this.tipos = []
return sendGet(_urls.api + '/tipos/categorias').then((data) => {
if (data.tipos === null || data.tipos.length === 0) {
return
}
$.each(data.tipos, (i, el) => {
const tipo = new TipoCategoria(el)
tipo.setModal(this.modal)
this.tipos.push(tipo)
})
}).then(() => {
this.draw()
})
},
getParent: function() {
let parent = $(this.id).find('tbody')
if (parent.length === 0) {
const table = $('<table></table>').attr('class', 'ui table').append(
$('<thead></thead>').append(
$('<tr></tr>').append(
$('<th></th>').attr('class', 'twelve wide').html('Tipo Categoría')
).append(
$('<th></th>').attr('class', 'two wide').html('Activo')
).append(
$('<th></th>').attr('class', 'two wide right aligned').append(
$('<button></button>').attr('class', 'ui tiny green circular icon button').append(
$('<i></i>').attr('class', 'plus icon')
)
)
)
)
)
table.find('.ui.button').click((e) => {
e.preventDefault()
this.add()
return false
})
parent = $('<tbody></tbody>')
table.append(parent)
$(this.id).append(table)
}
return parent
},
draw: function() {
const parent = this.getParent()
parent.html('')
$.each(this.tipos, (i, el) => {
parent.append(el.draw())
})
},
add: function() {
this.modal.find('form').trigger('reset')
modalToAdd(this.modal)
this.modal.modal('show')
},
doAdd: function() {
const data = JSON.stringify({
descripcion: $("[name='descripcion']").val(),
activo: $("[name='activo']").val()
})
return sendPost(_urls.api + '/tipos/categorias/add', data).then((data) => {
this.modal.modal('hide')
this.getTipos()
})
},
doEdit: function() {
const form = this.modal.find('form')
const id = form.find("[name='id']").val()
const data = JSON.stringify({
descripcion: form.find("[name='descripcion']").val(),
activo: form.find("[name='activo']").is(':checked') ? 1 : 0
})
return sendPut(_urls.api + '/tipos/categoria/' + id + '/edit', data).then((data) => {
this.modal.modal('hide')
this.getTipos()
})
},
setupModal: function() {
this.modal = $('.ui.modal')
this.modal.modal()
this.modal.find('.close.icon').click(() => {
this.modal.modal('hide')
})
this.modal.find('form').submit((e) => {
e.preventDefault()
const add = $(e.currentTarget).find('.plus.icon')
if (add.length > 0) {
this.doAdd()
} else {
this.doEdit()
}
return false
})
},
setup: function() {
this.setupModal()
this.getTipos()
}
}

View File

@ -0,0 +1,165 @@
class TipoCuenta {
constructor({id, descripcion, color}) {
this.id = id
this.descripcion = descripcion
this.color = color
this.modal = null
}
setModal(modal) {
this.modal = modal
}
setPicker(picker) {
this.picker = picker
}
draw() {
return $('<tr></tr>').append(
$('<td></td>').append(
$('<i></i>').attr('class', 'square full icon').css('color', '#' + this.color)
).append(this.descripcion)
).append(
$('<td></td>').attr('class', 'right aligned').append(
$('<button></button>').attr('class', 'ui tiny circular icon button').attr('data-id', this.id).append(
$('<i></i>').attr('class', 'edit icon')
).click((e) => {
e.preventDefault()
this.edit()
return false
})
).append(
$('<button></button>').attr('class', 'ui tiny circular red icon button').attr('data-id', this.id).append(
$('<i></i>').attr('class', 'remove icon')
).click((e) => {
e.preventDefault()
this.remove()
return false
})
)
)
}
edit() {
const form = this.modal.find('form')
form.find("[name='id']").val(this.id)
form.find("[name='descripcion']").val(this.descripcion)
form.find("[name='color']").val(this.color)
this.picker.setColor(this.color)
modalToEdit(this.modal)
this.modal.modal('show')
}
remove() {
sendDelete(_urls.api + '/tipos/cuenta/' + this.id + '/delete').then(() => {
tipos_cuentas.getTipos()
})
}
}
const tipos_cuentas = {
id: '#tipos_cuentas',
tipos: [],
getTipos: function() {
this.tipos = []
return sendGet(_urls.api + '/tipos/cuentas').then((data) => {
if (data.tipos === null || data.tipos.length === 0) {
return
}
$.each(data.tipos, (i, el) => {
const tipo = new TipoCuenta(el)
tipo.setModal(this.modal)
tipo.setPicker(this.picker)
this.tipos.push(tipo)
})
}).then(() => {
this.draw()
})
},
buildParent: function(segment) {
const table = $('<table></table>').attr('class', 'ui table').append(
$('<thead></thead>').append(
$('<tr></tr>').append(
$('<th></th>').html('Tipo')
).append(
$('<th></th>').attr('class', 'right aligned').append(
$('<button></button>').attr('class', 'ui tiny green circular icon button').append(
$('<i></i>').attr('class', 'plus icon')
)
)
)
)
)
table.find('.ui.button').click((e) => {
e.preventDefault()
this.add()
return false
})
parent = $('<tbody></tbody>')
table.append(parent)
segment.append(table)
return parent
},
getParent: function() {
const segment = $(this.id)
let parent = segment.find('tbody')
if (parent.length === 0) {
parent = this.buildParent(segment)
}
return parent
},
draw: function() {
const parent = this.getParent()
parent.html('')
$.each(this.tipos, (i, el) => {
parent.append(el.draw())
})
},
add: function() {
this.modal.find('form').trigger('reset')
this.picker.setColor('ffffff')
modalToAdd(this.modal)
this.modal.modal('show')
},
doAdd: function() {
const data = JSON.stringify({
descripcion: this.modal.find('form').find("[name='descripcion']").val(),
color: this.modal.find('form').find("[name='color']").val()
})
return sendPost(
_urls.api + '/tipos/cuentas/add',
data
).then((data) => {
this.modal.modal('hide')
this.getCuentas()
})
},
doEdit: function() {
id = this.modal.find('form').find("[name='id']").val()
const data = JSON.stringify({
descripcion: this.modal.find('form').find("[name='descripcion']").val(),
color: this.modal.find('form').find("[name='color']").val()
})
sendPut(_urls.api + '/tipos/cuenta/' + id + '/edit', data).then((data) => {
this.modal.modal('hide')
this.getTipos()
})
},
setupModal: function() {
this.modal = $('.ui.modal')
this.modal.modal()
this.modal.find('.close.icon').css('cursor', 'pointer').click(() => {
this.modal.modal('hide')
})
this.picker = new ColorPicker(this.modal.find("[name='color']"))
this.modal.find('form').submit((e) => {
e.preventDefault()
const add = $(e.currentTarget).find('.add.icon')
if (add.length > 0) {
this.doAdd()
} else {
this.doEdit()
}
return false
})
},
setup: function() {
this.setupModal()
this.getTipos()
}
}

View File

@ -0,0 +1,4 @@
<?php
use Contabilidad\Common\Controller\Config;
$app->get('/config', Config::class);

View File

@ -1,4 +1,5 @@
<?php <?php
use Contabilidad\Common\Controller\Home; use Contabilidad\Common\Controller\Home;
$app->get('/info[/]', [Home::class, 'info']);
$app->get('[/]', Home::class); $app->get('[/]', Home::class);

View File

@ -0,0 +1,13 @@
<?php
$folder = implode(DIRECTORY_SEPARATOR, [__DIR__, 'tipos']);
if (file_exists($folder)) {
$app->group('/tipos', function($app) use ($folder) {
$files = new DirectoryIterator($folder);
foreach ($files as $file) {
if ($file->isDir() or $file->getExtension() != 'php') {
continue;
}
include_once $file->getRealPath();
}
});
}

View File

@ -0,0 +1,4 @@
<?php
use Contabilidad\Common\Controller\TiposCategorias;
$app->get('/categorias', TiposCategorias::class);

View File

@ -0,0 +1,4 @@
<?php
use Contabilidad\Common\Controller\TiposCuentas;
$app->get('/cuentas', TiposCuentas::class);

View File

@ -6,10 +6,19 @@
<i class="close icon"></i> <i class="close icon"></i>
<div class="content"> <div class="content">
<form class="ui form"> <form class="ui form">
<input type="hidden" name="id" />
<div class="field"> <div class="field">
<label>Nombre</label> <label>Nombre</label>
<input type="text" name="nombre" /> <input type="text" name="nombre" />
</div> </div>
<div class="field">
<label>Tipo</label>
<div class="ui selection dropdown" id="tipos">
<input type="hidden" name="tipo" />
<div class="default text">Tipo</div>
<div class="menu"></div>
</div>
</div>
<button class="ui icon button"> <button class="ui icon button">
<i class="plus icon"></i> <i class="plus icon"></i>
</button> </button>

View File

@ -0,0 +1,14 @@
@extends('config.base')
@section('config_content')
<h1 class="ui header">
@hasSection('tipos_categorias_title')
Tipo Categoría @yield('tipos_categorias_title')
@else
Tipos Categoría
@endif
</h1>
<div class="ui segment">
@yield('tipos_categorias_content')
</div>
@endsection

View File

@ -0,0 +1,33 @@
@extends('categorias.tipos.base')
@section('tipos_categorias_content')
<div id="tipos_categorias"></div>
<div class="ui modal">
<i class="close icon"></i>
<div class="content">
<form class="ui form">
<input type="hidden" name="id" />
<div class="field">
<label>Descripci&oacute;n</label>
<input type="text" name="descripcion" />
</div>
<div class="field">
<label>Activo</label>
<input type="checkbox" name="activo" value="1" />
</div>
<button class="ui icon button">
<i class="plus icon"></i>
</button>
</form>
</div>
</div>
@endsection
@push('scripts')
<script type="text/javascript" src="{{$urls->scripts}}/tipos_categorias.list.js"></script>
<script type="text/javascript">
$(document).ready(() => {
tipos_categorias.setup()
})
</script>
@endpush

View File

@ -0,0 +1,20 @@
@extends('layout.base')
@section('page_content')
<h1 class="ui header">
@hasSection('config_title')
@yield('config_title')
@else
Configuraciones
@endif
</h1>
<div class="ui compact grid">
<div class="three wide column">
@include('config.menu')
</div>
<div class="thirteen wide column">
<div class="ui segment">
@yield('config_content')
</div>
</div>
@endsection

View File

@ -0,0 +1 @@
@extends('config.base')

View File

@ -0,0 +1,4 @@
<div class="ui vertical fluid borderless menu">
@include('config.menu.tipos_categorias')
@include('config.menu.tipos_cuentas')
</div>

View File

@ -0,0 +1,3 @@
<a class="item" href="{{$urls->base}}tipos/categorias">
Tipos Categorías
</a>

View File

@ -0,0 +1,3 @@
<a class="item" href="{{$urls->base}}tipos/cuentas">
Tipos Cuentas
</a>

View File

@ -6,6 +6,7 @@
<i class="close icon"></i> <i class="close icon"></i>
<div class="content"> <div class="content">
<form class="ui form"> <form class="ui form">
<input type="hidden" name="id" />
<div class="inline field"> <div class="inline field">
<label>Categor&iacute;a</label> <label>Categor&iacute;a</label>
<select name="categoria"></select> <select name="categoria"></select>
@ -14,6 +15,14 @@
<label>Nombre</label> <label>Nombre</label>
<input type="text" name="nombre" /> <input type="text" name="nombre" />
</div> </div>
<div class="inline field">
<label>Tipo</label>
<select name="tipo"></select>
</div>
<div class="inline field">
<label>Moneda</label>
<select name="moneda"></select>
</div>
<button class="ui icon button"> <button class="ui icon button">
<i class="plus icon"></i> <i class="plus icon"></i>
</button> </button>

View File

@ -50,6 +50,7 @@
<i class="close icon"></i> <i class="close icon"></i>
<div class="content"> <div class="content">
<form class="ui form"> <form class="ui form">
<input type="hidden" name="id" />
<div class="field"> <div class="field">
<label>Fecha</label> <label>Fecha</label>
<div class="ui calendar"> <div class="ui calendar">

View File

@ -0,0 +1,14 @@
@extends('config.base')
@section('config_content')
<h1 class="ui header">
@hasSection('tipos_cuentas_title')
Tipo Cuenta @yield('tipos_cuentas_title')
@else
Tipos Cuenta
@endif
</h1>
<div class="ui basic fitted segment">
@yield('tipos_cuentas_content')
</div>
@endsection

View File

@ -0,0 +1,34 @@
@extends('cuentas.tipos.base')
@section('tipos_cuentas_content')
<div id="tipos_cuentas"></div>
<div class="ui modal">
<i class="close icon"></i>
<div class="content">
<form class="ui form">
<input type="hidden" name="id" />
<div class="field">
<label>Descripcion</label>
<input type="text" name="descripcion" />
</div>
<div class="inline field">
<lable>Color</lable>
<input type="text" name="color" value="ffffff" />
</div>
<button class="ui icon button">
<i class="plus icon"></i>
</button>
</form>
</div>
</div>
@endsection
@push('scripts')
<script type="text/javascript" src="{{$urls->scripts}}/colorpicker.js"></script>
<script type="text/javascript" src="{{$urls->scripts}}/tipos_cuentas.list.js"></script>
<script type="text/javascript">
$(document).ready(() => {
tipos_cuentas.setup()
})
</script>
@endpush

View File

@ -0,0 +1,2 @@
<?php
phpinfo();

View File

@ -2,4 +2,7 @@
<a class="item" href="{{$urls->base}}">Inicio</a> <a class="item" href="{{$urls->base}}">Inicio</a>
@include('layout.body.menu.cuentas') @include('layout.body.menu.cuentas')
@include('layout.body.menu.categorias') @include('layout.body.menu.categorias')
<div class="right menu">
<a class="item" href="{{$urls->base}}config">Config</a>
</div>
</nav> </nav>

View File

@ -2,10 +2,45 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.8.8/semantic.min.js" integrity="sha512-t5mAtfZZmR2gl5LK7WEkJoyHCfyzoy10MlerMGhxsXl3J7uSSNTAW6FK/wvGBC8ua9AFazwMaC0LxsMTMiM5gg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.8.8/semantic.min.js" integrity="sha512-t5mAtfZZmR2gl5LK7WEkJoyHCfyzoy10MlerMGhxsXl3J7uSSNTAW6FK/wvGBC8ua9AFazwMaC0LxsMTMiM5gg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script type="text/javascript"> <script type="text/javascript">
const API_KEY = '{{$api_key}}'
const _urls = { const _urls = {
base: '{{$urls->base}}', base: '{{$urls->base}}',
api: '{{$urls->api}}' api: '{{$urls->api}}'
} }
function buildAjax(url, method) {
return {
url: url,
headers: {
'Authorization': 'Bearer ' + API_KEY
},
method: method,
dataType: 'json'
}
}
function sendGet(url) {
let ajax_obj = buildAjax(url, 'GET')
return $.ajax(ajax_obj)
}
function sendPost(url, data) {
let ajax_obj = buildAjax(url, 'POST')
ajax_obj['data'] = data
return $.ajax(ajax_obj)
}
function sendPut(url, data) {
let ajax_obj = buildAjax(url, 'PUT')
ajax_obj['data'] = data
return $.ajax(ajax_obj)
}
function sendDelete(url) {
let ajax_obj = buildAjax(url, 'DELETE')
return $.ajax(ajax_obj)
}
function modalToEdit(modal) {
$(modal).find('form').find('button').find('.icon').attr('class', 'edit icon')
}
function modalToAdd(modal) {
$(modal).find('form').find('button').find('.icon').attr('class', 'plus icon')
}
</script> </script>
@stack('scripts') @stack('scripts')

View File

@ -1,4 +1,5 @@
<?php <?php
return [ return [
'debug' => $_ENV['DEBUG'] ?? false 'debug' => $_ENV['DEBUG'] ?? false,
'API_KEY' => $_ENV['API_KEY'] ?? ''
]; ];

View File

@ -16,6 +16,10 @@ return [
$arr['assets'], $arr['assets'],
'scripts' 'scripts'
]); ]);
$arr['styles'] = implode('/', [
$arr['assets'],
'styles'
]);
$arr['api'] = $_ENV['API_URL'] ?? 'http://localhost:9001'; $arr['api'] = $_ENV['API_URL'] ?? 'http://localhost:9001';
return (object) $arr; return (object) $arr;
} }

View File

@ -8,6 +8,7 @@ return [
$c->get('folders')->cache, $c->get('folders')->cache,
null, null,
[ [
'api_key' => $c->get('API_KEY'),
'urls' => $c->get('urls') 'urls' => $c->get('urls')
] ]
); );