feat: add companion2 support, fix UI rendering, and update test data generator

This commit is contained in:
2026-06-22 02:31:08 -04:00
parent 81251fb869
commit ac0dd65efa
10 changed files with 268 additions and 27 deletions

View File

@@ -246,6 +246,7 @@ def init_db():
worker_id INTEGER NOT NULL,
worker_comision BOOLEAN DEFAULT 1,
companion_id INTEGER,
companion2_id INTEGER,
modulo_id INTEGER NOT NULL,
fecha DATE NOT NULL,
hora_entrada TEXT NOT NULL,
@@ -253,6 +254,7 @@ def init_db():
companion_hora_entrada TEXT,
companion_hora_salida TEXT,
companion_comision BOOLEAN DEFAULT 0,
companion2_comision BOOLEAN DEFAULT 0,
venta_debito INTEGER DEFAULT 0,
venta_credito INTEGER DEFAULT 0,
venta_mp INTEGER DEFAULT 0,
@@ -265,6 +267,7 @@ def init_db():
observaciones TEXT,
FOREIGN KEY (worker_id) REFERENCES workers(id),
FOREIGN KEY (companion_id) REFERENCES workers(id),
FOREIGN KEY (companion2_id) REFERENCES workers(id),
FOREIGN KEY (modulo_id) REFERENCES modulos(id))''')
c.execute('''CREATE TABLE IF NOT EXISTS rendicion_items
(id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -283,6 +286,13 @@ def init_db():
except sqlite3.OperationalError:
pass # column already exists
# Migrate: add companion2 columns
for col in ['companion2_id', 'companion2_comision']:
try:
c.execute(f"ALTER TABLE rendiciones ADD COLUMN {col}")
except sqlite3.OperationalError:
pass
c.execute("SELECT id FROM workers WHERE is_admin = 1")
if not c.fetchone():
admin_pass = generate_password_hash("admin123")

View File

@@ -122,13 +122,29 @@ def generar_historico_definitivo(dias_atras=180):
companion_id = None
comp_in, comp_out = None, None
companion_comision = 0
companion2_id = None
companion2_comision = 0
if random.random() < 0.70:
posibles_comp = [w for w in todos_los_trabajadores if w != worker_id]
posibles_comp = [w for w in workers_modulo if w != worker_id]
if posibles_comp:
companion_id = random.choice(posibles_comp)
comp_in, comp_out = hora_entrada, hora_salida
comp_tipo = workers_tipo.get(companion_id, "Part Time")
companion_comision = 1 if comp_tipo == "Full Time" else random.choice([0, 1])
# Acompañante 2 (25% probability if companion 1 is present)
if random.random() < 0.25:
posibles_comp2 = [w for w in posibles_comp if w != companion_id]
if posibles_comp2:
companion2_id = random.choice(posibles_comp2)
comp2_tipo = workers_tipo.get(companion2_id, "Part Time")
companion2_comision = 1 if comp2_tipo == "Full Time" else random.choice([0, 1])
# If there is no companion, comision should be disabled (0)
if companion_id is None:
companion_comision = 0
if companion2_id is None:
companion2_comision = 0
num_prods = random.randint(1, 5)
prods_elegidos = random.sample(productos, min(num_prods, len(productos)))
@@ -171,16 +187,16 @@ def generar_historico_definitivo(dias_atras=180):
c.execute('''
INSERT INTO rendiciones
(worker_id, worker_comision, companion_id, modulo_id, fecha,
(worker_id, worker_comision, companion_id, companion2_id, modulo_id, fecha,
hora_entrada, hora_salida, companion_hora_entrada, companion_hora_salida,
companion_comision,
companion_comision, companion2_comision,
venta_debito, venta_credito, venta_mp, venta_efectivo,
boletas_debito, boletas_credito, boletas_mp, boletas_efectivo,
gastos, observaciones)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
''', (worker_id, worker_comision, companion_id, modulo_id, fecha_str,
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
''', (worker_id, worker_comision, companion_id, companion2_id, modulo_id, fecha_str,
hora_entrada, hora_salida, comp_in, comp_out,
companion_comision,
companion_comision, companion2_comision,
debito, credito, mp, efectivo,
b_debito, b_credito, b_mp, b_efectivo,
gastos, tipo_registro))

View File

@@ -69,6 +69,7 @@ class Rendicion(db.Model):
worker_id = db.Column(db.Integer, db.ForeignKey('workers.id'), nullable=False)
worker_comision = db.Column(db.Boolean, default=True)
companion_id = db.Column(db.Integer, db.ForeignKey('workers.id'))
companion2_id = db.Column(db.Integer, db.ForeignKey('workers.id'))
modulo_id = db.Column(db.Integer, db.ForeignKey('modulos.id'), nullable=False)
fecha = db.Column(db.Date, nullable=False)
hora_entrada = db.Column(db.String, nullable=False)
@@ -76,6 +77,7 @@ class Rendicion(db.Model):
companion_hora_entrada = db.Column(db.String)
companion_hora_salida = db.Column(db.String)
companion_comision = db.Column(db.Boolean, default=False)
companion2_comision = db.Column(db.Boolean, default=False)
venta_debito = db.Column(db.Integer, default=0)
venta_credito = db.Column(db.Integer, default=0)
venta_mp = db.Column(db.Integer, default=0)

View File

@@ -2,3 +2,4 @@ Flask==3.1.3
Flask-SQLAlchemy==3.1.1
Werkzeug==3.1.6
SQLAlchemy==2.0.45
openpyxl==3.1.5

View File

@@ -1,4 +1,4 @@
from flask import Blueprint, render_template, request, redirect, url_for, flash, session, jsonify
from flask import Blueprint, render_template, request, redirect, url_for, flash, session, jsonify, send_file
from werkzeug.security import generate_password_hash
from sqlalchemy import func, and_
from sqlalchemy.exc import IntegrityError
@@ -489,8 +489,18 @@ def edit_rendicion(id):
if companion_id and worker_id == companion_id:
flash("Error: No puedes asignarte a ti mismo como acompañante.", "danger")
return redirect(url_for('admin.admin_rendiciones'))
companion2_id = request.form.get('companion2_id') or None
if companion2_id and worker_id == companion2_id:
flash("Error: No puedes asignarte a ti mismo como acompañante 2.", "danger")
return redirect(url_for('admin.admin_rendiciones'))
worker_comision = 1 if request.form.get('worker_comision') else 0
companion_comision = 1 if request.form.get('companion_comision') else 0
companion2_comision = 1 if request.form.get('companion2_comision') else 0
if not companion_id:
companion_comision = 0
if not companion2_id:
companion2_comision = 0
def clean_money(val):
if not val:
@@ -527,8 +537,10 @@ def edit_rendicion(id):
rendicion.worker_id = int(worker_id)
rendicion.modulo_id = int(modulo_id)
rendicion.companion_id = int(companion_id) if companion_id else None
rendicion.companion2_id = int(companion2_id) if companion2_id else None
rendicion.worker_comision = bool(worker_comision)
rendicion.companion_comision = bool(companion_comision)
rendicion.companion2_comision = bool(companion2_comision)
rendicion.venta_debito = debito
rendicion.venta_credito = credito
rendicion.venta_mp = mp
@@ -653,3 +665,129 @@ def report_modulo_calculo_iva(modulo_id):
workers_list=workers_list, worker_actual=worker_id,
fecha_inicio=fecha_inicio, fecha_fin=fecha_fin,
anios_disponibles=anios_list)
@admin_bp.route('/reportes/modulo/<int:modulo_id>/exportar_excel')
@admin_required
def report_modulo_exportar_excel(modulo_id):
fecha_inicio, fecha_fin, worker_id = get_report_params()
data = report_service.get_modulo_periodo_data(modulo_id, fecha_inicio, fecha_fin, worker_id)
mod_name, _, _ = report_service.get_modulo_workers_and_anios(modulo_id)
import io
import openpyxl
from openpyxl.styles import Font, Alignment, PatternFill, Border, Side
from openpyxl.utils import get_column_letter
wb = openpyxl.Workbook()
ws = wb.active
ws.title = "Detalle Ventas"
thin = Side(style='thin')
border = Border(left=thin, right=thin, top=thin, bottom=thin)
center = Alignment(horizontal='center', vertical='center')
# ── column colors matching web table ──
col_colors = {
2: '198754', # Venta Total → text-success green
3: '0DCAF0', # Comisión → text-info cyan
4: 'DC3545', # Gastos → text-danger red
5: '6C757D', # Crédito → text-muted gray
6: '6C757D', # Débito → text-muted gray
7: '6C757D', # Mercado Pago → text-muted gray
8: '6C757D', # Efectivo/Dep. → text-muted gray
9: 'e5904d', # Red. Crédito → custom orange
10: 'e5904d', # Red. Débito → custom orange
11: 'e5904d', # Red. MP → custom orange
12: '20c997', # REDELCOM Neto → teal
13: 'FFC107', # Efectivo - Gastos → text-warning
14: '0D6EFD', # Venta Total Neto → text-primary blue
}
hdr_fill = PatternFill(start_color="2B303A", end_color="2B303A", fill_type="solid")
ws.merge_cells('A1:O1')
ws['A1'] = f"Resumen Financiero — {mod_name} ({fecha_inicio} a {fecha_fin})"
ws['A1'].font = Font(bold=True, size=14)
headers = ['Día', 'Venta Total', 'Comisión', 'Gastos',
'Crédito', 'Débito', 'Mercado Pago', 'Efectivo/Dep.',
'Red. Crédito', 'Red. Débito', 'Red. MP',
'REDELCOM Neto', 'Efectivo - Gastos', 'Venta Total Neto']
for col, h in enumerate(headers, 1):
cell = ws.cell(row=3, column=col, value=h)
cell.fill = hdr_fill
cell.alignment = center
cell.border = border
font_color = col_colors.get(col, 'FFFFFF')
cell.font = Font(bold=True, color=font_color, size=11)
for row_idx, dia in enumerate(data['dias_en_periodo'], 4):
d = data['data_por_dia'][dia]
vals = [
dia,
d['venta_total'],
d['comision'],
d['gastos'],
d['credito'],
d['debito'],
d['mp'],
d['efectivo'],
d['credito'] * 0.97620,
d['debito'] * 0.98453,
d['mp'] * 0.98691,
d['credito'] * 0.97620 + d['debito'] * 0.98453 + d['mp'] * 0.98691,
d['efectivo'] - d['gastos'],
d['credito'] * 0.97620 + d['debito'] * 0.98453 + d['mp'] * 0.98691 + d['efectivo'] - d['gastos'],
]
for col, v in enumerate(vals, 1):
cell = ws.cell(row=row_idx, column=col, value=v)
cell.border = border
if col == 1:
cell.alignment = center
else:
cell.number_format = '#,##0'
if col in col_colors:
cell.font = Font(color=col_colors[col])
total_row = 4 + len(data['dias_en_periodo'])
totals = data['totales_mes']
total_vals = [
'TOTAL',
totals['venta_total'],
totals['comision'],
totals['gastos'],
totals['credito'],
totals['debito'],
totals['mp'],
totals['efectivo'],
totals['credito'] * 0.97620,
totals['debito'] * 0.98453,
totals['mp'] * 0.98691,
totals['credito'] * 0.97620 + totals['debito'] * 0.98453 + totals['mp'] * 0.98691,
totals['efectivo'] - totals['gastos'],
totals['credito'] * 0.97620 + totals['debito'] * 0.98453 + totals['mp'] * 0.98691 + totals['efectivo'] - totals['gastos'],
]
total_fill = PatternFill(start_color="2B303A", end_color="2B303A", fill_type="solid")
for col, v in enumerate(total_vals, 1):
cell = ws.cell(row=total_row, column=col, value=v)
cell.fill = total_fill
cell.border = border
if col == 1:
cell.alignment = center
cell.font = Font(bold=True, color="FFFFFF", size=11)
else:
cell.number_format = '#,##0'
font_color = col_colors.get(col, 'FFFFFF')
cell.font = Font(bold=True, color=font_color, size=11)
for col in range(1, 16):
ws.column_dimensions[get_column_letter(col)].width = 16
ws.column_dimensions['A'].width = 8
output = io.BytesIO()
wb.save(output)
output.seek(0)
filename = f"reporte_{mod_name}_{fecha_inicio}_{fecha_fin}.xlsx".replace(' ', '_')
return send_file(output, as_attachment=True, download_name=filename,
mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')

View File

@@ -31,6 +31,7 @@ def get_filtered_rendiciones(fecha_inicio, fecha_fin, zona_id, modulo_id):
fin = datetime.strptime(fecha_fin, '%Y-%m-%d').date()
Companion = aliased(Worker)
Companion2 = aliased(Worker)
filters = [
Rendicion.fecha >= inicio,
@@ -52,11 +53,14 @@ def get_filtered_rendiciones(fecha_inicio, fecha_fin, zona_id, modulo_id):
Companion.name.label('companion_name'),
Rendicion.worker_id, Rendicion.companion_id, Rendicion.modulo_id,
Rendicion.worker_comision, Rendicion.companion_comision,
Companion2.name.label('companion2_name'),
Rendicion.companion2_id, Rendicion.companion2_comision,
Rendicion.boletas_debito, Rendicion.boletas_credito,
Rendicion.boletas_mp, Rendicion.boletas_efectivo,
).join(Worker, Rendicion.worker_id == Worker.id
).join(Modulo, Rendicion.modulo_id == Modulo.id
).outerjoin(Companion, Rendicion.companion_id == Companion.id
).outerjoin(Companion2, Rendicion.companion2_id == Companion2.id
).filter(*filters
).order_by(Rendicion.fecha.desc(), Rendicion.id.desc()).all()

View File

@@ -23,6 +23,13 @@ document.addEventListener("DOMContentLoaded", function () {
window.updateComisionToggle(select, `cc_${id}`);
};
window.toggleComp2Div = function (id, select) {
const compDiv = document.getElementById(`comp2_com_div_${id}`);
if (compDiv) compDiv.style.display = select.value ? 'flex' : 'none';
window.updateBadge(select, `badge_comp2_${id}`);
window.updateComisionToggle(select, `cc2_${id}`);
};
window.updateComisionToggle = function (selectElement, toggleId) {
const option = selectElement.options[selectElement.selectedIndex];
const tipoJornada = option ? option.getAttribute('data-tipo') : null;
@@ -99,6 +106,9 @@ document.addEventListener("DOMContentLoaded", function () {
const compSelect = this.querySelector('select[name="companion_id"]');
if (compSelect && compSelect.value) window.updateBadge(compSelect, `badge_comp_${rid}`);
const comp2Select = this.querySelector('select[name="companion2_id"]');
if (comp2Select && comp2Select.value) window.updateBadge(comp2Select, `badge_comp2_${rid}`);
});
modal.addEventListener('hidden.bs.modal', function () {

View File

@@ -80,8 +80,8 @@
<button type="button" class="btn btn-sm btn-danger" data-bs-toggle="modal" data-bs-target="#deleteRendicion{{ r[0] }}" title="Eliminar Rendición"><i class="bi bi-trash"></i></button>
</div>
{{ rendicion_detail_modal(r, r[20], r[21], r[22]) }}
{{ edit_rendicion_modal(r, r[20], workers, modulos) }}
{{ rendicion_detail_modal(r, r[23], r[24], r[25]) }}
{{ edit_rendicion_modal(r, r[23], workers, modulos) }}
{{ confirm_modal(
id='deleteRendicion' ~ r[0],

View File

@@ -42,10 +42,10 @@
</div>
</div>
<div class="col-md-3">
<div class="card bg-warning text-dark shadow-sm h-100 border-0">
<div class="card bg-primary text-white shadow-sm h-100 border-0">
<div class="card-body">
<div class="text-uppercase small mb-1 opacity-75">Días Trabajados</div>
<h3 class="card-title mb-0">{{ dias_activos }} <span class="fs-6 fw-normal">/ 31</span></h3>
<div class="text-uppercase small mb-1 opacity-75">Venta Total Neto</div>
<h3 class="card-title mb-0">${{ "{:,.0f}".format(totales_mes.credito * 0.97620 + totales_mes.debito * 0.98453 + totales_mes.mp * 0.98691 + totales_mes.efectivo - totales_mes.gastos).replace(',', '.') }}</h3>
</div>
</div>
</div>
@@ -63,9 +63,9 @@
<div class="card-header border-0 bg-transparent d-flex justify-content-between align-items-center pb-0">
<span class="fw-bold text-muted text-uppercase"><i class="bi bi-calendar3 me-1"></i> Desglose Diario</span>
<button class="btn btn-success btn-sm shadow-sm" onclick="alert('Próximamente: Esto descargará un Excel con el detalle de todos los productos vendidos por día.')">
<a class="btn btn-success btn-sm shadow-sm" href="{{ url_for('admin.report_modulo_exportar_excel', modulo_id=modulo_id, fecha_inicio=fecha_inicio, fecha_fin=fecha_fin, worker_id=worker_actual) }}">
<i class="bi bi-file-earmark-excel-fill me-1"></i> Exportar Detalle Completo (.xlsx)
</button>
</a>
</div>
<div class="card-body">
<div class="table-responsive">
@@ -77,12 +77,20 @@
<th class="py-2 text-info" rowspan="2">COMISIÓN</th>
<th class="py-2 text-danger" rowspan="2">GASTOS</th>
<th class="py-1 border-bottom-0" colspan="4">MEDIOS DE PAGO</th>
<th class="py-1 border-bottom-0" colspan="3">COMISIÓN REDELCOM</th>
<th class="py-1 border-bottom-0" colspan="3">TOTALES NETOS</th>
</tr>
<tr>
<th class="py-1 text-muted">Crédito</th>
<th class="py-1 text-muted">Débito</th>
<th class="py-1 text-muted">Mercado Pago</th>
<th class="py-1 text-muted">Efectivo/Dep.</th>
<th class="py-1" style="color:#e5904d">Crédito (-2.38%)</th>
<th class="py-1" style="color:#e5904d">Débito (-1.547%)</th>
<th class="py-1" style="color:#e5904d">MP (-1.309%)</th>
<th class="py-1" style="color:#20c997">REDELCOM Neto</th>
<th class="py-1 text-warning">Efectivo - Gastos</th>
<th class="py-1 text-primary fw-bold">Venta Total Neto</th>
</tr>
</thead>
<tbody>
@@ -105,6 +113,17 @@
<td class="align-middle numeric-cell text-muted">{{ ("$" ~ "{:,.0f}".format(d.debito).replace(',', '.')) if d.debito > 0 else "-" }}</td>
<td class="align-middle numeric-cell text-muted">{{ ("$" ~ "{:,.0f}".format(d.mp).replace(',', '.')) if d.mp > 0 else "-" }}</td>
<td class="align-middle numeric-cell text-muted">{{ ("$" ~ "{:,.0f}".format(d.efectivo).replace(',', '.')) if d.efectivo > 0 else "-" }}</td>
{% set red_credito = d.credito * 0.97620 %}
{% set red_debito = d.debito * 0.98453 %}
{% set red_mp = d.mp * 0.98691 %}
{% set redelcom_neto = red_credito + red_debito + red_mp %}
{% set efectivo_menos_gastos = d.efectivo - d.gastos %}
<td class="align-middle numeric-cell" style="color:#e5904d">{{ ("$" ~ "{:,.0f}".format(red_credito).replace(',', '.')) if red_credito > 0 else "-" }}</td>
<td class="align-middle numeric-cell" style="color:#e5904d">{{ ("$" ~ "{:,.0f}".format(red_debito).replace(',', '.')) if red_debito > 0 else "-" }}</td>
<td class="align-middle numeric-cell" style="color:#e5904d">{{ ("$" ~ "{:,.0f}".format(red_mp).replace(',', '.')) if red_mp > 0 else "-" }}</td>
<td class="align-middle numeric-cell" style="color:#20c997">{{ ("$" ~ "{:,.0f}".format(redelcom_neto).replace(',', '.')) if redelcom_neto > 0 else "-" }}</td>
<td class="align-middle numeric-cell text-warning fw-bold">{{ ("$" ~ "{:,.0f}".format(efectivo_menos_gastos).replace(',', '.')) if efectivo_menos_gastos != 0 else "-" }}</td>
<td class="align-middle numeric-cell text-primary fw-bold">{{ ("$" ~ "{:,.0f}".format(redelcom_neto + efectivo_menos_gastos).replace(',', '.')) if (redelcom_neto + efectivo_menos_gastos) != 0 else "-" }}</td>
</tr>
{% endfor %}
</tbody>
@@ -125,6 +144,14 @@
<td class="align-middle numeric-cell py-2">${{ "{:,.0f}".format(totales_mes.debito).replace(',', '.') }}</td>
<td class="align-middle numeric-cell py-2">${{ "{:,.0f}".format(totales_mes.mp).replace(',', '.') }}</td>
<td class="align-middle numeric-cell py-2">${{ "{:,.0f}".format(totales_mes.efectivo).replace(',', '.') }}</td>
<td class="align-middle numeric-cell py-2" style="color:#e5904d">${{ "{:,.0f}".format(totales_mes.credito * 0.97620).replace(',', '.') }}</td>
<td class="align-middle numeric-cell py-2" style="color:#e5904d">${{ "{:,.0f}".format(totales_mes.debito * 0.98453).replace(',', '.') }}</td>
<td class="align-middle numeric-cell py-2" style="color:#e5904d">${{ "{:,.0f}".format(totales_mes.mp * 0.98691).replace(',', '.') }}</td>
{% set t_redelcom = totales_mes.credito * 0.97620 + totales_mes.debito * 0.98453 + totales_mes.mp * 0.98691 %}
{% set t_efectivo_menos = totales_mes.efectivo - totales_mes.gastos %}
<td class="align-middle numeric-cell py-2" style="color:#20c997">${{ "{:,.0f}".format(t_redelcom).replace(',', '.') }}</td>
<td class="align-middle numeric-cell py-2 text-warning">${{ "{:,.0f}".format(t_efectivo_menos).replace(',', '.') }}</td>
<td class="align-middle numeric-cell py-2 text-primary fw-bold">${{ "{:,.0f}".format(t_redelcom + t_efectivo_menos).replace(',', '.') }}</td>
</tr>
</tfoot>
</table>

View File

@@ -328,7 +328,7 @@
<dd class="col-sm-7">{{ rendicion[2] }}
{% if session.get('is_admin') %}
<span class="badge {% if rendicion[14] %}bg-success{% else %}bg-secondary{% endif %} ms-1" style="font-size: 0.65em;">
{% if rendicion[14] %}$ Si Recibe Comision{% else %}$ No Recibe Comision{% endif %}
{% if rendicion[14] %}Si Recibe Comision{% else %}No Recibe Comision{% endif %}
</span>
{% endif %}
</dd>
@@ -339,7 +339,21 @@
{{ rendicion[10] }}
{% if session.get('is_admin') %}
<span class="badge {% if rendicion[15] %}bg-success{% else %}bg-secondary{% endif %} ms-1" style="font-size: 0.65em;">
{% if rendicion[15] %}$ Si Recibe Comision{% else %}$ No Recibe Comision{% endif %}
{% if rendicion[15] %}Si Recibe Comision{% else %}No Recibe Comision{% endif %}
</span>
{% endif %}
{% else %}
<span class="text-muted italic small">Sin acompañante</span>
{% endif %}
</dd>
<dt class="col-sm-5 text-muted">Acompañante 2</dt>
<dd class="col-sm-7">
{% if rendicion[16] %}
{{ rendicion[16] }}
{% if session.get('is_admin') %}
<span class="badge {% if rendicion[18] %}bg-success{% else %}bg-secondary{% endif %} ms-1" style="font-size: 0.65em;">
{% if rendicion[18] %}Si Recibe Comision{% else %}No Recibe Comision{% endif %}
</span>
{% endif %}
{% else %}
@@ -352,19 +366,19 @@
</dl>
<hr>
<div class="d-flex justify-content-between mb-2">
<span class="text-muted">Débito <small>(x{{ rendicion[16] }})</small>:</span>
<span class="text-muted">Débito <small>(x{{ rendicion[19] or 0 }})</small>:</span>
<span>${{ "{:,.0f}".format(rendicion[4] or 0).replace(',', '.') }}</span>
</div>
<div class="d-flex justify-content-between mb-2">
<span class="text-muted">Crédito <small>(x{{ rendicion[17] }})</small>:</span>
<span class="text-muted">Crédito <small>(x{{ rendicion[20] or 0 }})</small>:</span>
<span>${{ "{:,.0f}".format(rendicion[5] or 0).replace(',', '.') }}</span>
</div>
<div class="d-flex justify-content-between mb-2">
<span class="text-muted">Mercado Pago <small>(x{{ rendicion[18] }})</small>:</span>
<span class="text-muted">Mercado Pago <small>(x{{ rendicion[21] or 0 }})</small>:</span>
<span>${{ "{:,.0f}".format(rendicion[6] or 0).replace(',', '.') }}</span>
</div>
<div class="d-flex justify-content-between mb-2">
<span class="text-muted">Efectivo <small>(x{{ rendicion[19] }})</small>:</span>
<span class="text-muted">Efectivo <small>(x{{ rendicion[22] or 0 }})</small>:</span>
<span>${{ "{:,.0f}".format(rendicion[7] or 0).replace(',', '.') }}</span>
</div>
@@ -451,7 +465,7 @@
<tr>
<td colspan="3" class="text-end fw-bold">Total Calculado por Sistema:</td>
<td class="text-end fw-bold fs-6 text-primary" id="sys_total_{{ rendicion[0] }}">
${{ "{:,.0f}".format(rendicion[21] or 0).replace(',', '.') }}
${{ "{:,.0f}".format(rendicion[24] or 0).replace(',', '.') }}
</td>
</tr>
</tfoot>
@@ -484,7 +498,7 @@
<div id="badge_worker_{{ rendicion[0] }}"></div>
<div class="form-check m-0">
<input class="form-check-input" type="checkbox" name="worker_comision" id="wc_{{ rendicion[0] }}" {% if rendicion[14] %}checked{% endif %}>
<label class="form-check-label text-warning small fw-bold" for="wc_{{ rendicion[0] }}">Recibe Comisión</label>
<label class="form-check-label text-success small fw-bold" for="wc_{{ rendicion[0] }}">Recibe Comisión</label>
</div>
</div>
</div>
@@ -503,7 +517,26 @@
<div id="badge_comp_{{ rendicion[0] }}"></div>
<div class="form-check m-0">
<input class="form-check-input" type="checkbox" name="companion_comision" id="cc_{{ rendicion[0] }}" {% if rendicion[15] %}checked{% endif %}>
<label class="form-check-label text-warning small fw-bold" for="cc_{{ rendicion[0] }}">Recibe Comisión</label>
<label class="form-check-label text-success small fw-bold" for="cc_{{ rendicion[0] }}">Recibe Comisión</label>
</div>
</div>
</div>
<div class="mb-2 border-top pt-2">
<label class="small text-muted mb-0">Acompañante 2</label>
<select class="form-select form-select-sm" name="companion2_id" onchange="toggleComp2Div({{ rendicion[0] }}, this)">
<option value="" data-tipo="">Sin acompañante</option>
{% for w in workers %}
{% if w[3] == rendicion[13] %}
<option value="{{ w[0] }}" data-tipo="{{ w[2] }}" {% if w[0] == rendicion[17] %}selected{% endif %}>{{ w[1] }}</option>
{% endif %}
{% endfor %}
</select>
<div class="d-flex justify-content-between align-items-center mt-1" id="comp2_com_div_{{ rendicion[0] }}" {% if not rendicion[17] %}style="display:none;"{% endif %}>
<div id="badge_comp2_{{ rendicion[0] }}"></div>
<div class="form-check m-0">
<input class="form-check-input" type="checkbox" name="companion2_comision" id="cc2_{{ rendicion[0] }}" {% if rendicion[18] %}checked{% endif %}>
<label class="form-check-label text-success small fw-bold" for="cc2_{{ rendicion[0] }}">Recibe Comisión</label>
</div>
</div>
</div>
@@ -514,7 +547,7 @@
<input type="text" class="form-control form-control-sm text-end money-input mb-1" id="edit_debito_{{ rendicion[0] }}" name="venta_debito" value="{{ '{:,.0f}'.format(rendicion[4] or 0).replace(',', '.') }}" oninput="calcTotalEdit({{ rendicion[0] }})">
<div class="input-group input-group-sm">
<span class="input-group-text bg-body-tertiary text-muted" style="font-size: 0.7em;">Boletas</span>
<input type="number" class="form-control text-center bg-body text-body border-secondary" name="boletas_debito" value="{{ rendicion[16] or 0 }}">
<input type="number" class="form-control text-center bg-body text-body border-secondary" name="boletas_debito" value="{{ rendicion[19] or 0 }}">
</div>
</div>
<div class="col-6">
@@ -522,7 +555,7 @@
<input type="text" class="form-control form-control-sm text-end money-input mb-1" id="edit_credito_{{ rendicion[0] }}" name="venta_credito" value="{{ '{:,.0f}'.format(rendicion[5] or 0).replace(',', '.') }}" oninput="calcTotalEdit({{ rendicion[0] }})">
<div class="input-group input-group-sm">
<span class="input-group-text bg-body-tertiary text-muted" style="font-size: 0.7em;">Boletas</span>
<input type="number" class="form-control text-center bg-body text-body border-secondary" name="boletas_credito" value="{{ rendicion[17] or 0 }}">
<input type="number" class="form-control text-center bg-body text-body border-secondary" name="boletas_credito" value="{{ rendicion[20] or 0 }}">
</div>
</div>
<div class="col-6">
@@ -530,7 +563,7 @@
<input type="text" class="form-control form-control-sm text-end money-input mb-1" id="edit_mp_{{ rendicion[0] }}" name="venta_mp" value="{{ '{:,.0f}'.format(rendicion[6] or 0).replace(',', '.') }}" oninput="calcTotalEdit({{ rendicion[0] }})">
<div class="input-group input-group-sm">
<span class="input-group-text bg-body-tertiary text-muted" style="font-size: 0.7em;">Boletas</span>
<input type="number" class="form-control text-center bg-body text-body border-secondary" name="boletas_mp" value="{{ rendicion[18] or 0 }}">
<input type="number" class="form-control text-center bg-body text-body border-secondary" name="boletas_mp" value="{{ rendicion[21] or 0 }}">
</div>
</div>
<div class="col-6">
@@ -538,7 +571,7 @@
<input type="text" class="form-control form-control-sm text-end money-input mb-1" id="edit_efectivo_{{ rendicion[0] }}" name="venta_efectivo" value="{{ '{:,.0f}'.format(rendicion[7] or 0).replace(',', '.') }}" oninput="calcTotalEdit({{ rendicion[0] }})">
<div class="input-group input-group-sm">
<span class="input-group-text bg-body-tertiary text-muted" style="font-size: 0.7em;">Boletas</span>
<input type="number" class="form-control text-center bg-body text-body border-secondary" name="boletas_efectivo" value="{{ rendicion[19] or 0 }}">
<input type="number" class="form-control text-center bg-body text-body border-secondary" name="boletas_efectivo" value="{{ rendicion[22] or 0 }}">
</div>
</div>
</div>