Matriz facturacion
This commit is contained in:
@ -3,4 +3,5 @@ use Incoviba\Controller\API\Ventas\Facturacion;
|
|||||||
|
|
||||||
$app->group('/facturacion', function($app) {
|
$app->group('/facturacion', function($app) {
|
||||||
$app->get('/proyecto/{proyecto_id}[/]', [Facturacion::class, 'proyecto']);
|
$app->get('/proyecto/{proyecto_id}[/]', [Facturacion::class, 'proyecto']);
|
||||||
|
$app->post('/get[/]', [Facturacion::class, 'ventas']);
|
||||||
});
|
});
|
||||||
|
@ -60,25 +60,33 @@
|
|||||||
return this.ufs[json.input.fecha] = json.uf
|
return this.ufs[json.input.fecha] = json.uf
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
ipc: (end, start) => {
|
ipc: ({end, start}) => {
|
||||||
const dateKey = [start.getFullYear(), (start.getMonth()+1), end.getFullYear(), (end.getMonth()+1)].join('-')
|
const dateKey = [start.getFullYear(), (start.getMonth()+1), end.getFullYear(), (end.getMonth()+1)].join('-')
|
||||||
if (typeof this.sent.ipc[dateKey] !== 'undefined') {
|
if (typeof this.sent.ipc[dateKey] !== 'undefined') {
|
||||||
return this.sent.ipc[dateKey]
|
return this.sent.ipc[dateKey]
|
||||||
}
|
}
|
||||||
|
let mult = 1
|
||||||
|
if (start > end) {
|
||||||
|
const tmp = structuredClone(end)
|
||||||
|
end = structuredClone(start)
|
||||||
|
start = tmp
|
||||||
|
mult = -1
|
||||||
|
}
|
||||||
const url = '{{$urls->api}}/money/ipc'
|
const url = '{{$urls->api}}/money/ipc'
|
||||||
const data = new FormData()
|
const data = new FormData()
|
||||||
data.set('start', start.toISOString())
|
data.set('start', [start.getFullYear() + ((start.getMonth() > 0) ? 0 : -1), start.getMonth(), start.getDate()].join('-'))
|
||||||
data.set('end', end.toISOString())
|
data.set('end', [end.getFullYear() + ((end.getMonth() > 0) ? 0 : -1), end.getMonth(), end.getDate()].join('-'))
|
||||||
const options = {
|
const options = {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
body: data
|
body: data
|
||||||
}
|
}
|
||||||
return this.sent.ipc[dateKey] = fetchAPI(url, options).then(response => {
|
return this.sent.ipc[dateKey] = fetchAPI(url, options).then(response => {
|
||||||
if (response.ok) {
|
if (!response) {
|
||||||
return response.json()
|
return
|
||||||
}
|
}
|
||||||
}).then(json => {
|
return response.json().then(json => {
|
||||||
return this.ipcs[json.date_string] = json.ipc
|
return this.ipcs[dateKey] = json.ipc * mult
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,8 +100,7 @@
|
|||||||
prorrateo
|
prorrateo
|
||||||
precio
|
precio
|
||||||
|
|
||||||
constructor({id, tipo, descripcion, prorrateo, precio})
|
constructor({id, tipo, descripcion, prorrateo, precio}) {
|
||||||
{
|
|
||||||
this.id = id
|
this.id = id
|
||||||
this.tipo = tipo
|
this.tipo = tipo
|
||||||
this.descripcion = descripcion
|
this.descripcion = descripcion
|
||||||
@ -111,44 +118,13 @@
|
|||||||
unidades
|
unidades
|
||||||
principal
|
principal
|
||||||
|
|
||||||
constructor({id, precio, fecha, escritura}) {
|
constructor({id, precio, fecha, escritura, unidades, principal}) {
|
||||||
this.id = id
|
this.id = id
|
||||||
this.precio = precio
|
this.precio = precio
|
||||||
this.fecha = fecha
|
this.fecha = new Date(fecha)
|
||||||
this.escritura = escritura
|
this.escritura = new Date(escritura)
|
||||||
this.uf = 1
|
this.unidades = unidades
|
||||||
this.ipc = 1
|
this.principal = principal
|
||||||
this.unidades = []
|
|
||||||
}
|
|
||||||
|
|
||||||
get() {
|
|
||||||
return {
|
|
||||||
unidades: () => {
|
|
||||||
const url = '{{$urls->api}}/venta/' + this.id + '/unidades'
|
|
||||||
return fetchAPI(url).then(response => {
|
|
||||||
if (response.ok) {
|
|
||||||
return response.json()
|
|
||||||
}
|
|
||||||
}).then(json => {
|
|
||||||
json.unidades.forEach(unidad => {
|
|
||||||
const tipo = unidad.proyecto_tipo_unidad.tipo_unidad.descripcion
|
|
||||||
const data = {
|
|
||||||
id: unidad.id,
|
|
||||||
tipo: tipo.charAt(0).toUpperCase() + tipo.slice(1),
|
|
||||||
descripcion: unidad.descripcion,
|
|
||||||
prorrateo: unidad.prorrateo,
|
|
||||||
precio: 0
|
|
||||||
}
|
|
||||||
if (unidad.current_precio !== null) {
|
|
||||||
data.precio = unidad.current_precio.valor
|
|
||||||
}
|
|
||||||
const u = new Unidad(data)
|
|
||||||
this.unidades.push(u)
|
|
||||||
})
|
|
||||||
this.principal = this.unidades.filter(unidad => unidad.tipo === 'Departamento')[0]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
draw({tbody, valor_terreno}) {
|
draw({tbody, valor_terreno}) {
|
||||||
@ -173,7 +149,7 @@
|
|||||||
const dateFormatter = new Intl.DateTimeFormat('es-CL', {year: 'numeric', month: 'numeric', day: 'numeric'})
|
const dateFormatter = new Intl.DateTimeFormat('es-CL', {year: 'numeric', month: 'numeric', day: 'numeric'})
|
||||||
const pesosFormatter = new Intl.NumberFormat('es-CL', {style: 'currency', currency: 'CLP'})
|
const pesosFormatter = new Intl.NumberFormat('es-CL', {style: 'currency', currency: 'CLP'})
|
||||||
const ufFormatter = new Intl.NumberFormat('es-CL', {minimumFractionDigits: 2, maximumFractionDigits: 2})
|
const ufFormatter = new Intl.NumberFormat('es-CL', {minimumFractionDigits: 2, maximumFractionDigits: 2})
|
||||||
const venta = this.unidades[0].descripcion
|
const venta = this.principal.descripcion
|
||||||
const cantidad = this.unidades.length
|
const cantidad = this.unidades.length
|
||||||
this.unidades.forEach(unidad => {
|
this.unidades.forEach(unidad => {
|
||||||
const values = [
|
const values = [
|
||||||
@ -195,7 +171,8 @@
|
|||||||
''
|
''
|
||||||
]
|
]
|
||||||
if (this.escritura !== null) {
|
if (this.escritura !== null) {
|
||||||
const descuento = valor_terreno * (1 + this.ipc / 100) * unidad.prorrateo
|
const ipc = (this.ipc >= 0) ? (1 + this.ipc) : 1 / (1 + this.ipc)
|
||||||
|
const descuento = valor_terreno * ipc * unidad.prorrateo
|
||||||
const precio_venta = unidad.precio * this.uf
|
const precio_venta = unidad.precio * this.uf
|
||||||
const precio_bruto = precio_venta - descuento
|
const precio_bruto = precio_venta - descuento
|
||||||
const precio_neto = precio_bruto / 1.19
|
const precio_neto = precio_bruto / 1.19
|
||||||
@ -210,7 +187,7 @@
|
|||||||
values[i++] = (iva / precio_venta * 100).toFixed(2) + '%'
|
values[i++] = (iva / precio_venta * 100).toFixed(2) + '%'
|
||||||
values[i++] = dateFormatter.format(this.escritura)
|
values[i++] = dateFormatter.format(this.escritura)
|
||||||
values[i++] = ufFormatter.format(this.uf)
|
values[i++] = ufFormatter.format(this.uf)
|
||||||
values[i++] = (this.ipc).toFixed(2) + '%'
|
values[i++] = ufFormatter.format(this.ipc >= 0 ? this.ipc * 100 : -this.ipc * 100) + '%'
|
||||||
}
|
}
|
||||||
const row = $('<tr></tr>')
|
const row = $('<tr></tr>')
|
||||||
values.forEach(value => {
|
values.forEach(value => {
|
||||||
@ -227,6 +204,10 @@
|
|||||||
selected: 0,
|
selected: 0,
|
||||||
data: JSON.parse('{!! json_encode($proyectos) !!}'),
|
data: JSON.parse('{!! json_encode($proyectos) !!}'),
|
||||||
sent: false,
|
sent: false,
|
||||||
|
queues: {
|
||||||
|
uf: {},
|
||||||
|
ipc: {}
|
||||||
|
},
|
||||||
ufs: {},
|
ufs: {},
|
||||||
ipcs: {},
|
ipcs: {},
|
||||||
table: null,
|
table: null,
|
||||||
@ -243,89 +224,99 @@
|
|||||||
if (!response) {
|
if (!response) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return response.json()
|
return response.json().then(json => {
|
||||||
}).then(json => {
|
const idx = this.data.findIndex(proyecto => proyecto.id === json.proyecto_id)
|
||||||
const idx = this.data.findIndex(proyecto => proyecto.id === json.proyecto_id)
|
this.data[idx]['ventas'] = []
|
||||||
const fecha_terreno = (typeof this.data[idx].terreno.date === 'undefined') ? new Date() : new Date(this.data[idx].terreno.date)
|
const ventas = []
|
||||||
this.data[idx]['ventas'] = []
|
const chunkSize = 100
|
||||||
const ventas = []
|
for (let i = 0; i < json.ventas.length; i += chunkSize) {
|
||||||
const unidadesQueue = []
|
const chunk = json.ventas.slice(i, i + chunkSize).map(venta => venta.id)
|
||||||
const ufQueue = {}
|
ventas.push(this.get().chunk({idx, chunk}))
|
||||||
const ipcQueue = {}
|
|
||||||
const chunkSize = 100
|
|
||||||
const url = '{{$urls->api}}/ventas/get'
|
|
||||||
for (let i = 0; i < json.ventas.length; i += chunkSize) {
|
|
||||||
const chunk = json.ventas.slice(i, i + chunkSize).map(venta => venta.id)
|
|
||||||
const body = new FormData()
|
|
||||||
body.set('ventas', chunk)
|
|
||||||
const promise = fetchAPI(url, {method: 'post', body}).then(response => {
|
|
||||||
if (!response) {
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
return response.json().then(json => {
|
|
||||||
json.ventas.forEach(venta => {
|
|
||||||
const data = {
|
|
||||||
id: venta.id,
|
|
||||||
precio: venta.valor,
|
|
||||||
fecha: new Date(venta.fecha),
|
|
||||||
escritura: new Date(venta.fecha)
|
|
||||||
}
|
|
||||||
if (['escriturando'].includes(venta.current_estado.tipo_estado_venta.descripcion)) {
|
|
||||||
data.escritura = new Date(venta.current_estado.fecha)
|
|
||||||
}
|
|
||||||
const v = new Venta(data)
|
|
||||||
if (v.escritura !== null) {
|
|
||||||
const dateString = v.escritura.toString()
|
|
||||||
if (!Object.hasOwn(ufQueue, dateString)) {
|
|
||||||
ufQueue[dateString] = []
|
|
||||||
}
|
|
||||||
ufQueue[dateString].push(v.id)
|
|
||||||
if (!Object.hasOwn(ipcQueue, dateString)) {
|
|
||||||
ipcQueue[dateString] = []
|
|
||||||
}
|
|
||||||
ipcQueue[dateString].push(v.id)
|
|
||||||
}
|
|
||||||
unidadesQueue.push(v.id)
|
|
||||||
this.data[idx].ventas.push(v)
|
|
||||||
|
|
||||||
})
|
|
||||||
});
|
|
||||||
})
|
|
||||||
ventas.push(promise)
|
|
||||||
}
|
|
||||||
Promise.all(ventas).then(() => {
|
|
||||||
const promises = []
|
|
||||||
Object.entries(ufQueue).forEach(([dateString, ventas]) => {
|
|
||||||
const date = new Date(dateString)
|
|
||||||
promises.push(money.get().uf(date).then(uf => {
|
|
||||||
ventas.forEach(id => {
|
|
||||||
const vidx = this.data[idx].ventas.findIndex(venta => venta.id === id)
|
|
||||||
this.data[idx].ventas[vidx].uf = uf
|
|
||||||
})
|
|
||||||
}))
|
|
||||||
})
|
|
||||||
Object.entries(ipcQueue).forEach(([dateString, ventas]) => {
|
|
||||||
const date = new Date(dateString)
|
|
||||||
promises.push(money.get().ipc(date, fecha_terreno).then(ipc => {
|
|
||||||
ventas.forEach(id => {
|
|
||||||
const vidx = this.data[idx].ventas.findIndex(venta => venta.id === id)
|
|
||||||
this.data[idx].ventas[vidx].ipc = ipc
|
|
||||||
})
|
|
||||||
}))
|
|
||||||
})
|
|
||||||
for (let i = 0; i < unidadesQueue.length; i += chunkSize) {
|
|
||||||
const chunk = unidadesQueue.slice(i, i + chunkSize)
|
|
||||||
chunk.forEach(id => {
|
|
||||||
const vidx = this.data[idx].ventas.findIndex(venta => venta.id === id)
|
|
||||||
promises.push(this.data[idx].ventas[vidx].get().unidades())
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
Promise.all(promises).then(() => {
|
Promise.all(ventas).then(() => {
|
||||||
this.draw().ventas(idx)
|
const promises = []
|
||||||
this.sent = false
|
promises.push(...this.get().ufs(idx))
|
||||||
|
promises.push(...this.get().ipcs(idx))
|
||||||
|
Promise.all(promises).then(() => {
|
||||||
|
this.draw().ventas(idx)
|
||||||
|
this.sent = false
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
chunk: ({idx, chunk}) => {
|
||||||
|
const url = '{{$urls->api}}/ventas/facturacion/get'
|
||||||
|
const method = 'post'
|
||||||
|
const body = new FormData()
|
||||||
|
body.set('ventas', chunk)
|
||||||
|
|
||||||
|
return fetchAPI(url, {method, body}).then(response => {
|
||||||
|
if (!response) {
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
return response.json().then(json => {
|
||||||
|
json.ventas.forEach(venta => {
|
||||||
|
this.add().venta({proyecto_idx: idx, venta})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
})
|
||||||
|
},
|
||||||
|
ufs: idx => {
|
||||||
|
const promises = []
|
||||||
|
Object.entries(this.queues.uf).forEach(([dateString, ventas]) => {
|
||||||
|
const date = new Date(dateString)
|
||||||
|
promises.push(money.get().uf(date).then(uf => {
|
||||||
|
ventas.forEach(id => {
|
||||||
|
const vidx = this.data[idx].ventas.findIndex(venta => venta.id === id)
|
||||||
|
this.data[idx].ventas[vidx].uf = uf
|
||||||
|
})
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
return promises
|
||||||
|
},
|
||||||
|
ipcs: idx => {
|
||||||
|
const fecha_terreno = (typeof this.data[idx].terreno.date === 'undefined') ? new Date() : new Date(this.data[idx].terreno.date)
|
||||||
|
const promises = []
|
||||||
|
Object.entries(this.queues.ipc).forEach(([dateString, ventas]) => {
|
||||||
|
const date = new Date(dateString)
|
||||||
|
promises.push(money.get().ipc({end: date, start: fecha_terreno}).then(ipc => {
|
||||||
|
ventas.forEach(id => {
|
||||||
|
const vidx = this.data[idx].ventas.findIndex(venta => venta.id === id)
|
||||||
|
this.data[idx].ventas[vidx].ipc = ipc
|
||||||
|
})
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
return promises
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
add() {
|
||||||
|
return {
|
||||||
|
venta: ({proyecto_idx, venta}) => {
|
||||||
|
const v = new Venta(venta)
|
||||||
|
this.data[proyecto_idx].ventas.push(v)
|
||||||
|
if (v.escritura !== null) {
|
||||||
|
const dateString = v.escritura.toString()
|
||||||
|
this.register().uf({dateString, venta_id: v.id})
|
||||||
|
this.register().ipc({dateString, venta_id: v.id})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
register() {
|
||||||
|
return {
|
||||||
|
uf: ({dateString, venta_id}) => {
|
||||||
|
if (!Object.hasOwn(this.queues.uf, dateString)) {
|
||||||
|
this.queues.uf[dateString] = []
|
||||||
|
}
|
||||||
|
this.queues.uf[dateString].push(venta_id)
|
||||||
|
},
|
||||||
|
ipc: ({dateString, venta_id}) => {
|
||||||
|
if (!Object.hasOwn(this.queues.ipc, dateString)) {
|
||||||
|
this.queues.ipc[dateString] = []
|
||||||
|
}
|
||||||
|
this.queues.ipc[dateString].push(venta_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -887,178 +887,6 @@
|
|||||||
].join("\n")
|
].join("\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*const output = [
|
|
||||||
'<div class="ui divider" data-index="'+propietario.props.index+'"></div>'+
|
|
||||||
'<div class="factura" data-index="'+propietario.props.index+'">'+
|
|
||||||
'<div class="ui compact grid">'+
|
|
||||||
'<div class="two columns row">'+
|
|
||||||
'<div class="twelve wide column">'+
|
|
||||||
'<strong>'+proyecto.inmobiliaria.nombre.toUpperCase()+'</strong><br/>'+
|
|
||||||
'GIRO: <br/>'+
|
|
||||||
'Dirección:'+proyecto.direccion+
|
|
||||||
'</div>'+
|
|
||||||
'<div class="four wide column">'+
|
|
||||||
'<div class="ui center aligned red segment">'+
|
|
||||||
'<strong>'+
|
|
||||||
'RUT:'+proyecto.inmobiliaria.rut.toUpperCase()+'<br/>'+
|
|
||||||
'FACTURA ELECTRÓNICA<br/>'+
|
|
||||||
'N° #'+
|
|
||||||
'</strong>'+
|
|
||||||
'</div>'+
|
|
||||||
'</div>'+
|
|
||||||
'</div>'+
|
|
||||||
'<div class="row">'+
|
|
||||||
'<table class="ui table">'+
|
|
||||||
'<tr>'+
|
|
||||||
'<td class="grey"><strong>Señor(es)</strong></td>'+
|
|
||||||
'<td>'+propietario.props.nombre+'</td>'+
|
|
||||||
'<td class="grey"><strong>RUT</strong></td>'+
|
|
||||||
'<td>'+propietario.props.rut.toUpperCase()+'</td>'+
|
|
||||||
'</tr>'+
|
|
||||||
'<tr>'+
|
|
||||||
'<td class="grey"><strong>Giro</strong></td>'+
|
|
||||||
'<td>Otras Actividades Profesionales</td>'+
|
|
||||||
'<td class="grey"><strong>Fecha Emisión</strong></td>'+
|
|
||||||
'<td>'+formatters.date.format(propietario.props.fecha)+'</td>'+
|
|
||||||
'</tr>'+
|
|
||||||
'<tr>'+
|
|
||||||
'<td class="grey"><strong>Dirección</strong></td>'+
|
|
||||||
'<td>'+propietario.props.direccion+'</td>'+
|
|
||||||
'<td class="grey"><strong>Comuna</strong></td>'+
|
|
||||||
'<td>'+propietario.props.comuna.toUpperCase()+'</td>'+
|
|
||||||
'</tr>'+
|
|
||||||
'</table>'+
|
|
||||||
'</div>'+
|
|
||||||
'<div class="row">'+
|
|
||||||
'<table class="ui celled table">'+
|
|
||||||
'<thead>'+
|
|
||||||
'<tr class="grey">'+
|
|
||||||
'<th class="center aligned" colspan="6">DETALLES</th>'+
|
|
||||||
'</tr>'+
|
|
||||||
'<tr class="grey">'+
|
|
||||||
'<th>N°</th>'+
|
|
||||||
'<th class="center aligned">Descripción</th>'+
|
|
||||||
'<th class="center aligned">Cant/Unidad</th>'+
|
|
||||||
'<th class="center aligned">Prec. Unit.</th>'+
|
|
||||||
'<th class="center aligned">Ind</th>'+
|
|
||||||
'<th class="center aligned">Total</th>'+
|
|
||||||
'</tr>'+
|
|
||||||
'</thead>'
|
|
||||||
]
|
|
||||||
const unidadesData = []
|
|
||||||
|
|
||||||
let c = 1
|
|
||||||
const classes = [
|
|
||||||
'',
|
|
||||||
'',
|
|
||||||
'center aligned',
|
|
||||||
'right aligned',
|
|
||||||
'center aligned',
|
|
||||||
'right aligned'
|
|
||||||
]
|
|
||||||
const uf_mult = this.props.uf / uf
|
|
||||||
unidades.forEach(unidad => {
|
|
||||||
const descuento = parseFloat(proyecto.terreno) * parseFloat(unidad.prorrateo) * uf_mult
|
|
||||||
const bruto = parseFloat(unidad.base) * uf_mult - descuento
|
|
||||||
const neto = bruto / 1.19
|
|
||||||
const data = [
|
|
||||||
c ++,
|
|
||||||
unidad.descripcion + ' (UF ' + formatters.ufs.format(unidad.precio * this.props.proporcion * uf_mult) + ')',
|
|
||||||
'1 UNID',
|
|
||||||
formatters.pesos.format(neto * this.props.proporcion),
|
|
||||||
'AF',
|
|
||||||
formatters.pesos.format(neto * this.props.proporcion)
|
|
||||||
]
|
|
||||||
|
|
||||||
const row = ['<tr>']
|
|
||||||
data.forEach((value, i) => {
|
|
||||||
const cell = ['<td']
|
|
||||||
if (classes[i] !== '') {
|
|
||||||
cell.push(' class="'+classes[i]+'"')
|
|
||||||
}
|
|
||||||
cell.push('>'+value+'</td>')
|
|
||||||
row.push(cell.join(''))
|
|
||||||
})
|
|
||||||
row.push('</tr>')
|
|
||||||
unidadesData.push(row.join(''))
|
|
||||||
})
|
|
||||||
|
|
||||||
const emptyTerreno = '<div class="ui tiny red horizontal circular label">0</div>'
|
|
||||||
const data = [
|
|
||||||
c,
|
|
||||||
'Valor con Terreno ' + formatters.pesos.format((venta.base * uf_mult + venta.terreno * uf_mult) * this.props.proporcion) + ' - Menos valor terreno ' + ((venta.terreno > 0) ? formatters.pesos.format(-venta.terreno * uf_mult * this.props.proporcion) : emptyTerreno) + '<br />' +
|
|
||||||
'Base imponible ' + formatters.pesos.format(venta.base * uf_mult * this.props.proporcion) + '<br />' +
|
|
||||||
'IVA ' + formatters.pesos.format(venta.iva * uf_mult * this.props.proporcion) + '<br />' +
|
|
||||||
'SUBTOTAL ' + formatters.pesos.format(venta.subtotal * uf_mult * this.props.proporcion) + '<br />' +
|
|
||||||
'Mas valor terreno ' + ((venta.terreno > 0) ? formatters.pesos.format(venta.terreno * uf_mult * this.props.proporcion) : emptyTerreno) + '<br />' +
|
|
||||||
'TOTAL ' + formatters.pesos.format(venta.total * uf_mult * this.props.proporcion) + ';' + formatters.ufs.format(venta.totalUF * this.props.proporcion) + ' UF<br /><br />' +
|
|
||||||
'Descuento Terreno: ' + ((venta.terreno > 0) ? formatters.percent.format(venta.prorrateo * 100) : emptyTerreno) + '%<br /><br />' +
|
|
||||||
'UF: ' + formatters.ufs.format(uf),
|
|
||||||
'1 UNID',
|
|
||||||
formatters.pesos.format(venta.terreno * uf_mult * this.props.proporcion),
|
|
||||||
'EX',
|
|
||||||
formatters.pesos.format(venta.terreno * uf_mult * this.props.proporcion)
|
|
||||||
]
|
|
||||||
|
|
||||||
const row = ['<tr class="top aligned">']
|
|
||||||
data.forEach((value, i) => {
|
|
||||||
const cell = ['<td']
|
|
||||||
if (classes[i] !== '') {
|
|
||||||
cell.push(' class="'+classes[i]+'"')
|
|
||||||
}
|
|
||||||
cell.push('>'+value+'</td>')
|
|
||||||
row.push(cell.join(''))
|
|
||||||
})
|
|
||||||
unidadesData.push(row.join(''))
|
|
||||||
|
|
||||||
output.push('<tbody id="unidades">'+unidadesData.join('')+'</tbody>')
|
|
||||||
output.push(
|
|
||||||
'<tfoot>'+
|
|
||||||
'<tr>'+
|
|
||||||
'<td colspan="6">'+
|
|
||||||
'<br />'+
|
|
||||||
'<br />'+
|
|
||||||
'<br />'+
|
|
||||||
'<br />'+
|
|
||||||
'</td>'+
|
|
||||||
'</tr>'+
|
|
||||||
'</tfoot>'+
|
|
||||||
'</table>'+
|
|
||||||
'</div>'+
|
|
||||||
'<div class="row">'+
|
|
||||||
'<div class="ten wide column"></div>'+
|
|
||||||
'<div class="six wide column">'+
|
|
||||||
'<table class="ui celled very compact table">'+
|
|
||||||
'<thead>'+
|
|
||||||
'<tr>'+
|
|
||||||
'<th class="center aligned grey" colspan="2">TOTALES</th>'+
|
|
||||||
'</tr>'+
|
|
||||||
'</thead>'+
|
|
||||||
'<tbody>'+
|
|
||||||
'<tr>'+
|
|
||||||
'<td class="grey">Monto Neto</td>'+
|
|
||||||
'<td class="right aligned" id="neto">'+formatters.pesos.format(venta.neto * uf_mult * this.props.proporcion)+'</td>'+
|
|
||||||
'</tr>'+
|
|
||||||
'<tr>'+
|
|
||||||
'<td class="grey">Monto Exento</td>'+
|
|
||||||
'<td class="right aligned" id="exento">'+formatters.pesos.format(venta.exento * uf_mult * this.props.proporcion)+'</td>'+
|
|
||||||
'</tr>'+
|
|
||||||
'<tr>'+
|
|
||||||
'<td class="grey">19% IVA</td>'+
|
|
||||||
'<td class="right aligned" id="iva">'+formatters.pesos.format(venta.iva * uf_mult * this.props.proporcion)+'</td>'+
|
|
||||||
'</tr>'+
|
|
||||||
'<tr>'+
|
|
||||||
'<td class="grey">Monto Total</td>'+
|
|
||||||
'<td class="right aligned"><strong id="total">'+formatters.pesos.format(venta.total * uf_mult * this.props.proporcion)+'</strong></td>'+
|
|
||||||
'</tr>'+
|
|
||||||
'</tbody>'+
|
|
||||||
'</table>'+
|
|
||||||
'</div>'+
|
|
||||||
'</div>'+
|
|
||||||
'</div>'+
|
|
||||||
'</div>'
|
|
||||||
)
|
|
||||||
return output.join('')*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,16 +2,15 @@
|
|||||||
namespace Incoviba\Controller\API\Ventas;
|
namespace Incoviba\Controller\API\Ventas;
|
||||||
|
|
||||||
use DateTimeImmutable;
|
use DateTimeImmutable;
|
||||||
use Incoviba\Common\Implement\Exception\EmptyRedis;
|
|
||||||
use Incoviba\Common\Implement\Exception\EmptyResult;
|
|
||||||
use Incoviba\Controller\API\emptyBody;
|
|
||||||
use Incoviba\Controller\API\withJson;
|
|
||||||
use Incoviba\Controller\withRedis;
|
|
||||||
use Incoviba\Service;
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Incoviba\Common\Implement\Exception\{EmptyRedis,EmptyResult};
|
||||||
|
use Incoviba\Controller\API\{emptyBody,withJson};
|
||||||
|
use Incoviba\Controller\withRedis;
|
||||||
|
use Incoviba\Service;
|
||||||
|
use Incoviba\Common\Ideal;
|
||||||
|
|
||||||
class Facturacion
|
class Facturacion extends Ideal\Service
|
||||||
{
|
{
|
||||||
use withJson, withRedis, emptyBody;
|
use withJson, withRedis, emptyBody;
|
||||||
|
|
||||||
@ -34,4 +33,31 @@ class Facturacion
|
|||||||
}
|
}
|
||||||
return $this->withJson($response, $output);
|
return $this->withJson($response, $output);
|
||||||
}
|
}
|
||||||
|
public function ventas(ServerRequestInterface $request, ResponseInterface $response, Service\Redis $redisService,
|
||||||
|
Service\Venta $ventaService, Service\Proyecto\Terreno $terrenoService, Service\UF $ufService,
|
||||||
|
Service\IPC $ipcService): ResponseInterface
|
||||||
|
{
|
||||||
|
$input = $request->getParsedBody();
|
||||||
|
$output = [
|
||||||
|
'input' => $input,
|
||||||
|
'ventas' => []
|
||||||
|
];
|
||||||
|
$ventas = explode(',', $input['ventas']);
|
||||||
|
foreach ($ventas as $venta_id) {
|
||||||
|
$redisKey = "ventas:facturacion:venta:{$venta_id}";
|
||||||
|
try {
|
||||||
|
$venta = $this->fetchRedis($redisService, $redisKey);
|
||||||
|
$output['ventas'] []= $venta;
|
||||||
|
} catch (EmptyRedis) {
|
||||||
|
try {
|
||||||
|
$venta = $ventaService->getFacturacionById($venta_id);
|
||||||
|
$output['ventas'] []= $venta;
|
||||||
|
$this->saveRedis($redisService, $redisKey, $venta);
|
||||||
|
} catch (EmptyResult $exception) {
|
||||||
|
$this->logger->notice($exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $this->withJson($response, $output);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,12 @@
|
|||||||
namespace Incoviba\Service;
|
namespace Incoviba\Service;
|
||||||
|
|
||||||
use DateTimeImmutable;
|
use DateTimeImmutable;
|
||||||
|
use DateInterval;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
use Incoviba\Common\Ideal\Service;
|
use Incoviba\Common\Ideal\Service;
|
||||||
use Incoviba\Common\Implement;
|
use Incoviba\Common\Implement;
|
||||||
use Incoviba\Repository;
|
use Incoviba\Repository;
|
||||||
use Incoviba\Model;
|
use Incoviba\Model;
|
||||||
use Psr\Log\LoggerInterface;
|
|
||||||
|
|
||||||
class Venta extends Service
|
class Venta extends Service
|
||||||
{
|
{
|
||||||
@ -27,6 +28,7 @@ class Venta extends Service
|
|||||||
protected Venta\Credito $creditoService,
|
protected Venta\Credito $creditoService,
|
||||||
protected Venta\BonoPie $bonoPieService,
|
protected Venta\BonoPie $bonoPieService,
|
||||||
protected Venta\Pago $pagoService,
|
protected Venta\Pago $pagoService,
|
||||||
|
protected Proyecto\Terreno $terrenoService,
|
||||||
protected Money $moneyService
|
protected Money $moneyService
|
||||||
) {
|
) {
|
||||||
parent::__construct($logger);
|
parent::__construct($logger);
|
||||||
@ -91,6 +93,33 @@ class Venta extends Service
|
|||||||
{
|
{
|
||||||
return $this->process($this->ventaRepository->fetchByPie($pie_id));
|
return $this->process($this->ventaRepository->fetchByPie($pie_id));
|
||||||
}
|
}
|
||||||
|
public function getFacturacionById(int $venta_id): array
|
||||||
|
{
|
||||||
|
$venta = $this->getById($venta_id);
|
||||||
|
$escritura = (in_array($venta->currentEstado()->tipoEstadoVenta->descripcion, ['escriturando'])) ? $venta->currentEstado()->fecha : $venta->fecha;
|
||||||
|
$data = [
|
||||||
|
'id' => $venta->id,
|
||||||
|
'fecha' => $venta->fecha->format('Y-m-d'),
|
||||||
|
'valor' => $venta->valor,
|
||||||
|
'escritura' => $escritura->format('Y-m-d'),
|
||||||
|
'unidades' => [],
|
||||||
|
];
|
||||||
|
foreach ($venta->propiedad()->unidades as $unidad) {
|
||||||
|
$data['unidades'] []= [
|
||||||
|
'id' => $unidad->id,
|
||||||
|
'tipo' => ucwords($unidad->proyectoTipoUnidad->tipoUnidad->descripcion),
|
||||||
|
'descripcion' => $unidad->descripcion,
|
||||||
|
'prorrateo' => $unidad->prorrateo,
|
||||||
|
'precio' => (isset($unidad->currentPrecio)) ? $unidad->currentPrecio->valor : 0
|
||||||
|
];
|
||||||
|
}
|
||||||
|
$principal = $venta->propiedad()->principal();
|
||||||
|
$data['principal'] = [
|
||||||
|
'id' => $principal->id,
|
||||||
|
'descripcion' => $principal->descripcion
|
||||||
|
];
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
protected function process(Model\Venta $venta): Model\Venta
|
protected function process(Model\Venta $venta): Model\Venta
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user