Facturacion
This commit is contained in:
7
app/resources/routes/api/money.php
Normal file
7
app/resources/routes/api/money.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
use Incoviba\Controller\API\Money;
|
||||
|
||||
$app->group('/money', function($app) {
|
||||
$app->post('/ipc[/]', [Money::class, 'ipc']);
|
||||
$app->post('[/]', [Money::class, 'get']);
|
||||
});
|
@ -22,6 +22,7 @@ $app->group('/ventas', function($app) {
|
||||
$app->post('[/]', [Ventas::class, 'proyecto']);
|
||||
});
|
||||
$app->group('/venta/{venta_id}', function($app) {
|
||||
$app->get('/unidades', [Ventas::class, 'unidades']);
|
||||
$app->get('/comentarios', [Ventas::class, 'comentarios']);
|
||||
$app->get('[/]', [Ventas::class, 'get']);
|
||||
});
|
||||
|
6
app/resources/routes/api/ventas/facturacion.php
Normal file
6
app/resources/routes/api/ventas/facturacion.php
Normal file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
use Incoviba\Controller\API\Ventas\Facturacion;
|
||||
|
||||
$app->group('/facturacion', function($app) {
|
||||
$app->get('/proyecto/{proyecto_id}[/]', [Facturacion::class, 'proyecto']);
|
||||
});
|
6
app/resources/routes/ventas/facturacion.php
Normal file
6
app/resources/routes/ventas/facturacion.php
Normal file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
use Incoviba\Controller\Ventas\Facturacion;
|
||||
|
||||
$app->group('/facturacion', function($app) {
|
||||
$app->get('[/]', Facturacion::class);
|
||||
});
|
@ -224,6 +224,7 @@
|
||||
const proyecto_id = element.data('proyecto')
|
||||
this.get().tipos(proyecto_id)
|
||||
})
|
||||
$('#data').hide()
|
||||
}
|
||||
}
|
||||
$(document).ready(() => {
|
||||
|
384
app/resources/views/ventas/facturacion.blade.php
Normal file
384
app/resources/views/ventas/facturacion.blade.php
Normal file
@ -0,0 +1,384 @@
|
||||
@extends('layout.base')
|
||||
|
||||
@section('page_content')
|
||||
<div class="ui container">
|
||||
<h2 class="ui header">Matriz Facturación</h2>
|
||||
<h4 class="ui dividing header">
|
||||
<div class="ui two column grid">
|
||||
<div id="list_title" class="column">Proyectos</div>
|
||||
<div class="right aligned column">
|
||||
<div class="ui tiny icon buttons">
|
||||
<button id="up_button" class="ui button">
|
||||
<i class="up arrow icon"></i>
|
||||
</button>
|
||||
<button id="refresh_button" class="ui button">
|
||||
<i class="refresh icon"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</h4>
|
||||
<div id="proyectos" class="ui link selection list">
|
||||
@foreach ($proyectos as $proyecto)
|
||||
<div class="item" data-proyecto="{{$proyecto->id}}">{{$proyecto->descripcion}}</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
<table class="ui table" id="data"></table>
|
||||
@endsection
|
||||
|
||||
@include('layout.head.styles.datatables')
|
||||
@include('layout.body.scripts.datatables')
|
||||
|
||||
@push('page_scripts')
|
||||
<script>
|
||||
const money = {
|
||||
ufs: {},
|
||||
ipcs: {},
|
||||
sent: {
|
||||
uf: {},
|
||||
ipc: {}
|
||||
},
|
||||
get() {
|
||||
return {
|
||||
uf: date => {
|
||||
if (typeof this.sent.uf[date.toISOString()] !== 'undefined') {
|
||||
return this.sent.uf[date.toISOString()]
|
||||
}
|
||||
const url = '{{$urls->api}}/money'
|
||||
const data = new FormData()
|
||||
data.set('provider', 'uf')
|
||||
data.set('fecha', date.toISOString())
|
||||
const options = {
|
||||
method: 'post',
|
||||
body: data
|
||||
}
|
||||
return this.sent.uf[date.toISOString()] = fetch(url, options).then(response => {
|
||||
if (response.ok) {
|
||||
return response.json()
|
||||
}
|
||||
}).then(json => {
|
||||
return this.ufs[json.input.fecha] = json.uf
|
||||
})
|
||||
},
|
||||
ipc: (end, start) => {
|
||||
const dateKey = [start.getFullYear(), (start.getMonth()+1), end.getFullYear(), (end.getMonth()+1)].join('-')
|
||||
if (typeof this.sent.ipc[dateKey] !== 'undefined') {
|
||||
return this.sent.ipc[dateKey]
|
||||
}
|
||||
const url = '{{$urls->api}}/money/ipc'
|
||||
const data = new FormData()
|
||||
data.set('provider', 'ipc')
|
||||
data.set('start', start.toISOString())
|
||||
data.set('end', end.toISOString())
|
||||
const options = {
|
||||
method: 'post',
|
||||
body: data
|
||||
}
|
||||
return this.sent.ipc[dateKey] = fetch(url, options).then(response => {
|
||||
if (response.ok) {
|
||||
return response.json()
|
||||
}
|
||||
}).then(json => {
|
||||
return this.ipcs[json.date_string] = json.ipc
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Unidad {
|
||||
id
|
||||
tipo
|
||||
descripcion
|
||||
prorrateo
|
||||
precio
|
||||
|
||||
constructor({id, tipo, descripcion, prorrateo, precio})
|
||||
{
|
||||
this.id = id
|
||||
this.tipo = tipo
|
||||
this.descripcion = descripcion
|
||||
this.prorrateo = prorrateo
|
||||
this.precio = precio
|
||||
}
|
||||
}
|
||||
class Venta {
|
||||
id
|
||||
precio
|
||||
fecha
|
||||
escritura
|
||||
uf
|
||||
ipc
|
||||
unidades
|
||||
principal
|
||||
|
||||
constructor({id, precio, fecha, escritura}) {
|
||||
this.id = id
|
||||
this.precio = precio
|
||||
this.fecha = fecha
|
||||
this.escritura = escritura
|
||||
this.uf = 1
|
||||
this.ipc = 1
|
||||
this.unidades = []
|
||||
}
|
||||
|
||||
get() {
|
||||
return {
|
||||
unidades: () => {
|
||||
const url = '{{$urls->api}}/venta/' + this.id + '/unidades'
|
||||
return fetch(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}) {
|
||||
/**
|
||||
'Venta',
|
||||
'Unidades',
|
||||
'Tipo',
|
||||
'Unidad',
|
||||
'Fecha Promesa',
|
||||
'Valor Promesa',
|
||||
'Prorrateo',
|
||||
'Descuento',
|
||||
'Precio Venta',
|
||||
'Precio Bruto',
|
||||
'IVA',
|
||||
'Precio Neto',
|
||||
'% IVA/Neto',
|
||||
'Fecha Escritura',
|
||||
'UF',
|
||||
'IPC'
|
||||
*/
|
||||
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 ufFormatter = new Intl.NumberFormat('es-CL', {minimumFractionDigits: 2, maximumFractionDigits: 2})
|
||||
const venta = this.unidades[0].descripcion
|
||||
const cantidad = this.unidades.length
|
||||
this.unidades.forEach(unidad => {
|
||||
const values = [
|
||||
venta,
|
||||
cantidad,
|
||||
unidad.tipo,
|
||||
unidad.descripcion,
|
||||
dateFormatter.format(this.fecha),
|
||||
ufFormatter.format(unidad.precio) + ' UF',
|
||||
unidad.prorrateo,
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
''
|
||||
]
|
||||
if (this.escritura !== null) {
|
||||
const descuento = valor_terreno * (1 + this.ipc / 100) * unidad.prorrateo
|
||||
const precio_venta = unidad.precio * this.uf
|
||||
const precio_bruto = precio_venta - descuento
|
||||
const precio_neto = precio_bruto / 1.19
|
||||
const iva = precio_bruto - precio_neto
|
||||
|
||||
let i = 7
|
||||
values[i++] = pesosFormatter.format(descuento)
|
||||
values[i++] = pesosFormatter.format(precio_venta)
|
||||
values[i++] = pesosFormatter.format(precio_bruto)
|
||||
values[i++] = pesosFormatter.format(iva)
|
||||
values[i++] = pesosFormatter.format(precio_neto)
|
||||
values[i++] = (iva / precio_venta * 100).toFixed(2) + '%'
|
||||
values[i++] = dateFormatter.format(this.escritura)
|
||||
values[i++] = ufFormatter.format(this.uf)
|
||||
values[i++] = (this.ipc).toFixed(2) + '%'
|
||||
}
|
||||
const row = $('<tr></tr>')
|
||||
values.forEach(value => {
|
||||
row.append(
|
||||
$('<td></td>').html(value)
|
||||
)
|
||||
})
|
||||
tbody.append(row)
|
||||
})
|
||||
}
|
||||
}
|
||||
const proyectos = {
|
||||
ids: {},
|
||||
selected: 0,
|
||||
data: JSON.parse('{!! json_encode($proyectos) !!}'),
|
||||
table: null,
|
||||
get: function() {
|
||||
return {
|
||||
ventas: () => {
|
||||
const url = '{{$urls->api}}/ventas/facturacion/proyecto/' + this.selected
|
||||
return fetch(url).then(response => {
|
||||
if (response.ok) {
|
||||
return response.json()
|
||||
}
|
||||
}).then(json => {
|
||||
const idx = this.data.findIndex(proyecto => proyecto.id === json.proyecto_id)
|
||||
const fecha_terreno = new Date(this.data[idx].terreno.date)
|
||||
this.data[idx]['ventas'] = []
|
||||
const ventas = []
|
||||
json.ventas.forEach(venta => {
|
||||
const data = {
|
||||
id: venta.id,
|
||||
precio: venta.valor,
|
||||
fecha: new Date(venta.fecha),
|
||||
escritura: null
|
||||
}
|
||||
if (['escriturando'].includes(venta.current_estado.tipo_estado_venta.descripcion)) {
|
||||
data.escritura = new Date(venta.current_estado.fecha)
|
||||
}
|
||||
const v = new Venta(data)
|
||||
const promises = []
|
||||
if (v.escritura !== null) {
|
||||
promises.push(money.get().uf(v.escritura).then(uf => {
|
||||
v.uf = uf
|
||||
}))
|
||||
promises.push(money.get().ipc(v.escritura, fecha_terreno).then(ipc => {
|
||||
v.ipc = ipc
|
||||
}))
|
||||
}
|
||||
promises.push(v.get().unidades())
|
||||
const promise = Promise.all(promises).then(() => {
|
||||
this.data[idx].ventas.push(v)
|
||||
})
|
||||
ventas.push(promise)
|
||||
})
|
||||
Promise.all(ventas).then(() => {
|
||||
this.data[idx].ventas.sort((a, b) => parseInt(a.principal.descripcion) - parseInt(b.principal.descripcion))
|
||||
this.draw().ventas(idx)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
draw: function() {
|
||||
return {
|
||||
proyectos: () => {
|
||||
if (this.table !== null) {
|
||||
this.table.clear()
|
||||
}
|
||||
$(this.ids.data).hide()
|
||||
$(this.ids.proyectos).show()
|
||||
},
|
||||
ventas: proyecto_idx => {
|
||||
const table = $(this.ids.data)
|
||||
if (this.table !== null) {
|
||||
this.table.clear().destroy()
|
||||
}
|
||||
table.append(this.draw().thead())
|
||||
table.append(this.draw().tbody(proyecto_idx))
|
||||
table.show()
|
||||
$(this.ids.proyectos).hide()
|
||||
if (this.table === null) {
|
||||
this.table = table.DataTable()
|
||||
}
|
||||
},
|
||||
thead: () => {
|
||||
const thead = $('<thead></thead>')
|
||||
const columns = [
|
||||
'Venta',
|
||||
'Unidades',
|
||||
'Tipo',
|
||||
'Unidad',
|
||||
'Fecha Promesa',
|
||||
'Valor Promesa',
|
||||
'Prorrateo',
|
||||
'Descuento',
|
||||
'Precio Venta',
|
||||
'Precio Bruto',
|
||||
'IVA',
|
||||
'Precio Neto',
|
||||
'% IVA/Neto',
|
||||
'Fecha Escritura',
|
||||
'UF',
|
||||
'IPC'
|
||||
]
|
||||
const row = $('<tr></tr>')
|
||||
columns.forEach(title => {
|
||||
row.append(
|
||||
$('<th></th>').html(title)
|
||||
)
|
||||
})
|
||||
thead.append(row)
|
||||
return thead
|
||||
},
|
||||
tbody: proyecto_idx => {
|
||||
const tbody = $('<tbody></tbody>')
|
||||
this.data[proyecto_idx].ventas.forEach(venta => {
|
||||
venta.draw({tbody, valor_terreno: this.data[proyecto_idx].terreno.valor})
|
||||
})
|
||||
return tbody
|
||||
}
|
||||
}
|
||||
},
|
||||
actions: function() {
|
||||
return {
|
||||
up: event => {
|
||||
this.draw().proyectos()
|
||||
},
|
||||
refresh: event => {
|
||||
const list = $(this.ids.proyectos)
|
||||
if (list.is(':hidden')) {
|
||||
const table = $(this.ids.table)
|
||||
table.hide()
|
||||
if (this.table !== null) {
|
||||
this.table.clear().destroy()
|
||||
this.table = null
|
||||
}
|
||||
this.get().ventas()
|
||||
} else {
|
||||
this.draw().proyectos()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
setup: function({ids}) {
|
||||
this.ids = ids
|
||||
$(this.ids.data).hide()
|
||||
$(this.ids.proyectos).find('.item').click(event => {
|
||||
this.selected = $(event.currentTarget).data('proyecto')
|
||||
this.get().ventas()
|
||||
})
|
||||
|
||||
$(this.ids.buttons.up).click(this.actions().up)
|
||||
$(this.ids.buttons.refresh).click(this.actions().refresh)
|
||||
}
|
||||
}
|
||||
$(document).ready(() => {
|
||||
proyectos.setup({ids: {
|
||||
proyectos: '#proyectos',
|
||||
data: '#data',
|
||||
buttons: {
|
||||
up: '#up_button',
|
||||
refresh: '#refresh_button'
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
@endpush
|
11
app/resources/views/ventas/facturacion/show.blade.php
Normal file
11
app/resources/views/ventas/facturacion/show.blade.php
Normal file
@ -0,0 +1,11 @@
|
||||
@extends('layout.base')
|
||||
|
||||
@section('page_content')
|
||||
<div class="ui container">
|
||||
<form id="venta_form">
|
||||
<div class="field">
|
||||
<label for=""></label>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@endsection
|
Reference in New Issue
Block a user