2024-10-01 13:11:15 -03:00
< script >
class MovimientosTable {
props
columns
constructor ({ ids , eventHandler }) {
this . props = {
ids ,
eventHandler ,
movimientos : [],
formatters : {
number : new Intl . NumberFormat ( 'es-CL' ),
date : new Intl . DateTimeFormat ( 'es-CL' , {
day : '2-digit' ,
month : '2-digit' ,
year : 'numeric'
}),
},
}
this . columns = [
2025-01-13 17:53:30 -03:00
{ title : 'Sigla' , defs : { width : 'short' , type : 'string' }, process : movimiento => movimiento . cuenta . inmobiliaria . sigla , args : [ 'movimiento' ], searchable : true , export : true }, //0
{ title : 'Banco' , defs : { width : 'long' , type : 'string' }, process : movimiento => movimiento . cuenta . banco . nombre , args : [ 'movimiento' ], searchable : true , export : true },
{ title : 'Cuenta' , defs : { width : 'short' , type : 'string' }, process : movimiento => movimiento . cuenta . cuenta , args : [ 'movimiento' ], searchable : true , export : true },
{ title : 'Fecha' , defs : { width : 'long' , type : 'string' }, process : fecha => this . props . formatters . date . format ( fecha ), args : [ 'fecha' ], searchable : true , export : true , format : ( value ) => value . split ( '-' ) . reverse () . join ( '-' )},
{ title : 'ISO Fecha' , defs : { visible : false }, process : fecha => [ fecha . getFullYear (), fecha . getMonth () + 1 , fecha . getDate ()] . join ( '-' ), args : [ 'fecha' ]},
{ title : 'Mes' , defs : { width : 'short' , type : 'string' }, process : fecha => fecha . getMonth () + 1 , args : [ 'fecha' ], searchable : true }, //5
{ title : 'Año' , defs : { width : 'long' , type : 'string' }, process : fecha => fecha . getFullYear (), args : [ 'fecha' ], searchable : true },
{ title : 'Valor' , defs : { className : 'dt-right' , width : 'long' , type : 'num' }, process : valor => this . props . formatters . number . format ( valor ), args : [ 'valor' ], export : true , format : ( value ) => value . replace ( / \ ./ g , '' )},
{ title : 'ISO Valor' , defs : { visible : false , type : 'num' }, args : [ 'valor' ]},
{ title : 'Glosa' , defs : { width : 'short' , type : 'string' }, process : movimiento => movimiento . glosa , args : [ 'movimiento' ], export : true },
{ title : 'Centro de Costo' , defs : { width : 'short' , type : 'string' }, process : movimiento => ( movimiento . detalles && movimiento . detalles . centro_costo ) ? movimiento . detalles . centro_costo . id : '' , args : [ 'movimiento' ], searchable : true , export : true }, //10
{ title : 'Categoría' , defs : { width : 'short' , type : 'string' }, process : movimiento => ( movimiento . detalles ) ? movimiento . detalles . categoria : '' , args : [ 'movimiento' ], searchable : true , export : true },
{ title : 'Detalle' , defs : { width : 'long' , type : 'string' }, process : movimiento => ( movimiento . detalles ) ? movimiento . detalles . detalle : '' , args : [ 'movimiento' ], export : true },
{ title : 'RUT' , defs : { width : 'short' , type : 'string' }, process : movimiento => ( movimiento . detalles && movimiento . detalles . digito ) ? `${this.props.formatters.number.format(movimiento.detalles.rut)}-${movimiento.detalles.digito}` : '' , args : [ 'movimiento' ], searchable : true , export : true },
{ title : 'Nombre' , defs : { width : 'short' , type : 'string' }, args : [ 'nombre' ], searchable : true , export : true },
{ title : 'Identificador' , defs : { width : 'short' , type : 'string' }, process : movimiento => ( movimiento . detalles ) ? movimiento . detalles . identificador : '' , args : [ 'movimiento' ], export : true }, //15
{ title : 'Editar' , defs : { width : 'short' , type : 'string' }, args : [ 'buttonsHTML' ]},
2024-10-01 13:11:15 -03:00
]
const N = this . columns . filter ( column => typeof column . defs . visible === 'undefined' || column . defs . visible ) . length
const nShort = this . columns . filter ( column => column . defs . width === 'short' ) . length
const nLong = this . columns . filter ( column => column . defs . width === 'long' ) . length
const short = `${(nShort / N).toFixed(2)}%`
const long = `${(nLong / N).toFixed(2)}%`
this . columns = this . columns . map ( column => {
if ( typeof column . defs . width === 'undefined' ) {
return column
}
switch ( column . defs . width ) {
case 'short' :
column . defs . width = short
break
case 'long' :
column . defs . width = long
break
}
return column
})
const tr = $ ( this . props . ids . table ) . find ( 'thead tr' )
tr . empty ()
this . columns . forEach ( column => {
if ( typeof column . defs . className === 'undefined' ) {
tr . append ( `<th>${column.title}</th>` )
return
}
switch ( column . defs . className ) {
case 'dt-right' :
tr . append ( `<th class="right aligned">${column.title}</th>` )
break
case 'dt-center' :
tr . append ( `<th class="center aligned">${column.title}</th>` )
break
default :
tr . append ( `<th>${column.title}</th>` )
break
}
})
let dtD = structuredClone ( datatables_defaults )
const groupedColumns = Object . groupBy ( this . columns , ({ defs }) => Object . entries ( defs ) . map (( field , value ) => `${field}: ${value}` ) . join ( ' - ' ))
const columnDefs = Object . values ( groupedColumns ) . map ( group => {
return {
targets : group . map (({ title }) => title ) . map ( title => this . columns . map ( column => column . title ) . indexOf ( title )),
... group [ 0 ] . defs
}
})
const searchBuilderColumns = this . columns . filter ( column => column . searchable )
. map ( column => column . title ) . map ( title => this . columns . map ( column => column . title ) . indexOf ( title ))
const exportColumns = this . columns . filter ( column => column . export )
. map ( column => column . title ) . map ( title => this . columns . map ( column => column . title ) . indexOf ( title ))
const order = [ 'Sigla' , 'Banco' , 'ISO Fecha' ] . map ( title => {
return [ this . columns . map ( column => column . title ) . indexOf ( title ), 'asc' ]
})
dtD = Object . assign ( dtD , {
columnDefs ,
order ,
language : Object . assign ( dtD . language , {
2025-07-22 13:18:00 +00:00
searchBuilder
2024-10-01 13:11:15 -03:00
}),
layout : {
top1 : {
searchBuilder : {
columns : searchBuilderColumns ,
}
},
top1End : {
buttons : [
{
extend : 'excelHtml5' ,
className : 'green' ,
text : 'Exportar a Excel <i class="file excel icon"></i>' ,
title : 'Movimientos Contables' ,
download : 'open' ,
exportOptions : {
columns : exportColumns ,
format : {
2025-01-13 17:53:30 -03:00
body : ( data , row , columnIdx , node ) => {
const formats = this . columns . filter ( columnDef => columnDef . format )
const match = formats . map (({ title }) => title ) . indexOf ( this . columns [ columnIdx ] . title )
if ( match > - 1 ) {
return formats [ match ] . format ( data )
2024-10-01 13:11:15 -03:00
}
2025-01-13 17:53:30 -03:00
if ( typeof data === 'string' && data . includes ( '<span data-tooltip' )) {
return data . replace ( /< span data - tooltip = " (.*) " > ( .* ) < \ / span >/ , '$2' )
2024-10-01 13:11:15 -03:00
}
return data
}
}
},
customize : xlsx => {
const sheet = xlsx . xl . worksheets [ 'sheet1.xml' ]
const columns = Object . values ( $ ( 'row[r="2"] t' , sheet ) . map (( idx , column ) => column . textContent ))
const columnStylesMap = {
Valor : '63' ,
Fecha : '15'
}
Object . entries ( columnStylesMap ) . forEach (( column , style ) => {
const columnIndex = String . fromCharCode ( 'A' . charCodeAt ( 0 ) + columns . indexOf ( column ))
$ ( `c[r^="${columnIndex}"]` , sheet ) . attr ( 's' , style )
})
}
}
]
}
},
data : this . props . movimientos ,
2024-11-12 21:27:33 -03:00
rowCallback : ( row , data ) => {
$ ( row ) . find ( this . props . ids . buttons . edit ) . on ( 'click' , { handler : this . props . eventHandler }, this . props . eventHandler . edit () . movimiento )
$ ( row ) . find ( this . props . ids . buttons . remove ) . on ( 'click' , { handler : this . props . eventHandler }, this . props . eventHandler . remove () . movimiento )
}
2024-10-01 13:11:15 -03:00
})
this . props . table = new DataTable ( this . props . ids . table , dtD )
}
draw () {
return {
table : ( movimientos ) => {
2024-11-12 21:27:33 -03:00
const info = this . props . table . page . info ()
2024-10-01 13:11:15 -03:00
this . props . table . clear () . rows . add ( this . draw () . movimientos ( movimientos )) . draw ()
2024-11-12 21:27:33 -03:00
this . props . table . page ( info . page ) . draw ( false )
2024-10-01 13:11:15 -03:00
$ ( this . props . ids . buttons . edit ) . on ( 'click' , { handler : this . props . eventHandler }, this . props . eventHandler . edit () . movimiento )
$ ( this . props . ids . buttons . remove ) . on ( 'click' , { handler : this . props . eventHandler }, this . props . eventHandler . remove () . movimiento )
},
movimientos : ( movimientos ) => {
const output = []
movimientos . forEach ( movimiento => {
this . draw () . movimiento ({ movimiento , output })
})
return output
},
movimiento : ({ movimiento , output }) => {
const valor = movimiento . abono - movimiento . cargo
const fecha = movimiento . fecha
const buttons = {
edit : {
icon : 'edit'
},
remove : {
color : ' red' ,
icon : 'trash'
}
}
const buttonsHTML = Object . entries ( buttons ) . map (([ action , { color = '' , icon }]) => {
const className = this . props . ids . buttons [ action ] . replace ( '.' , '' )
return `<button class="ui${color} icon button ${className}" data-id="${movimiento.id}" data-index="${movimiento.index}" data-type="movimiento"><i class="${icon} icon"></i></button>`
}) . join ( '' )
2024-12-03 20:32:29 -03:00
let nombre = ''
if ( movimiento . detalles ) {
if ( movimiento . detalles . relacionado ) {
let type = movimiento . detalles . relacionadoType
type = type . charAt ( 0 ) . toUpperCase () + type . slice ( 1 )
nombre = `<span data-tooltip="${type}">${movimiento.detalles.nombres}</span>`
} else {
nombre = movimiento . detalles . nombres
}
}
2025-01-13 17:53:30 -03:00
const params = {
movimiento ,
fecha ,
valor ,
nombre ,
buttonsHTML ,
2024-10-01 13:11:15 -03:00
}
2025-01-13 17:53:30 -03:00
const data = {}
this . columns . forEach ( column => {
if ( column . process ) {
const args = Object . entries ( params ) . filter (([ param , value ]) => column . args . includes ( param )) . map ( arr => arr [ 1 ])
data [ column . title ] = column . process ( ... args )
return
}
if ( column . args ) {
data [ column . title ] = Object . entries ( params ) . filter (([ param , value ]) => column . args . includes ( param )) . map ( arr => arr [ 1 ])[ 0 ]
return ;
}
data [ column . title ] = params [ column . title . toLowerCase ()]
})
2024-10-01 13:11:15 -03:00
const values = []
this . columns . forEach ( column => {
values . push ( data [ column . title ])
})
output . push ( values )
}
}
}
}
</ script >