from decimal import Decimal from django.contrib.auth import get_user_model from django.test import TestCase from django.urls import reverse from inventory.models import Item, ItemTemplate from inventory.services import PricingSuggestionService User = get_user_model() class ItemModelTests(TestCase): def setUp(self): self.user = User.objects.create_user(username="alice", password="password123") def test_profit_uses_costs_and_sale_price(self): item = Item.objects.create( created_by=self.user, title="Vintage jacket", category="Apparel", purchase_price=Decimal("10.00"), ebay_fee=Decimal("2.00"), shipping_cost=Decimal("4.00"), sold_price=Decimal("30.00"), status=Item.Status.SOLD, ) self.assertEqual(item.total_cost, Decimal("16.00")) self.assertEqual(item.profit, Decimal("14.00")) class ItemCreateViewTests(TestCase): def setUp(self): self.user = User.objects.create_user(username="alice", password="password123") self.template = ItemTemplate.objects.create( name="Blanket", category="Home", default_purchase_price=Decimal("8.00"), default_estimated_resale_price=Decimal("24.00"), default_notes="Check for stains.", ) def test_template_defaults_are_applied_on_create(self): self.client.login(username="alice", password="password123") response = self.client.post( reverse("item-create"), { "template": self.template.id, "title": "Wool blanket", "brand": "Pendleton", "category": "", "condition": "Good", "size": "Queen", "color": "Red", "purchase_price": "", "estimated_resale_price": "", "notes": "", }, ) self.assertEqual(response.status_code, 302) item = Item.objects.get(title="Wool blanket") self.assertEqual(item.category, "Home") self.assertEqual(item.purchase_price, Decimal("8.00")) self.assertEqual(item.estimated_resale_price, Decimal("24.00")) self.assertEqual(item.notes, "Check for stains.") self.assertEqual(item.created_by, self.user) class ItemWorkflowTests(TestCase): def setUp(self): self.user = User.objects.create_user(username="alice", password="password123") self.other_user = User.objects.create_user(username="bob", password="password123") self.item = Item.objects.create( created_by=self.user, title="Leather boots", category="Shoes", purchase_price=Decimal("20.00"), ) def test_dashboard_filters_by_query(self): self.client.login(username="alice", password="password123") response = self.client.get(reverse("dashboard"), {"query": "boots"}) self.assertContains(response, "Leather boots") def test_mark_item_sold_sets_status_and_sold_date(self): self.client.login(username="alice", password="password123") response = self.client.post( reverse("item-mark-sold", kwargs={"pk": self.item.pk}), { "sold_price": "55.00", "ebay_fee": "5.00", "shipping_cost": "7.00", "sold_at": "", }, ) self.assertEqual(response.status_code, 302) self.item.refresh_from_db() self.assertEqual(self.item.status, Item.Status.SOLD) self.assertEqual(self.item.sold_price, Decimal("55.00")) self.assertIsNotNone(self.item.sold_at) def test_editing_item_does_not_change_creator(self): self.client.login(username="bob", password="password123") response = self.client.post( reverse("item-edit", kwargs={"pk": self.item.pk}), { "template": "", "title": "Leather boots updated", "brand": "", "category": "Shoes", "condition": "", "size": "", "color": "", "purchase_price": "20.00", "estimated_resale_price": "", "notes": "Updated notes", }, ) self.assertEqual(response.status_code, 302) self.item.refresh_from_db() self.assertEqual(self.item.title, "Leather boots updated") self.assertEqual(self.item.created_by, self.user) class TemplateAndPricingTests(TestCase): def setUp(self): self.user = User.objects.create_user(username="alice", password="password123") def test_template_edit_updates_existing_template(self): template = ItemTemplate.objects.create(name="Mugs", category="Kitchen") self.client.login(username="alice", password="password123") response = self.client.post( reverse("template-edit", kwargs={"pk": template.pk}), { "name": "Mugs and cups", "description": "Glassware", "category": "Kitchen", "default_purchase_price": "3.00", "default_estimated_resale_price": "12.00", "default_notes": "Check for chips.", "is_active": "on", }, ) self.assertEqual(response.status_code, 302) template.refresh_from_db() self.assertEqual(template.name, "Mugs and cups") self.assertEqual(template.default_purchase_price, Decimal("3.00")) def test_pricing_suggestion_uses_recent_sold_comps(self): sold_one = Item.objects.create( created_by=self.user, title="Blue sweater", category="Apparel", purchase_price=Decimal("10.00"), ) sold_one.mark_sold(Decimal("40.00")) sold_two = Item.objects.create( created_by=self.user, title="Green sweater", category="Apparel", purchase_price=Decimal("12.00"), ) sold_two.mark_sold(Decimal("60.00")) unsold = Item.objects.create( created_by=self.user, title="Striped sweater", category="Apparel", purchase_price=Decimal("15.00"), ) suggestion = PricingSuggestionService().suggest_for_item(unsold) self.assertEqual(suggestion["price"], Decimal("50.00")) self.assertEqual(suggestion["source"], "Recent sold comps")