Files
contabilidad/ui/public/assets/scripts/home.js
2022-01-07 00:24:08 -03:00

368 lines
11 KiB
JavaScript

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)
})
const prev = this.prev()
prev.after(tr)
}
prev() {
let prev = $("[data-id='" + this.categoria_id + "'][data-class='categoria']")
let n = 0
while (prev.next().attr('data-class') === 'cuenta') {
prev = prev.next()
n ++;
if (n >= 100) {
return prev
}
}
return prev
}
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 = {
id: '#cuentas',
balance: 0,
tipos: [],
tipos_categorias: [],
build: function() {
return {
parent: (segment) => {
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(
$('<thead></thead>').append(tr)
)
const parent = $('<tbody></tbody>')
table.append(parent)
segment.append(table)
return parent
},
resultado: (segment) => {
segment.append(
$('<table></table>').attr('class', 'ui collapsing table').append(
$('<tr></tr>').append(
$('<td></td>').html('Ganancias')
).append(
$('<td></td>').attr('data-tipo', 'ganancias')
)
).append(
$('<tr></tr>').append(
$('<td></td>').html('Perdidas')
).append(
$('<td></td>').attr('data-tipo', 'perdidas')
)
).append(
$('<tr></tr>').append(
$('<td></td>').html('<b>Resultado</b>')
).append(
$('<td></td>').attr('data-tipo', 'resultado')
)
)
)
}
}
},
get: function() {
return {
parent: () => {
const segment = $(this.id)
let parent = segment.find('tbody')
if (parent.length === 0) {
parent = this.build().parent(segment)
}
return parent
},
tipos_cuentas: () => {
return sendGet(_urls.api + '/tipos/cuentas').then((data) => {
if (data.tipos === null || data.tipos.length === 0) {
return
}
this.tipos = data.tipos
})
},
tipos_categorias: () => {
return sendGet(_urls.api + '/tipos/categorias').then((data) => {
if (data.tipos === null || data.tipos.length === 0) {
return
}
$.each(data.tipos, (i, el) => {
tipo = new TipoCategoria(el)
tipo.setTipos(this.tipos)
this.tipos_categorias.push(tipo)
})
}).then(() => {
this.draw().tipos_categorias()
})
},
balance: () => {
sendGet(_urls.api + '/balance').then((data) => {
this.balance = data
}).then(() => {
this.draw().balance()
}).then(() => {
this.draw().resultado()
})
}
}
},
draw: function() {
return {
tipos_categorias: () => {
const format = Intl.NumberFormat('es-CL', {style: 'currency', currency: 'CLP'})
const parent = this.get().parent()
$.each(this.tipos_categorias, (i, el) => {
parent.append(el.draw({format, tipos: this.tipos}))
})
this.get().balance()
},
balance: () => {
const parent = this.get().parent().parent()
if (parent.find('tfoot').length === 0) {
parent.append(
$('<tfoot></tfoot>')
)
}
const format = Intl.NumberFormat('es-CL', {style: 'currency', currency: 'CLP'})
const foot = parent.find('tfoot')
foot.html('')
const tr = $('<tr></tr>').append(
$('<th></th>').attr('colspan', 3).html('<b>Total</b>')
)
$.each(this.tipos, (i, el) => {
tr.append(
$('<th></th>').attr('class', 'right aligned').append(
$('<b></b>').html(format.format(this.balance[el.descripcion.toLowerCase() + 's']))
)
)
})
foot.append(tr)
},
resultado: () => {
const div = $('#resultado')
if (div.find("[data-tipo='resultado']").length === 0) {
div.html('')
this.build().resultado(div)
}
const format = Intl.NumberFormat('es-CL', {style: 'currency', currency: 'CLP'})
div.find("[data-tipo='ganancias']").html(format.format(this.balance['ganancias']))
div.find("[data-tipo='perdidas']").html(format.format(this.balance['perdidas']))
div.find("[data-tipo='resultado']").html('<b>' + format.format(this.balance['ganancias'] - this.balance['perdidas']) + '</b>')
}
}
},
setup: async function() {
this.get().tipos_cuentas().then(() => {
this.get().tipos_categorias()
})
}
}