caudal/programa/pruebas/test_tierra.py
esetheyers 7e18576f86 Caudal 0.2.0
Taxes for the whole of Spain (common territory, Navarre, Álava, Bizkaia and Gipuzkoa); flats, garages and land valued on their own; Treasury bills, bonds and deposits priced on BME; broker accounts; a guided start; a page per investment with its chart and the tax of selling today; net worth at the top; undo when deleting; Woodpecker CI for the tests and the Linux build.
2026-10-15 16:49:15 -05:00

145 lines
7.4 KiB
Python

"""
Pruebas del valor de las fincas rústicas con el precio de la tierra del MAPA
(cartera/tierra.py y su ficha en operaciones.py).
python3 -m unittest pruebas.test_tierra -v
"""
from __future__ import annotations
import datetime as dt
import sys
import tempfile
import unittest
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
from cartera import tierra # noqa: E402
from cartera.datos import Datos, ErrorDatos, _validar, escribir # noqa: E402
from cartera.operaciones import Cartera, ErrorOperacion # noqa: E402
# Serie pequeña e inventada, para que las cuentas se vean
SERIE = {"cultivos": {"TAS": "Secano", "TAR": "Regadío", "OLS": "Olivar"},
"precios": {"navarra": {"TAS": [[2020, 10000], [2021, 11000], [2022, 12000]],
"TAR": [[2020, 20000], [2021, 22000], [2022, 25000]]},
"nacional": {"TAS": [[2020, 5000], [2021, 5500], [2022, 6000]],
"OLS": [[2020, 8000], [2021, 8000], [2022, 9000]]}}}
def finca(**ficha):
base = {"clase": "terreno_rustico", "uso": "vacio", "comunidad": "navarra", "auto": True,
"superficie": 2, "origen": "compra", "cultivos": [{"desde": "", "cultivo": "TAS"}]}
return {"id": "IN1", "tipo": "Inmueble", "inmueble": {**base, **ficha}}
COMPRA = [{"id": "m1", "activo": "IN1", "tipo": "Compra", "fecha": "2020-05-10", "importe": 30000}]
def valores(a, movs=COMPRA, precios=(), hoy=dt.date(2026, 1, 1)):
return [(e["fecha"], e["valor_total"]) for e in tierra.estimaciones(a, movs, list(precios), hoy, SERIE)]
class TestPrecio(unittest.TestCase):
def test_el_de_su_comunidad_o_el_nacional_y_fuera_de_la_serie_el_mas_cercano(self):
self.assertEqual(tierra.precio("navarra", "TAS", 2021, SERIE), (11000.0, "navarra"))
self.assertEqual(tierra.precio("navarra", "OLS", 2022, SERIE), (9000.0, "nacional"))
self.assertEqual(tierra.precio("navarra", "TAS", 2015, SERIE)[0], 10000.0)
self.assertEqual(tierra.precio("navarra", "TAS", 2026, SERIE)[0], 12000.0)
self.assertIsNone(tierra.precio("navarra", "XXX", 2022, SERIE))
def test_el_cultivo_de_cada_dia(self):
f = {"cultivos": [{"desde": "", "cultivo": "TAS"}, {"desde": "2021-03-01", "cultivo": "TAR"}]}
self.assertEqual((tierra.cultivo_en(f, "2020-01-01"), tierra.cultivo_en(f, "2021-03-01")), ("TAS", "TAR"))
def test_la_serie_del_programa_trae_las_comunidades_y_el_secano_y_el_regadio(self):
s = tierra.serie()
self.assertGreaterEqual(tierra.ultimo_año(s), 2024)
self.assertIn("TAS", s["precios"]["navarra"])
self.assertIn("TAR", s["precios"]["navarra"])
self.assertEqual(len([c for c in s["precios"] if c != "nacional"]), 17)
class TestEstimaciones(unittest.TestCase):
def test_parte_de_lo_que_costo_y_sigue_a_su_cultivo_cada_31_de_diciembre(self):
self.assertEqual(valores(finca()), [("2020-12-31", 30000.0), ("2021-12-31", 33000.0), ("2022-12-31", 36000.0)])
def test_con_origen_media_parte_de_la_superficie_por_el_precio_de_ese_año(self):
a = finca(origen="media")
self.assertEqual(tierra.punto_de_partida(a, COMPRA, SERIE), ("2020-05-10", 20000.0))
self.assertEqual(valores(a)[-1], ("2022-12-31", 24000.0))
def test_un_valor_a_mano_manda_desde_su_fecha(self):
tasacion = [{"fecha": "2021-06-30", "valor_total": 50000, "fuente": "manual"}]
self.assertEqual(valores(finca(), precios=tasacion),
[("2020-12-31", 30000.0), ("2021-12-31", 50000.0), ("2022-12-31", round(50000 * 12000 / 11000, 2))])
def test_al_pasar_a_regadio_el_valor_se_reescala_por_lo_que_vale_el_nuevo_cultivo(self):
a = finca(cultivos=[{"desde": "", "cultivo": "TAS"}, {"desde": "2021-03-01", "cultivo": "TAR"}])
# 30.000 comprado con el secano a 10.000 €/ha; en 2021 el regadío vale 22.000 → 66.000
self.assertEqual(valores(a), [("2020-12-31", 30000.0), ("2021-12-31", 66000.0), ("2022-12-31", 75000.0)])
def test_se_para_al_vender_y_sin_auto_o_sin_cultivo_no_hay_nada(self):
venta = COMPRA + [{"id": "m2", "activo": "IN1", "tipo": "Venta", "fecha": "2022-02-01", "importe": 40000}]
self.assertEqual(valores(finca(), venta)[-1][0], "2021-12-31")
self.assertEqual(valores(finca(auto=False)), [])
self.assertEqual(valores(finca(cultivos=[])), [])
self.assertEqual(valores({**finca(), "inmueble": {**finca()["inmueble"], "clase": "vivienda"}}), [])
class TestEnLaCartera(unittest.TestCase):
def setUp(self):
t = tempfile.TemporaryDirectory()
self.addCleanup(t.cleanup)
carpeta = Path(t.name) / "datos"
escribir(carpeta, Datos([], [], [], []))
self.c = Cartera(carpeta)
self.addCleanup(self.c.cerrar)
def alta(self, **ficha):
return self.c.guardar_activo({"tipo": "Inmueble", "nombre": "Finca", "inmueble": {
"clase": "terreno_rustico", "uso": "vacio", "comunidad": "navarra", "auto": True,
"superficie": 3, "cultivo": "TAS", "origen": "media", **ficha}})
def test_alta_compra_y_valores_con_la_fuente_mapa(self):
a = self.alta()
self.assertEqual(a["inmueble"]["cultivos"], [{"desde": "", "cultivo": "TAS"}])
self.c.guardar_movimiento({"activo": a["id"], "tipo": "Compra", "fecha": "2021-06-01", "importe": 30000})
suyos = {r["fecha"]: r for r in self.c.datos.vivos("precios") if r["activo"] == a["id"]}
precio_2021 = tierra.precio("navarra", "TAS", 2021)[0]
self.assertEqual(suyos["2021-06-01"]["valor_total"], round(3 * precio_2021, 2))
self.assertEqual(suyos["2021-06-01"]["fuente"], "compra")
self.assertEqual(suyos[f"{tierra.ultimo_año()}-12-31"]["fuente"], "MAPA")
def test_el_cultivo_guarda_su_historia_y_el_mismo_dia_se_corrige(self):
a = self.alta()
cambio = {"id": a["id"], "tipo": "Inmueble", "nombre": "Finca", "inmueble": {
"clase": "terreno_rustico", "uso": "vacio", "comunidad": "navarra", "auto": True, "superficie": 3,
"origen": "media", "cultivo": "TAR", "cultivo_desde": "2023-03-01"}}
a = self.c.guardar_activo(cambio)
self.assertEqual([c["cultivo"] for c in a["inmueble"]["cultivos"]], ["TAS", "TAR"])
a = self.c.guardar_activo({**cambio, "inmueble": {**cambio["inmueble"], "cultivo": "VIS"}})
self.assertEqual(a["inmueble"]["cultivos"][-1], {"desde": "2023-03-01", "cultivo": "VIS"})
self.assertEqual(len(a["inmueble"]["cultivos"]), 2)
# Guardar sin cambiar el cultivo no toca la historia
a = self.c.guardar_activo({**cambio, "inmueble": {**cambio["inmueble"], "cultivo": "VIS", "cultivo_desde": "2024-01-01"}})
self.assertEqual(len(a["inmueble"]["cultivos"]), 2)
def test_lo_que_falta_se_dice(self):
with self.assertRaises(ErrorOperacion):
self.alta(cultivo="NO")
with self.assertRaises(ErrorOperacion):
self.alta(cultivo=None)
with self.assertRaises(ErrorOperacion):
self.alta(superficie=None)
self.assertNotIn("cultivos", self.alta(cultivo=None, auto=False, origen="compra")["inmueble"])
def test_los_datos_rechazan_una_historia_de_cultivos_rota(self):
a = {**finca(), "nombre": "F", "valoracion": "total", "estado": "abierta", "unidad": "inmueble"}
a["inmueble"]["cultivos"] = "TAS"
with self.assertRaises(ErrorDatos):
_validar("activos", a, "prueba")
if __name__ == "__main__":
unittest.main()