""" Tests for ExtraGood model """ import pytest from decimal import Decimal from datetime import datetime from app.models import ExtraGood, Project, User, Client, Invoice from factories import InvoiceFactory class TestExtraGoodModel: """Test cases for ExtraGood model""" def test_create_extra_good_for_project(self, app, db_session): """Test creating an extra good for a project""" # Create test data client = Client(name="Test Client") db_session.add(client) db_session.commit() user = User(username="testuser", email="test@example.com", role="user") user.password_hash = "hash" db_session.add(user) db_session.commit() project = Project(name="Test Project", client_id=client.id) db_session.add(project) db_session.commit() # Create extra good good = ExtraGood( name="Test Product", unit_price=100.00, quantity=5, created_by=user.id, project_id=project.id, description="Test description", category="product", sku="TEST-001", ) db_session.add(good) db_session.commit() # Verify assert good.id is not None assert good.name == "Test Product" assert good.quantity == Decimal("5") assert good.unit_price == Decimal("100.00") assert good.total_amount == Decimal("500.00") assert good.project_id == project.id assert good.created_by == user.id assert good.category == "product" assert good.sku == "TEST-001" def test_create_extra_good_for_invoice(self, app, db_session): """Test creating an extra good for an invoice""" # Create test data client = Client(name="Test Client") db_session.add(client) db_session.commit() user = User(username="testuser", email="test@example.com", role="user") user.password_hash = "hash" db_session.add(user) db_session.commit() project = Project(name="Test Project", client_id=client.id) db_session.add(project) db_session.commit() invoice = InvoiceFactory( invoice_number="INV-001", project_id=project.id, client_name="Test Client", due_date=datetime.utcnow().date(), created_by=user.id, client_id=client.id, status="draft", ) # Create extra good good = ExtraGood( name="License Fee", unit_price=500.00, quantity=1, created_by=user.id, invoice_id=invoice.id, category="license", ) db_session.add(good) db_session.commit() # Verify assert good.id is not None assert good.invoice_id == invoice.id assert good.total_amount == Decimal("500.00") def test_update_total(self, app, db_session): """Test updating total when quantity or price changes""" user = User(username="testuser", email="test@example.com", role="user") user.password_hash = "hash" db_session.add(user) db_session.commit() good = ExtraGood(name="Test Good", unit_price=10.00, quantity=2, created_by=user.id) db_session.add(good) db_session.commit() # Change quantity and update total good.quantity = Decimal("5") good.update_total() assert good.total_amount == Decimal("50.00") # Change unit price and update total good.unit_price = Decimal("15.00") good.update_total() assert good.total_amount == Decimal("75.00") def test_to_dict(self, app, db_session): """Test converting extra good to dictionary""" user = User(username="testuser", email="test@example.com", role="user") user.password_hash = "hash" db_session.add(user) db_session.commit() good = ExtraGood( name="Test Product", unit_price=100.00, quantity=2, created_by=user.id, description="Test desc", category="product", sku="SKU-123", ) db_session.add(good) db_session.commit() data = good.to_dict() assert data["name"] == "Test Product" assert data["quantity"] == 2.0 assert data["unit_price"] == 100.0 assert data["total_amount"] == 200.0 assert data["category"] == "product" assert data["sku"] == "SKU-123" assert data["creator"] == "testuser" def test_get_project_goods(self, app, db_session): """Test getting goods for a project""" client = Client(name="Test Client") db_session.add(client) db_session.commit() user = User(username="testuser", email="test@example.com", role="user") user.password_hash = "hash" db_session.add(user) db_session.commit() project = Project(name="Test Project", client_id=client.id) db_session.add(project) db_session.commit() # Create multiple goods good1 = ExtraGood( name="Good 1", unit_price=10, quantity=1, created_by=user.id, project_id=project.id, billable=True ) good2 = ExtraGood( name="Good 2", unit_price=20, quantity=1, created_by=user.id, project_id=project.id, billable=False ) good3 = ExtraGood( name="Good 3", unit_price=30, quantity=1, created_by=user.id, project_id=project.id, billable=True ) db_session.add_all([good1, good2, good3]) db_session.commit() # Get all goods all_goods = ExtraGood.get_project_goods(project.id) assert len(all_goods) == 3 # Get only billable goods billable_goods = ExtraGood.get_project_goods(project.id, billable_only=True) assert len(billable_goods) == 2 def test_get_total_amount(self, app, db_session): """Test calculating total amount for goods""" client = Client(name="Test Client") db_session.add(client) db_session.commit() user = User(username="testuser", email="test@example.com", role="user") user.password_hash = "hash" db_session.add(user) db_session.commit() project = Project(name="Test Project", client_id=client.id) db_session.add(project) db_session.commit() # Create goods with different amounts good1 = ExtraGood( name="Good 1", unit_price=100, quantity=2, created_by=user.id, project_id=project.id, billable=True ) good2 = ExtraGood( name="Good 2", unit_price=50, quantity=3, created_by=user.id, project_id=project.id, billable=False ) db_session.add_all([good1, good2]) db_session.commit() # Total of all goods: 200 + 150 = 350 total = ExtraGood.get_total_amount(project_id=project.id) assert total == 350.0 # Total of billable goods only: 200 billable_total = ExtraGood.get_total_amount(project_id=project.id, billable_only=True) assert billable_total == 200.0 def test_get_goods_by_category(self, app, db_session): """Test grouping goods by category""" client = Client(name="Test Client") db_session.add(client) db_session.commit() user = User(username="testuser", email="test@example.com", role="user") user.password_hash = "hash" db_session.add(user) db_session.commit() project = Project(name="Test Project", client_id=client.id) db_session.add(project) db_session.commit() # Create goods in different categories good1 = ExtraGood( name="Product 1", unit_price=100, quantity=1, created_by=user.id, project_id=project.id, category="product" ) good2 = ExtraGood( name="Product 2", unit_price=150, quantity=1, created_by=user.id, project_id=project.id, category="product" ) good3 = ExtraGood( name="Service 1", unit_price=200, quantity=1, created_by=user.id, project_id=project.id, category="service" ) db_session.add_all([good1, good2, good3]) db_session.commit() breakdown = ExtraGood.get_goods_by_category(project_id=project.id) assert len(breakdown) == 2 # Find product category product_cat = next((c for c in breakdown if c["category"] == "product"), None) assert product_cat is not None assert product_cat["total_amount"] == 250.0 assert product_cat["count"] == 2 # Find service category service_cat = next((c for c in breakdown if c["category"] == "service"), None) assert service_cat is not None assert service_cat["total_amount"] == 200.0 assert service_cat["count"] == 1