iteracion 2
This commit is contained in:
+175
-2
@@ -1,3 +1,176 @@
|
||||
from django.test import TestCase
|
||||
from django.test import TestCase, Client
|
||||
from django.contrib.auth.models import User, Group
|
||||
from decimal import Decimal
|
||||
from datetime import date
|
||||
from expenses.models import (
|
||||
Expense, Project, Category, SystemSetting, Vendor, ProjectPhase,
|
||||
ProjectStatusEnum, TaxTypeEnum, ExpenseTypeEnum, VehicleLog
|
||||
)
|
||||
from expenses.services.sii import SIIService
|
||||
from talent.models import SpecialistCategoryEnum, SpecialistCandidate
|
||||
from procurement.models import ItemCatalog, Category as ProcurementCategory
|
||||
|
||||
# Create your tests here.
|
||||
class ERPRequirementsTestCase(TestCase):
|
||||
def setUp(self):
|
||||
self.client = Client()
|
||||
self.admin = User.objects.create_superuser('admin_user', 'admin@efintel.cl', 'password123')
|
||||
self.pm_group, _ = Group.objects.get_or_create(name='Director de Proyecto')
|
||||
self.pm_user = User.objects.create_user('pm_user', 'pm@efintel.cl', 'password123')
|
||||
self.pm_user.groups.add(self.pm_group)
|
||||
|
||||
self.setting = SystemSetting.objects.create(id=1, usd_exchange_rate=950.0, iva_rate=19.00)
|
||||
|
||||
self.category_combustible = Category.objects.create(code='3101', name='Combustibles / Bencina')
|
||||
self.category_office = Category.objects.create(code='2301', name='Arriendo de Oficinas y Espacios de Trabajo')
|
||||
self.category_courses = Category.objects.create(code='4201', name='Cursos, Capacitación y Certificaciones Técnicas para Especialistas')
|
||||
self.category_ai = Category.objects.create(code='7000', name='Software, Datos, Inteligencia Artificial y Cloud')
|
||||
|
||||
self.project_idi = Project.objects.create(
|
||||
code='CC-IDI-01',
|
||||
name='Centro I+D+i Central',
|
||||
assigned_budget_clp=10000000,
|
||||
payment_method='Mensual',
|
||||
total_income_clp=15000000,
|
||||
type=ExpenseTypeEnum.COSTO_DIRECTO,
|
||||
status=ProjectStatusEnum.ACTIVO,
|
||||
manager=self.pm_user
|
||||
)
|
||||
|
||||
def test_req_1_and_5_dynamic_iva_and_settings(self):
|
||||
"""Test Requerimiento 1 (No global_budget in dashboard) & Requerimiento 5 (Dynamic IVA)."""
|
||||
self.client.login(username='admin_user', password='password123')
|
||||
response = self.client.get('/')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertNotIn('PRESUPUESTO GENERAL I+D+i', response.content.decode())
|
||||
|
||||
# Test Dynamic IVA (Change to 21%)
|
||||
self.setting.iva_rate = Decimal('21.00')
|
||||
self.setting.save()
|
||||
calc = SIIService.calculate_taxes(Decimal('100000'), 'IVA_19')
|
||||
self.assertEqual(calc['tax_amount'], Decimal('21000'))
|
||||
self.assertEqual(calc['total_amount'], Decimal('121000'))
|
||||
|
||||
def test_req_2_exact_project_count(self):
|
||||
"""Test Requerimiento 2: Exact project count by status."""
|
||||
Project.objects.create(code='PROY-P1', name='Pausado', status=ProjectStatusEnum.PAUSADA)
|
||||
Project.objects.create(code='PROY-T1', name='Terminado', status=ProjectStatusEnum.TERMINADO)
|
||||
Project.objects.create(code='PROY-D1', name='Borrador', status=ProjectStatusEnum.BORRADOR)
|
||||
|
||||
self.client.login(username='admin_user', password='password123')
|
||||
res = self.client.get('/proyectos/')
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertEqual(res.context['project_count_active'], 1)
|
||||
self.assertEqual(res.context['project_count_paused'], 1)
|
||||
self.assertEqual(res.context['project_count_completed'], 1)
|
||||
self.assertEqual(res.context['project_count_draft'], 1)
|
||||
self.assertEqual(res.context['project_count_total'], 4)
|
||||
|
||||
def test_req_4_sii_integration(self):
|
||||
"""Test Requerimiento 4: SII API service and taxpayer info query."""
|
||||
is_valid, formatted = SIIService.validate_rut('76543210-3')
|
||||
self.assertTrue(is_valid)
|
||||
self.assertEqual(formatted, '76.543.210-3')
|
||||
|
||||
info = SIIService.get_taxpayer_info('76.543.210-3')
|
||||
self.assertTrue(info['valid'])
|
||||
self.assertEqual(info['rut'], '76.543.210-3')
|
||||
|
||||
def test_req_6_vendor_draft_mitigation(self):
|
||||
"""Test Requerimiento 6: Vendor registration error mitigation and draft in session."""
|
||||
self.client.login(username='admin_user', password='password123')
|
||||
# Submit invalid vendor form (RUT invalid - fails Modulo 11 check)
|
||||
response = self.client.post('/gestion/proveedores/nuevo/', {
|
||||
'rut': '12345678-0',
|
||||
'name': 'Vendor Test Draft',
|
||||
'payment_terms': 30
|
||||
})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertIn('vendor_draft', self.client.session)
|
||||
|
||||
def test_req_7_is_reimbursement_logic(self):
|
||||
"""Test Requerimiento 7: Erogación rendición vs centro I+D+i."""
|
||||
expense = Expense.objects.create(
|
||||
project=self.project_idi,
|
||||
category=self.category_office,
|
||||
is_reimbursement=False,
|
||||
amount_clp=50000,
|
||||
date=date.today(),
|
||||
description='Gasto I+D+i directo',
|
||||
user=self.admin
|
||||
)
|
||||
self.assertFalse(expense.is_reimbursement)
|
||||
|
||||
# Reimbursement expense
|
||||
expense_reimb = Expense.objects.create(
|
||||
project=self.project_idi,
|
||||
category=self.category_office,
|
||||
is_reimbursement=True,
|
||||
responsible_person=self.pm_user,
|
||||
amount_clp=30000,
|
||||
date=date.today(),
|
||||
description='Rendición de pasajes',
|
||||
user=self.admin
|
||||
)
|
||||
self.assertTrue(expense_reimb.is_reimbursement)
|
||||
self.assertEqual(expense_reimb.responsible_person, self.pm_user)
|
||||
|
||||
def test_req_8_9_10_project_detail_and_phase_balances(self):
|
||||
"""Test Requerimiento 8, 9, 10: Project detail, progressive creation, and phase balances (+ / -)."""
|
||||
phase1 = ProjectPhase.objects.create(
|
||||
project=self.project_idi,
|
||||
phase_number=1,
|
||||
name='Fase 1: Prototipado',
|
||||
planned_amount_clp=5000000,
|
||||
income_amount_clp=6000000,
|
||||
expense_amount_clp=2000000
|
||||
)
|
||||
self.assertEqual(phase1.balance_clp, Decimal('4000000')) # Positive balance +$4.000.000
|
||||
|
||||
phase2 = ProjectPhase.objects.create(
|
||||
project=self.project_idi,
|
||||
phase_number=2,
|
||||
name='Fase 2: Pruebas Terreno',
|
||||
planned_amount_clp=3000000,
|
||||
income_amount_clp=1000000,
|
||||
expense_amount_clp=2500000
|
||||
)
|
||||
self.assertEqual(phase2.balance_clp, Decimal('-1500000')) # Negative balance -$1.500.000
|
||||
|
||||
self.client.login(username='admin_user', password='password123')
|
||||
res = self.client.get(f'/proyectos/{self.project_idi.id}/')
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertIn('Fases de Pago e Hitos del Proyecto', res.content.decode())
|
||||
|
||||
def test_req_11_12_13_categories_taxonomy(self):
|
||||
"""Test Requerimiento 11, 12, 13: Talent category 7, Office Rental, and Specialist Courses."""
|
||||
# Req 11
|
||||
self.assertEqual(SpecialistCategoryEnum.CAT_7_SOFTWARE_DATOS_IA_CLOUD, '7')
|
||||
self.assertEqual(SpecialistCategoryEnum.CAT_7_SOFTWARE_DATOS_IA_CLOUD.label, '7. Software, Datos, IA y Cloud')
|
||||
|
||||
# Req 12
|
||||
self.assertEqual(self.category_office.code, '2301')
|
||||
|
||||
# Req 13
|
||||
self.assertEqual(self.category_courses.code, '4201')
|
||||
|
||||
def test_req_14_vehicle_category_strict_combustible(self):
|
||||
"""Test Requerimiento 14: Vehicle log applies ONLY to combustible category."""
|
||||
exp_combustible = Expense.objects.create(
|
||||
project=self.project_idi,
|
||||
category=self.category_combustible,
|
||||
amount_clp=40000,
|
||||
date=date.today(),
|
||||
description='Carga Combustible Copec',
|
||||
user=self.admin
|
||||
)
|
||||
self.assertTrue(exp_combustible.is_vehicle_category())
|
||||
|
||||
exp_office = Expense.objects.create(
|
||||
project=self.project_idi,
|
||||
category=self.category_office,
|
||||
amount_clp=150000,
|
||||
date=date.today(),
|
||||
description='Pago Arriendo Oficina',
|
||||
user=self.admin
|
||||
)
|
||||
self.assertFalse(exp_office.is_vehicle_category())
|
||||
|
||||
Reference in New Issue
Block a user