185 lines
6.4 KiB
Python
185 lines
6.4 KiB
Python
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")
|