Merge pull request 'feature/cierres' (#50) from feature/cierres into develop
Reviewed-on: http://git.provm.cl/Incoviba/oficial/pulls/50
This commit is contained in:
@ -61,7 +61,7 @@ class Exception implements ProcessorInterface
|
||||
'trace' => $exception->getTraceAsString(),
|
||||
];
|
||||
if ($exception->getPrevious() !== null) {
|
||||
$output['previous'] = $this->processException($exception);
|
||||
$output['previous'] = $this->processException($exception->getPrevious());
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
@ -79,7 +79,7 @@
|
||||
'<td colspan="3">Todas las Unidades</td>',
|
||||
`<td class="right aligned">`,
|
||||
`<button class="ui red icon button remove_button project" data-id="${project.id}">`,
|
||||
'<i class="plus icon"></i>',
|
||||
'<i class="trash icon"></i>',
|
||||
'</button>',
|
||||
`</td>`
|
||||
].join("\n")
|
||||
|
||||
@ -295,46 +295,66 @@
|
||||
}
|
||||
}
|
||||
get columnsData() {
|
||||
return this.reservations.map(reservation => {
|
||||
const date = new Date(Date.parse(reservation.date) + 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 ? '<span class="ui green text">Si</span>' : '<span class="ui red text">No</span>',
|
||||
operador: reservation.broker?.name ?? '',
|
||||
}
|
||||
const columnValues = {
|
||||
id: reservation => reservation.id,
|
||||
unidades: reservation => reservation.summary,
|
||||
cliente: reservation => reservation.buyer.nombreCompleto,
|
||||
fecha: reservation => this.formatters.date.format(new Date(Date.parse(reservation.date) + 24 * 60 * 60 * 1000)),
|
||||
oferta: reservation => `${this.formatters.ufs.format(reservation.offer)} UF`,
|
||||
valida: reservation => reservation.valid ? '<span class="ui green text">Si</span>' : '<span class="ui red text">No</span>',
|
||||
operador: reservation => reservation.broker?.name ?? '',
|
||||
};
|
||||
const tooltipVariation = 'very wide multiline'
|
||||
const tooltips = this.draw().tooltip()
|
||||
return this.reservations.map(reservation => {
|
||||
const data = {}
|
||||
Object.entries(columnValues).forEach(([key, value]) => {
|
||||
if (key in tooltips) {
|
||||
const processor = tooltips[key]
|
||||
const content = processor(reservation)//.replaceAll(' ', ' ')
|
||||
data[key] = `data-html="${content}" data-variation="${tooltipVariation}">${value(reservation)}`
|
||||
return
|
||||
}
|
||||
data[key] = value(reservation)
|
||||
})
|
||||
return data
|
||||
})
|
||||
}
|
||||
draw() {
|
||||
if (this.reservations.length === 0) {
|
||||
this.empty()
|
||||
return
|
||||
}
|
||||
const tbody = this.component.querySelector('tbody')
|
||||
tbody.innerHTML = ''
|
||||
this.columnsData.forEach(column => {
|
||||
const tr = document.createElement('tr')
|
||||
const contents = []
|
||||
const id = column.id
|
||||
this.columnNames.forEach(name => {
|
||||
contents.push(`<td>${column[name]}</td>`)
|
||||
})
|
||||
const actions = this.drawActions(id)
|
||||
if (actions !== '') {
|
||||
contents.push(actions)
|
||||
}
|
||||
tr.innerHTML = contents.join("\n")
|
||||
tbody.appendChild(tr)
|
||||
})
|
||||
this.show()
|
||||
return {
|
||||
tbody: () => {
|
||||
if (this.reservations.length === 0) {
|
||||
this.empty()
|
||||
return
|
||||
}
|
||||
const tbody = this.component.querySelector('tbody')
|
||||
tbody.innerHTML = ''
|
||||
this.columnsData.forEach(column => {
|
||||
const tr = document.createElement('tr')
|
||||
const contents = []
|
||||
const id = column.id
|
||||
this.columnNames.forEach(name => {
|
||||
let td = `<td>${column[name]}</td>`
|
||||
if (column[name].includes('data-content') || column[name].includes('data-html')) {
|
||||
td = `<td ${column[name]}</td>`
|
||||
}
|
||||
contents.push(td)
|
||||
})
|
||||
const actions = this.draw().actions(id)
|
||||
if (actions !== '') {
|
||||
contents.push(actions)
|
||||
}
|
||||
tr.innerHTML = contents.join("\n")
|
||||
tbody.appendChild(tr)
|
||||
})
|
||||
this.show()
|
||||
|
||||
this.watch()
|
||||
}
|
||||
drawActions(id) {
|
||||
return `
|
||||
$(this.component).find('[data-content],[data-html]').popup()
|
||||
|
||||
this.watch()
|
||||
},
|
||||
actions: id => {
|
||||
return `
|
||||
<td class="right aligned">
|
||||
<button class="ui green mini icon button approve" data-id="${id}" title="Aprobar">
|
||||
<i class="check icon"></i>
|
||||
@ -343,6 +363,51 @@
|
||||
<i class="trash icon"></i>
|
||||
</button>
|
||||
</td>`
|
||||
},
|
||||
tooltip: () => {
|
||||
return {
|
||||
oferta: reservation => {
|
||||
const formatter = new Intl.NumberFormat('es-CL', {minimumFractionDigits: 2, maximumFractionDigits: 2})
|
||||
|
||||
const output = []
|
||||
const table = ['<table>']
|
||||
reservation.units.forEach(unit => {
|
||||
const type = unit.unit.proyecto_tipo_unidad.tipo_unidad.descripcion
|
||||
table.push(`<tr><td>${type.charAt(0).toUpperCase() + type.slice(1)} ${unit.unit.descripcion}:</td><td align='right'>${formatter.format(unit.value)} UF</td></tr>`)
|
||||
})
|
||||
if (reservation.broker !== null) {
|
||||
table.push('<tr><td>-----</td></tr>')
|
||||
let commission = reservation.broker.commission
|
||||
table.push(`<tr><td>Broker:</td><td align='right'>${reservation.broker.name}</td><td align='right'>(${commission})</td></tr>`)
|
||||
}
|
||||
if (reservation.promotions.length > 0) {
|
||||
table.push('<tr><td>-----</td></tr>')
|
||||
reservation.promotions.forEach(promotion => {
|
||||
let value = 0
|
||||
switch (promotion.type) {
|
||||
case {{ \Incoviba\Model\Venta\Promotion\Type::FIXED }}:
|
||||
value = `${formatter.format(promotion.amount)} UF`
|
||||
break;
|
||||
case {{ \Incoviba\Model\Venta\Promotion\Type::VARIABLE }}:
|
||||
value = `${formatter.format(promotion.amount * 100)} %`
|
||||
break;
|
||||
}
|
||||
table.push(`<tr><td>${promotion.description}:</td><td align='right'>${value}</td></tr>`)
|
||||
})
|
||||
}
|
||||
table.push('</table>')
|
||||
output.push(table.join(''))
|
||||
return output.join("<br />")
|
||||
},
|
||||
cliente: reservation => {
|
||||
const formatter = new Intl.NumberFormat('es-CL', {minimumFractionDigits: 0, maximumFractionDigits: 0})
|
||||
return [
|
||||
`RUT: ${formatter.format(reservation.buyer.rut)}-${reservation.buyer.digito}`
|
||||
].join("<br />")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
watch() {
|
||||
if (Object.keys(this.actions).length === 0) {
|
||||
@ -412,8 +477,10 @@
|
||||
return row
|
||||
})
|
||||
}
|
||||
drawActions(id) {
|
||||
return `
|
||||
draw() {
|
||||
const draw = super.draw()
|
||||
draw.actions = (id) => {
|
||||
return `
|
||||
<td class="right aligned">
|
||||
<button class="ui green mini icon button edit" data-id="${id}" title="Promesar">
|
||||
<i class="right chevron icon"></i>
|
||||
@ -422,6 +489,8 @@
|
||||
<i class="trash icon"></i>
|
||||
</button>
|
||||
</td>`
|
||||
}
|
||||
return draw
|
||||
}
|
||||
actions = {
|
||||
edit: event => {
|
||||
@ -448,6 +517,56 @@
|
||||
super({component_id, formatters})
|
||||
}
|
||||
|
||||
draw() {
|
||||
const draw = super.draw()
|
||||
const tooltip = draw.tooltip()
|
||||
tooltip['valida'] = reservation => {
|
||||
const formatter = new Intl.NumberFormat('es-CL', {minimumFractionDigits: 2, maximumFractionDigits: 2})
|
||||
|
||||
const output = []
|
||||
const table = [
|
||||
'<table>',
|
||||
'<thead>',
|
||||
'<tr>',
|
||||
'<th></th>',
|
||||
'<th>Base Oferta</th>',
|
||||
'<th>Precio</th>',
|
||||
'</thead>'
|
||||
]
|
||||
reservation.units.forEach(unit => {
|
||||
let type = unit.unit.proyecto_tipo_unidad.tipo_unidad.descripcion
|
||||
type = type.charAt(0).toUpperCase() + type.slice(1)
|
||||
const base = unit.base ?? (unit.value ?? 0);
|
||||
const price = unit.unit.current_precio?.valor ?? 0
|
||||
const diff = (base - price) / price * 100
|
||||
table.push(`<tr><td>${type} ${unit.unit.descripcion}:</td><td align='right'> ${formatter.format(base)} UF</td><td align='right'>${formatter.format(price)} UF</td><td align='right'>(${formatter.format(diff)} %)</td></tr>`)
|
||||
})
|
||||
if (reservation.broker !== null) {
|
||||
table.push('<tr><td>-----</td></tr>')
|
||||
let commission = reservation.broker.commission
|
||||
table.push(`<tr><td>Broker:</td><td align='right'>${reservation.broker.name}</td><td align='right'>(${commission})</td></tr>`)
|
||||
}
|
||||
reservation.promotions.forEach(promotion => {
|
||||
let value = 0
|
||||
switch (promotion.type) {
|
||||
case {{ \Incoviba\Model\Venta\Promotion\Type::FIXED }}:
|
||||
value = `${formatter.format(promotion.amount)} UF`
|
||||
break;
|
||||
case {{ \Incoviba\Model\Venta\Promotion\Type::VARIABLE }}:
|
||||
value = `${formatter.format(promotion.amount * 100)} %`
|
||||
break;
|
||||
}
|
||||
table.push(`<tr><td>${promotion.description}:</td><td align='right'>${value}</td></tr>`)
|
||||
})
|
||||
table.push('</table>')
|
||||
output.push(table.join(''))
|
||||
return output.join("<br />")
|
||||
}
|
||||
draw['tooltip'] = () => {
|
||||
return tooltip
|
||||
}
|
||||
return draw
|
||||
}
|
||||
actions = {
|
||||
approve: event => {
|
||||
event.preventDefault()
|
||||
@ -482,8 +601,12 @@
|
||||
return data[idx]
|
||||
})
|
||||
}
|
||||
drawActions(id) {
|
||||
return ''
|
||||
draw() {
|
||||
const draw = super.draw()
|
||||
draw.actions = (id) => {
|
||||
return ''
|
||||
}
|
||||
return draw
|
||||
}
|
||||
watch() {}
|
||||
|
||||
@ -522,7 +645,7 @@
|
||||
if (json.reservations.length > 0) {
|
||||
component.set.reservations(json.reservations)
|
||||
}
|
||||
component.draw()
|
||||
component.draw().tbody()
|
||||
})
|
||||
},
|
||||
active: project_id => {
|
||||
|
||||
@ -131,6 +131,41 @@
|
||||
<h4 class="ui dividing header">Unidades <span id="add_project_name"></span></h4>
|
||||
<div class="fields" id="add_unit_buttons"></div>
|
||||
<div id="add_units"></div>
|
||||
<h4 class="ui dividing header">Forma de Pago</h4>
|
||||
<div class="fields">
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="has_pie" id="add_has_pie" />
|
||||
<label>¿Tiene Pie?</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field" id="add_pie">
|
||||
<label>Pie</label>
|
||||
<div class="ui right labeled input">
|
||||
<input type="text" name="pie" />
|
||||
<div class="ui basic label">UF</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field" id="add_cuotas">
|
||||
<label>Cuotas</label>
|
||||
<input type="text" name="cuotas" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="fields">
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="has_credit" id="add_has_credit" />
|
||||
<label>¿Tiene Crédito?</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field" id="add_credit">
|
||||
<label>Crédito</label>
|
||||
<div class="ui right labeled input">
|
||||
<input type="text" name="credit" />
|
||||
<div class="ui basic label">UF</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="actions">
|
||||
@ -153,7 +188,8 @@
|
||||
elements: ''
|
||||
}
|
||||
data = {
|
||||
promotions: []
|
||||
promotions: [],
|
||||
selected: []
|
||||
}
|
||||
components = {
|
||||
button: null,
|
||||
@ -171,16 +207,16 @@
|
||||
this.setup()
|
||||
}
|
||||
add() {
|
||||
const idx = Math.max(this.data.promotions.length, 0, Math.max(...this.data.promotions) + 1)
|
||||
this.data.promotions.push(idx)
|
||||
const idx = Math.max(this.data.selected.length, 0, Math.max(...this.data.selected) + 1)
|
||||
this.data.selected.push(idx)
|
||||
this.draw.promotions()
|
||||
}
|
||||
reset() {
|
||||
this.data.promotions = []
|
||||
this.data.selected = []
|
||||
this.draw.promotions()
|
||||
}
|
||||
remove(idx) {
|
||||
this.data.promotions = this.data.promotions.filter(promotion => promotion !== idx)
|
||||
this.data.selected = this.data.selected.filter(promotion => promotion !== idx)
|
||||
this.draw.promotions()
|
||||
}
|
||||
draw = {
|
||||
@ -213,7 +249,10 @@
|
||||
return
|
||||
}
|
||||
this.components.button.parentElement.style.display = this.display.button
|
||||
this.components.promotions.innerHTML = this.data.promotions.map((promotion, idx) => {
|
||||
if (this.data.selected.length === 0) {
|
||||
return
|
||||
}
|
||||
this.components.promotions.innerHTML = this.data.selected.map(idx => {
|
||||
return this.draw.promotion(idx)
|
||||
}).join('')
|
||||
this.components.promotions.querySelectorAll('.dropdown').forEach(dropdown => {
|
||||
@ -362,7 +401,7 @@
|
||||
'<div class="three wide field">',
|
||||
'<label>Valor</label>',
|
||||
'<div class="ui right labeled input">',
|
||||
'<input type="number" name="add_units_value[]" placeholder="Valor" />',
|
||||
'<input type="text" name="add_units_value[]" placeholder="Valor" />',
|
||||
'<div class="ui basic label">UF</div>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
@ -394,6 +433,101 @@
|
||||
this.draw.buttons()
|
||||
}
|
||||
}
|
||||
class AddModalPayments {
|
||||
ids = {
|
||||
pie: {
|
||||
checkbox: 'add_has_pie',
|
||||
value: 'add_pie',
|
||||
installments: 'add_cuotas'
|
||||
},
|
||||
credit: {
|
||||
checkbox: 'add_has_credit',
|
||||
value: 'add_credit'
|
||||
}
|
||||
}
|
||||
components = {
|
||||
pie: {
|
||||
$checkbox: null,
|
||||
value: null,
|
||||
installments: null
|
||||
},
|
||||
credit: {
|
||||
$checkbox: null,
|
||||
value: null
|
||||
}
|
||||
}
|
||||
data = {
|
||||
pie: {
|
||||
value: '',
|
||||
installments: ''
|
||||
},
|
||||
credit: {
|
||||
value: ''
|
||||
}
|
||||
}
|
||||
constructor() {
|
||||
this.setup()
|
||||
}
|
||||
reset() {
|
||||
this.components.pie.$checkbox.prop('checked', false)
|
||||
this.components.pie.value.value = ''
|
||||
this.components.pie.installments.value = ''
|
||||
this.components.credit.$checkbox.prop('checked', false)
|
||||
this.components.credit.value.value = ''
|
||||
}
|
||||
show = {
|
||||
pie: () => {
|
||||
this.components.pie.value.style.display = this.data.pie.value
|
||||
this.components.pie.installments.style.display = this.data.pie.installments
|
||||
},
|
||||
credit: () => {
|
||||
this.components.credit.value.style.display = this.data.credit.value
|
||||
}
|
||||
}
|
||||
hide = {
|
||||
pie: () => {
|
||||
this.components.pie.value.style.display = 'none'
|
||||
this.components.pie.installments.style.display = 'none'
|
||||
},
|
||||
credit: () => {
|
||||
this.components.credit.value.style.display = 'none'
|
||||
},
|
||||
all: () => {
|
||||
this.hide.pie()
|
||||
this.hide.credit()
|
||||
}
|
||||
}
|
||||
setup() {
|
||||
this.components.pie.$checkbox = $(`#${this.ids.pie.checkbox}`)
|
||||
this.components.pie.value = document.getElementById(this.ids.pie.value)
|
||||
this.components.pie.installments = document.getElementById(this.ids.pie.installments)
|
||||
this.components.credit.$checkbox = $(`#${this.ids.credit.checkbox}`)
|
||||
this.components.credit.value = document.getElementById(this.ids.credit.value)
|
||||
|
||||
this.components.pie.$checkbox.checkbox()
|
||||
this.components.pie.$checkbox.change(changeEvent => {
|
||||
if (this.components.pie.$checkbox.is(':checked')) {
|
||||
this.show.pie()
|
||||
return
|
||||
}
|
||||
this.hide.pie()
|
||||
})
|
||||
this.components.credit.$checkbox.checkbox()
|
||||
this.components.credit.$checkbox.change(changeEvent => {
|
||||
if (this.components.credit.$checkbox.is(':checked')) {
|
||||
this.show.credit()
|
||||
return
|
||||
}
|
||||
this.hide.credit()
|
||||
})
|
||||
|
||||
this.data.pie.value = this.components.pie.value.style.display
|
||||
this.data.pie.installments = this.components.pie.installments.style.display
|
||||
this.data.credit.value = this.components.credit.value.style.display
|
||||
|
||||
this.hide.all()
|
||||
}
|
||||
}
|
||||
class AddReservationModal {
|
||||
ids = {
|
||||
modal: '',
|
||||
@ -429,6 +563,7 @@
|
||||
project_name: null,
|
||||
unit_buttons: null,
|
||||
units: null,
|
||||
payments: null,
|
||||
$loader: null
|
||||
}
|
||||
data = {
|
||||
@ -480,8 +615,8 @@
|
||||
this.get.promotions(project_id).then(promotions => {
|
||||
this.components.promotions.data.promotions = promotions.map(promotion => {
|
||||
return {
|
||||
text: promotion.name,
|
||||
name: promotion.name,
|
||||
text: promotion.description,
|
||||
name: promotion.description,
|
||||
value: promotion.id
|
||||
}
|
||||
})
|
||||
@ -509,6 +644,7 @@
|
||||
this.components.form.reset()
|
||||
this.components.promotions.reset()
|
||||
this.components.units.reset()
|
||||
this.components.payments.reset()
|
||||
}
|
||||
add() {
|
||||
const url = '/api/ventas/reservation/add'
|
||||
@ -524,6 +660,16 @@
|
||||
const birthdate = this.components.$birthdate.calendar('get date')
|
||||
body.set('add_buyer_birthdate', [birthdate.getFullYear(), birthdate.getMonth() + 1, birthdate.getDate()].join('-'))
|
||||
|
||||
if (this.components.payments.components.pie.$checkbox.checkbox('is unchecked')) {
|
||||
body.delete('add_pie')
|
||||
body.delete('add_cuotas')
|
||||
}
|
||||
body.delete('add_has_pie')
|
||||
if (this.components.payments.components.credit.$checkbox.checkbox('is unchecked')) {
|
||||
body.delete('add_credit')
|
||||
}
|
||||
body.delete('add_has_credit')
|
||||
|
||||
body.delete('comuna')
|
||||
body.delete('region')
|
||||
body.delete('broker')
|
||||
@ -672,6 +818,9 @@
|
||||
}
|
||||
fill = {
|
||||
user: user => {
|
||||
if (typeof user === 'undefined' || user === null) {
|
||||
return
|
||||
}
|
||||
const form = this.components.form
|
||||
form.querySelector('input[name="add_buyer_name"]').value = user.nombres || ''
|
||||
form.querySelector('input[name="add_buyer_last_name"]').value = user.apellidoPaterno || ''
|
||||
@ -753,6 +902,7 @@
|
||||
this.components.projects = document.getElementById(this.ids.projects)
|
||||
this.components.project_name = document.getElementById(this.ids.project_name)
|
||||
this.components.units = new AddModalUnits(this)
|
||||
this.components.payments = new AddModalPayments()
|
||||
|
||||
this.components.$modal.modal({
|
||||
onApprove: () => {
|
||||
|
||||
@ -22,10 +22,13 @@ class Reservation extends Common\Ideal\Model
|
||||
public function withCommission(): float
|
||||
{
|
||||
$base = 0;
|
||||
foreach ($this->units as $unit) {
|
||||
foreach ($this->units as &$unit) {
|
||||
$unitBase = $unit->value;
|
||||
foreach ($this->promotions as $promotion) {
|
||||
$base += $promotion->activate()->reverse($unit['unit'], $unit['value'], $this->broker);
|
||||
$unitBase = $promotion->activate()->reverse($unit->unit, $unitBase, $this->broker);
|
||||
}
|
||||
$unit->base = $unitBase;
|
||||
$base += $unitBase;
|
||||
}
|
||||
return $base;
|
||||
}
|
||||
|
||||
@ -63,7 +63,7 @@ class Datos extends Ideal\Repository
|
||||
'persona_rut', 'direccion_id', 'telefono', 'email', 'fecha_nacimiento', 'sexo', 'estado_civil',
|
||||
'nacionalidad', 'ocupacion'
|
||||
], [
|
||||
$model->persona->rut, $model->direccion?->id, $model->telefono, $model->email, $model->fechaNacimiento,
|
||||
$model->persona->rut, $model->direccion?->id, $model->telefono, $model->email, $model->fechaNacimiento->format('Y-m-d'),
|
||||
$model->sexo, $model->estadoCivil, $model->nacionalidad, $model->ocupacion
|
||||
]);
|
||||
return $model;
|
||||
|
||||
@ -236,6 +236,9 @@ class Persona extends Ideal\Service
|
||||
} else {
|
||||
$newKey = substr($key, strlen('address_'));
|
||||
}
|
||||
if ($newKey === 'id') {
|
||||
continue;
|
||||
}
|
||||
$addressData[$newKey] = $value;
|
||||
}
|
||||
if (!empty($addressData)) {
|
||||
@ -258,7 +261,7 @@ class Persona extends Ideal\Service
|
||||
'birthdate' => 'fecha_nacimiento',
|
||||
];
|
||||
foreach ($data as $key => $value) {
|
||||
if (array_key_exists($key, $dataMap)) {
|
||||
if (array_key_exists($key, $dataMap) and trim($value) !== '') {
|
||||
$data[$dataMap[$key]] = $value;
|
||||
unset($data[$key]);
|
||||
}
|
||||
|
||||
@ -251,6 +251,9 @@ class Reservation extends Ideal\Service\API
|
||||
return $this->stateRepository->fetchByReservation($reservation_id);
|
||||
})
|
||||
);
|
||||
foreach ($model->units as &$unit) {
|
||||
$unit->unit = $this->unitService->getById($unit->unit->id);
|
||||
}
|
||||
$model->buyer = $this->personaService->getById($model->buyer->rut);
|
||||
return $model;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user