From 62aa6a08a04be1061a9a3871c378d50f5a2ce870 Mon Sep 17 00:00:00 2001 From: Juan Pablo Vial Date: Tue, 5 Aug 2025 18:18:05 -0400 Subject: [PATCH] Listado de cierres --- .../20250215133437_create_reservations.php | 2 +- ...05212635_add_comments_to_estado_cierre.php | 29 ++ .../views/ventas/reservations.blade.php | 356 ++++++++++++++---- 3 files changed, 316 insertions(+), 71 deletions(-) create mode 100644 app/resources/database/migrations/20250805212635_add_comments_to_estado_cierre.php diff --git a/app/resources/database/migrations/20250215133437_create_reservations.php b/app/resources/database/migrations/20250215133437_create_reservations.php index fb3bc74..1a8dec7 100644 --- a/app/resources/database/migrations/20250215133437_create_reservations.php +++ b/app/resources/database/migrations/20250215133437_create_reservations.php @@ -4,7 +4,7 @@ declare(strict_types=1); use Phinx\Migration\AbstractMigration; -final class CreateReservation extends AbstractMigration +final class CreateReservations extends AbstractMigration { /** * Change Method. diff --git a/app/resources/database/migrations/20250805212635_add_comments_to_estado_cierre.php b/app/resources/database/migrations/20250805212635_add_comments_to_estado_cierre.php new file mode 100644 index 0000000..bbd9cae --- /dev/null +++ b/app/resources/database/migrations/20250805212635_add_comments_to_estado_cierre.php @@ -0,0 +1,29 @@ +table('estado_cierre_comentarios') + ->addColumn('estado_cierre_id', 'integer', ['signed' => false]) + ->addColumn('fecha', 'datetime', ['default' => 'CURRENT_TIMESTAMP']) + ->addColumn('comments', 'text') + ->addForeignKey('estado_cierre_id', 'estado_cierre', 'id', ['delete' => 'cascade', 'update' => 'cascade']) + ->create(); + } +} diff --git a/app/resources/views/ventas/reservations.blade.php b/app/resources/views/ventas/reservations.blade.php index 12801f9..14936e6 100644 --- a/app/resources/views/ventas/reservations.blade.php +++ b/app/resources/views/ventas/reservations.blade.php @@ -24,7 +24,7 @@ @endif -

+

+
- - + +
+
+ @@ -44,15 +53,43 @@ - + - - -
Unidades ClienteOferta ¿Valida? Operador - -
+ + + + +
+ + + + + + + + + + + + +
UnidadesClienteFechaOfertaOperador
+
+
+ + + + + + + + + + + + + +
UnidadesClienteFechaOfertaEstadoOperadorComentarios
+
@endsection @@ -94,7 +131,7 @@ event.preventDefault() const project_id = event.currentTarget.dataset.id - if (project_id === this.curent_project) { + if (project_id === this.current_project) { this.hide() this.title_component.innerHTML = event.currentTarget.innerHTML @@ -102,7 +139,7 @@ return } - this.curent_project = project_id + this.current_project = project_id reservations.get().reservations(project_id) this.hide() @@ -122,41 +159,73 @@ this.title_component.style.display = this.display.project } } - class Reservations { + class Controls { display = { - reservations: '', - controls: '' + up: '', + reset: '', } component_id = '' component = null - controls_id = '' - controls = null - formatters = { - date: null, - ufs: null + + buttons = { + up: null, + reset: null, + add: null } - reservations = [] - - constructor({component_id, controls_id, formatters = {date, ufs}}) { + constructor({component_id}) { this.component_id = component_id this.component = document.getElementById(this.component_id) - this.display.reservations = this.component.style.display - this.controls_id = controls_id - this.controls = document.getElementById(this.controls_id) - this.display.controls = this.controls.style.display - this.formatters = formatters + const buttons = this.component.querySelectorAll('button') + this.buttons.up = buttons[0] + this.buttons.reset = buttons[1] + this.buttons.add = buttons[2] + this.display.up = buttons[0].style.display + this.display.reset = buttons[1].style.display this.watch() this.hide() } watch() { - const buttons = this.controls.querySelectorAll('button') - const up_button = buttons[0] - const reset_button = buttons[1] - up_button.addEventListener('click', reservations.action().up.bind(reservations)) - reset_button.addEventListener('click', reservations.action().reset.bind(reservations)) + Object.entries(this.buttons).forEach(([key, value]) => { + const name = key.replace('_button', '') + value.addEventListener('click', reservations.action()[name].bind(reservations)) + }) + } + hide() { + this.buttons.up.style.display = this.display.up + this.buttons.reset.style.display = this.display.reset + } + show() { + this.buttons.up.style.display = 'none' + this.buttons.reset.style.display = 'none' + } + } + class Reservations { + display = { + reservations: '', + } + component_id = '' + component = null + formatters = { + date: null, + ufs: null + } + + columnNames = [] + reservations = [] + + constructor({component_id, formatters = {date, ufs}}) { + this.component_id = component_id + this.component = document.getElementById(this.component_id) + this.display.reservations = this.component.style.display + + this.formatters = formatters + + this.set().columnNames() + + this.hide() } set() { @@ -164,53 +233,135 @@ reservations: reservations => { this.reservations = reservations return this + }, + columnNames: () => { + const tds = this.component.querySelector('thead tr').querySelectorAll('th') + this.columnNames = [] + tds.forEach(td => { + let name = td.innerHTML.toLowerCase() + if (name === '') { + return + } + if (name.includes('?')) { + name = name.replaceAll(/[¿?]/g, '') + } + this.columnNames.push(name) + }) + return this } } } + columnsData() { + return this.reservations.map(reservation => { + const date = new Date(Date.parse(reservation.fecha) + 24 * 60 * 60 * 1000) + return { + id: reservation.id, + unidades: reservation.summary, + cliente: reservation.buyer.nombreCompleto, + fecha: this.formatters.date.format(date), + oferta: `${this.formatters.ufs.format(reservation.offer)} UF`, + valida: reservation.valid ? 'Si' : 'No', + operador: reservation.broker?.name ?? '', + } + }) + } draw() { const tbody = this.component.querySelector('tbody') tbody.innerHTML = '' - this.reservations.forEach(reservation => { + this.columnsData().forEach(column => { const tr = document.createElement('tr') - const date = new Date(Date.parse(reservation.fecha) + 24 * 60 * 60 * 1000) - tr.innerHTML = ` - ${reservation.summary} - ${reservation.buyer.nombreCompleto} - ${this.formatters.date.format(date)} - ${this.formatters.ufs.format(reservation.offer)} UF - ${reservation.valid ? 'Si' : 'No'} - ${reservation.broker?.name ?? ''} - - - - - ` + const contents = [] + const id = column.id + this.columnNames.forEach(name => { + contents.push(`${column[name]}`) + }) + const actions = this.drawActions(id) + if (actions !== '') { + contents.push(actions) + } + tr.innerHTML = contents.join("\n") tbody.appendChild(tr) }) this.show() } + drawActions(id) { + return ` + + + + ` + } show() { this.component.style.display = this.display.reservations - this.controls.style.display = this.display.controls } hide() { this.component.style.display = 'none' - this.controls.style.display = 'none' + } + } + class ActiveReservations extends Reservations { + constructor({component_id, formatters = {date, ufs}}) { + super({component_id, formatters}) + } + columnsData() { + const data = super.columnsData(); + return data.map(row => { + delete(row['valida']) + return row + }) + } + drawActions(id) { + return ` + + + + ` + } + } + class PendingReservations extends Reservations { + constructor({component_id, formatters = {date, ufs}}) { + super({component_id, formatters}) + } + } + class RejectedReservations extends Reservations { + constructor({component_id, formatters = {date, ufs}}) { + super({component_id, formatters}) + } + + columnsData() { + const data = super.columnsData() + return this.reservations.map((reservation, idx) => { + data[idx]['estado'] = reservation.state.charAt(0).toUpperCase() + reservation.state.slice(1) + data[idx]['comentarios'] = reservation.comments?.join('
\n') ?? '' + return data[idx] + }) + } + + drawActions(id) { + return '' } } const reservations = { components: { projects: null, - reservations: null + controls: null, + reservations: { + active: null, + pending: null, + rejected: null + } }, get() { return { - reservations: project_id => { + active: project_id => { const reservations = [ { id: 1, @@ -220,26 +371,74 @@ nombreCompleto: 'Juan Perez' }, fecha: '2021-01-01', - offer: 1000, - valid: false, + offer: 3000, + valid: true, broker: { name: 'Operador 1' } - }, + } + ] + this.components.reservations.active.set().reservations(reservations).draw() + }, + pending: project_id => { + const reservations = [ { id: 2, summary: 'D2', buyer: { rut: '12345678-9', - nombreCompleto: 'Pedro Gonzalez' + nombreCompleto: 'Pedro Jimenez' }, fecha: '2021-10-01', - offer: 1200, - valid: true, - broker: null + offer: 1000, + valid: false, + broker: { + name: 'Operador 2' + } } ] - this.components.reservations.set().reservations(reservations).draw() + this.components.reservations.pending.set().reservations(reservations).draw() + }, + rejected: project_id => { + const reservations = [ + { + id: 3, + summary: 'D3', + buyer: { + rut: '12345678-9', + nombreCompleto: 'Fernando Dominguez' + }, + fecha: '2021-01-10', + offer: 1000, + valid: false, + state: 'rechazado', + broker: { + name: 'Operador 3' + }, + comments: ['Comentarios'] + }, + { + id: 4, + summary: 'D4', + buyer: { + rut: '12345678-9', + nombreCompleto: 'Domingo Gomez' + }, + fecha: '2021-02-01', + offer: 1000, + valid: false, + state: 'abandonado', + broker: { + name: 'Operador 4' + } + } + ] + this.components.reservations.rejected.set().reservations(reservations).draw() + }, + reservations: project_id => { + this.get().active(project_id) + this.get().pending(project_id) + this.get().rejected(project_id) } } }, @@ -248,19 +447,28 @@ reset: event => { event.preventDefault() this.components.projects.current_project = null - this.components.reservations.reservations = [] - this.components.reservations.hide() + Object.entries(this.components.reservations).forEach(([key, value]) => { + this.components.reservations[key].reservations = [] + this.components.reservations[key].hide() + }) this.components.projects.show() return false }, up: event => { event.preventDefault() - this.components.reservations.hide() + Object.values(this.components.reservations).forEach(reservations => reservations.hide()) this.components.projects.show() return false }, + add: event => { + event.preventDefault() + console.debug('Add') + return false + }, reservations: () => { - this.components.reservations.draw() + Object.values(this.components.reservations).forEach(reservations => { + reservations.draw() + }) } } }, @@ -270,7 +478,12 @@ ufs: new Intl.NumberFormat('es-CL', {minimumFractionDigits: 2, maximumFractionDigits: 2}) } this.components.projects = new Projects({component_id: configuration.ids.projects, title_id: configuration.ids.project}) - this.components.reservations = new Reservations({component_id: configuration.ids.reservations, controls_id: configuration.ids.controls, formatters}) + this.components.controls = new Controls({component_id: configuration.ids.controls}) + this.components.reservations.active = new ActiveReservations({component_id: configuration.ids.active, formatters}) + this.components.reservations.pending = new PendingReservations({component_id: configuration.ids.pending, formatters}) + this.components.reservations.rejected = new RejectedReservations({component_id: configuration.ids.rejected, formatters}) + + $(`#${configuration.ids.tabs} .item`).tab() } } $(document).ready(() => { @@ -279,7 +492,10 @@ projects: 'projects', project: 'project', controls: 'controls', - reservations: 'reservations' + tabs: 'tabs', + active: 'active_reservations', + pending: 'pending_reservations', + rejected: 'rejected_reservations', } }) })