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 = $('').attr('data-id', this.id).attr('data-class', 'cuenta').append( $('').append( $('').attr('class', 'angle right icon') ) ).append( $('').append( $('').attr('class', 'angle right icon') ) ).append( $('').append( $('').attr('href', _urls.base + 'cuenta/' + this.id).append( $('').attr('class', 'square full icon').css('color', '#' + this.tipo.color) ).append(this.nombre) ) ) $.each(this.tipos, (i, m) => { const 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 = $('').attr('class', 'ui mini compact icon button').append( $('').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 = $('').attr('data-id', this.id).attr('data-class', 'categoria').append( $('').append($('').html('')) ).append( $('').attr('colspan', 2).append( $('
').append(button).append(this.nombre) ) ) $.each(this.tipos, (i, el) => { tr.append( $('').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( $('').attr('data-class', 'cuenta').attr('data-id', 'vacio').append( $('') ).append( $('') ).append( $('').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 = $('').attr('class', 'ui mini compact icon button').append( $('').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 = $('').attr('data-id', this.id).attr('data-class', 'tipo_categoria').append( $('').attr('colspan', 3).append( $('
').append(button).append(this.descripcion) ) ) $.each(this.tipos, (i, el) => { tr.append($('').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 = $('').append( $('').attr('colspan', 3).html('Cuenta') ) $.each(this.tipos, (i, el) => { tr.append( $('').attr('class', 'right aligned').css('color', '#' + el.color).html(el.descripcion) ) }) const table = $('
').attr('class', 'ui striped table').append( $('').append(tr) ) const parent = $('') table.append(parent) segment.append(table) return parent }, resultado: (segment) => { segment.append( $('
').attr('class', 'ui collapsing table').append( $('').append( $('').html('Ganancias') ).append( $('').attr('data-tipo', 'ganancias') ) ).append( $('').append( $('').html('Perdidas') ).append( $('').attr('data-tipo', 'perdidas') ) ).append( $('').append( $('').html('Resultado') ).append( $('').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( $('') ) } const format = Intl.NumberFormat('es-CL', {style: 'currency', currency: 'CLP'}) const foot = parent.find('tfoot') foot.html('') const tr = $('').append( $('').attr('colspan', 3).html('Total') ) $.each(this.tipos, (i, el) => { tr.append( $('').attr('class', 'right aligned').append( $('').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(format.format(this.balance['ganancias'] - this.balance['perdidas'])) } } }, setup: async function() { this.get().tipos_cuentas().then(() => { this.get().tipos_categorias() }) } }