""" exportar.py — El informe fiscal de un ejercicio en una hoja de cálculo. Lo mismo que enseña la pestaña «Fiscal», con todo el detalle, para repasarlo fuera del programa, guardarlo con la declaración o dárselo a quien te lleve los impuestos. Valores, sin fórmulas ni macros: es una foto, no se edita. Resumen las cifras del año y la liquidación de la parte del ahorro Ventas cada transmisión: lo cobrado, lo que costó y la ganancia Lotes de qué compras sale cada venta (el FIFO, lote a lote) Rendimientos dividendos, intereses y rentas, con su retención Actividad la minería: ingresos, gastos y amortización de los aparatos Recibido cada entrada minada o recibida sin pagar, a su valor del día Existencias lo que quedaba a 31 de diciembre Criterios con qué criterios está hecho y qué queda por resolver Recibe el informe ya calculado (fiscal.completo): aquí no se calcula nada. Necesita openpyxl, como la exportación de la cartera. """ from __future__ import annotations from pathlib import Path from ..exportar_xlsx import EUROS, UNIDADES, _fecha, _Hoja, _openpyxl FECHA = "DD/MM/YYYY" CANTIDAD = "#,##0.00000000" def exportar(r: dict, destino: Path) -> None: """Escribe el libro del informe «r» (lo que devuelve fiscal.completo).""" _openpyxl() from openpyxl import Workbook wb = Workbook() wb.remove(wb.active) c, t = r["cuota"], r["total"] h = _Hoja(wb, "Resumen", [("Concepto", 62, None), ("Importe", 16, EUROS), ("Nota", 90, None)]) h.datos([f"Ejercicio {r['ejercicio']} · {c['nombre_territorio']}", None, "Ayuda para preparar la declaración, no asesoría fiscal. Hecho solo con lo que hay en la cartera."], True) h.titulo("Ganancias y pérdidas por ventas") h.datos(["Ganancias", t["ganancias"]]) h.datos(["Pérdidas", t["perdidas"]]) h.datos(["Pérdidas aplazadas por recompra", t["aplazadas"]]) h.datos(["Pérdidas de años anteriores que se integran", t["integradas"]]) h.datos(["Lo que cuenta este año", t["computable"]], True) for x in r["por_clase"]: h.datos([f" {x['clase']} ({x['transmisiones']} operaciones)", x["neto"], f"Transmisión {x['valor_transmision']:.2f} · adquisición {x['valor_adquisicion']:.2f}"]) if r.get("bróker"): h.titulo("Cuentas de bróker o trading (del informe fiscal del bróker)") for x in r["bróker"]: h.datos([x["nombre"], x["resultado"], None if x["resultado"] is not None else "Sin apuntar: no entra en la cuota"]) if r.get("alquileres") or r.get("imputaciones") or r.get("ventas_inmuebles"): h.titulo("Inmuebles") for x in r.get("alquileres", []): h.datos([f"{x['nombre']}: alquiler ({'base del ahorro' if x['base'] == 'ahorro' else 'parte general'})", x["rendimiento"], f"Cobrado {x['ingresos']:.2f} · gastos {x['deducido']:.2f} · bonificación {x['bonificacion']:.2f} · reducción {x['reduccion']:.2f}" + ("" if x["verificado"] else " · REGLAS SIN COMPROBAR")]) for x in r.get("ventas_inmuebles", []): h.datos([f"{x['nombre']}: venta (base del ahorro)", x["ganancia"], f"Cobrado {x['valor_transmision']:.2f} · coste {x['valor_adquisicion']:.2f} (pagado {x['pagado']:.2f}, " f"actualizado {x['actualizado']:.2f}, amortizado {x['amortizacion']:.2f})"]) for x in r.get("imputaciones", []): h.datos([f"{x['nombre']}: renta imputada (parte general)", x["renta"], x["aviso"] or x["cita"]]) h.titulo("Dividendos, intereses y rentas") for x in r["por_concepto"]: h.datos([x["concepto"], x["bruto"], f"Retención {x['retencion']:.2f} · cobrado {x['neto']:.2f}"]) h.titulo("Actividades económicas (parte general)") for a in r["actividades"]: h.datos([f"{a['nombre']}: rendimiento neto", a["rendimiento"], "Detalle en la hoja «Actividad»"], True) h.datos(["Minado o recibido sin pagar, a su valor del día", r["total_recibido"]]) h.titulo(f"Parte del ahorro · {c['nombre_territorio']}") if not c["verificado"]: h.datos(["REGLAS SIN COMPROBAR PARA ESTE AÑO", None, c["nota"]], True) h.datos(["Dividendos e intereses (bruto)", c["rendimientos"]]) h.datos(["Ganancias y pérdidas (ventas y bróker)" if any(x["resultado"] is not None for x in r.get("bróker", [])) else "Ganancias y pérdidas por ventas", c["ganancias"]]) for p in c["pasos"]: h.datos([f" ↳ {p['texto']}", None, p["cita"]]) h.datos(["Base del ahorro", c["base"]], True) for x in c["tramos"]: h.datos([f" {x['base']:.2f} al {x['tipo']} %", x["cuota"]]) h.datos(["Cuota del ahorro", c["cuota"], c["citas"]["escala"]], True) h.datos(["Retenciones", -c["retenciones"]]) h.datos(["Resultado (a pagar si es positivo)", c["resultado"]], True) for x in c["pendientes"]: h.datos([f"Queda para restar: {x['clase']} de {x['ejercicio']}", x["importe"], f"Hasta {x['hasta']}"]) h.datos([None, None, f"Reglas: {c['norma']} ({c['fuente']}), consultado el {c['consultado']}."]) h = _Hoja(wb, "Ventas", [("Fecha", 12, FECHA), ("Activo", 28, None), ("Clase", 20, None), ("Qué", 32, None), ("Cantidad", 16, CANTIDAD), ("Valor de transmisión", 18, EUROS), ("Valor de adquisición", 18, EUROS), ("Ganancia", 14, EUROS), ("Aplazada por recompra", 18, EUROS), ("Cuenta este año", 16, EUROS), ("Avisos", 30, None)]) lotes = _Hoja(wb, "Lotes", [("Fecha de la venta", 16, FECHA), ("Activo", 28, None), ("Qué", 32, None), ("Fecha de la compra", 16, FECHA), ("Cantidad", 16, CANTIDAD), ("Coste", 14, EUROS)]) avisos = {"sin_cubrir": "falta historial", "estimado": "cifras estimadas", "sin_fecha": "compra sin fecha (traspaso de fuera)"} for x in r["transmisiones"]: h.datos([_fecha(x["fecha"]), x["nombre"], x["clase"], x["concepto"], x["cantidad"], x["valor_transmision"], x["valor_adquisicion"], x["ganancia"], x["aplazada"], x["computable"], ", ".join(avisos.get(a, a) for a in x["avisos"])]) for lote in x["lotes"]: lotes.datos([_fecha(x["fecha"]), x["nombre"], x["concepto"], _fecha(lote["fecha"]), lote["cantidad"], lote["coste"]]) for x in r["integradas"]: h.datos([_fecha(x["fecha"]), x["nombre"], None, f"Pérdida aplazada de la venta del {x['fecha_venta']} que se integra", None, None, None, None, None, x["importe"]]) h = _Hoja(wb, "Rendimientos", [("Fecha", 12, FECHA), ("Activo", 28, None), ("Concepto", 26, None), ("Bruto", 14, EUROS), ("Retención", 14, EUROS), ("Cobrado", 14, EUROS)]) for x in r["rendimientos"]: h.datos([_fecha(x["fecha"]), x["nombre"], x["concepto"], x["bruto"], x["retencion"], x["neto"]]) h = _Hoja(wb, "Actividad", [("Concepto", 46, None), ("Fecha", 12, FECHA), ("Importe", 16, EUROS), ("Amortizado antes", 16, EUROS), ("Este año", 14, EUROS), ("Queda", 14, EUROS), ("Nota", 70, None)]) for a in r["actividades"]: h.datos([f"{a['nombre']} · {a['ejercicio']}", None, None, None, None, None, a["citas"]["actividad"]], True) h.datos(["Ingresos: lo recibido, a su valor de ese día", None, a["ingresos"], None, None, None, f"{a['entradas']} entradas"]) h.datos(["Gastos del año", None, -a["gastos"]]) if a["amortiza"]: h.datos(["Amortización de los aparatos", None, -a["amortizacion"], None, None, None, f"{a['tabla']['nombre']}: {a['tabla']['coeficiente']} % al año como mucho ({a['citas']['amortizacion']})"]) else: h.datos(["Amortización de los aparatos", None, None, None, None, None, f"No se restan aparte: los cubre la reducción ({a['citas']['amortizacion']})"]) h.datos([a["texto_reduccion"] or "Reducción", None, -a["reduccion"], None, None, None, a["citas"]["reduccion"]]) h.datos(["Rendimiento neto de la actividad", None, a["rendimiento"], None, None, None, a["texto_negativo"] if a["rendimiento"] < 0 and a["texto_negativo"] else a["citas"]["general"]], True) if not a["verificado"]: h.datos(["REGLAS SIN COMPROBAR", None, None, None, None, None, a["nota"]], True) h.titulo("Aparatos") for x in a["aparatos"]: h.datos([x["notas"] or "Aparato", _fecha(x["fecha"]), x["coste"], x["antes"], x["amortizacion"], x["pendiente"], "cifras estimadas" if x["estimado"] else None]) h.titulo("Gastos del año, uno a uno") for x in a["corrientes"]: h.datos([x["notas"] or ("Devolución" if x["importe"] < 0 else "Gasto"), _fecha(x["fecha"]), x["importe"], None, None, None, "cifras estimadas" if x["estimado"] else None]) h.fila += 1 h = _Hoja(wb, "Recibido", [("Fecha", 12, FECHA), ("Activo", 28, None), ("Qué", 14, None), ("Actividad", 18, None), ("Cantidad", 16, CANTIDAD), ("Valor al recibirlo", 16, EUROS)]) for x in r["recibido"]: h.datos([_fecha(x["fecha"]), x["nombre"], "Minado" if x["tipo"] == "Mineria" else "Recibido", x["actividad"], x["cantidad"], x["valor"]]) h = _Hoja(wb, "Existencias", [("Qué", 28, None), ("Clase", 20, None), ("Cantidad", 16, CANTIDAD), ("Coste (FIFO)", 16, EUROS), (f"Valor a 31-12-{r['ejercicio']}", 18, EUROS), ("Compras vivas", 14, None), ("Compra más antigua", 18, FECHA)]) for x in r["existencias"]: h.datos([x["nombre"], x["clase"], x["cantidad"], x["coste"], x["valor"], x["lotes"], _fecha(x["primer_lote"])]) h = _Hoja(wb, "Criterios", [("Criterio", 50, None), ("Cómo se aplica", 120, None), ("Fuente", 60, None)]) for x in r["criterios"]: h.datos([x["titulo"], x["texto"], x["fuente"]]) for clave, o in r["opciones_posibles"].items(): h.datos([f"Elegido · {o['titulo']}", dict(o["valores"]).get(r["opciones"][clave], r["opciones"][clave])]) if r["tareas"]: h.titulo("Por resolver antes de fiarse de estas cifras") for x in r["tareas"]: h.datos([f"{x['fecha']} · {x['activo']}", x["texto"]]) fuera = [x for x in r["fuera"] if x["cobrado"]] if fuera: h.titulo("No entran en este cálculo") for x in fuera: h.datos([x["nombre"], f"Cobraste {x['cobrado']:.2f} €; {x['motivo']}"]) destino = Path(destino) destino.parent.mkdir(parents=True, exist_ok=True) wb.save(destino)