import json from . import models as m from datetime import datetime from django.urls import reverse from django_ledger import models as lm from django.test import Client, TestCase from django.contrib.auth import get_user_model from django_ledger.io.io_core import get_localdate from django.core.exceptions import ObjectDoesNotExist from decimal import Decimal from unittest.mock import MagicMock from inventory.models import VatRate from inventory.utils import CarFinanceCalculator User = get_user_model() # Create your tests here. class ModelTest(TestCase): def setUp(self): email = "RkzgO@example.com" name = "John Doe" password = "password" crn = "123456789" vrn = "123456789" phone = "123456789" address = "123 Main St" arabic_name = "الاسم بالعربية" self.vat = m.VatRate.objects.create(rate=0.15) user = User.objects.create(username=email, email=email) user.set_password(password) user.save() self.dealer = m.Dealer.objects.create( user=user, name=name, arabic_name=arabic_name, crn=crn, vrn=vrn, phone_number=phone, address=address, ) self.car_make = m.CarMake.objects.create(name="Make") self.car_model = m.CarModel.objects.create( name="Model", id_car_make=self.car_make ) self.car_serie = m.CarSerie.objects.create( name="Serie", id_car_model=self.car_model ) self.trim = m.CarTrim.objects.create(name="Trim", id_car_serie=self.car_serie) self.car = m.Car.objects.create( vin="123456789", dealer=self.dealer, id_car_make=self.car_make, id_car_model=self.car_model, id_car_serie=self.car_serie, year=2020, id_car_trim=self.trim, receiving_date=get_localdate(), ) self.car_finances = m.CarFinance.objects.create( car=self.car, selling_price=1000, cost_price=500, discount_amount=200 ) def test_dealer_creation_creates_user_and_entity(self): dealer = self.dealer self.assertEqual(User.objects.count(), 1) self.assertEqual(m.Dealer.objects.count(), 1) self.assertEqual(User.objects.first().username, "RkzgO@example.com") self.assertEqual(User.objects.first().email, "RkzgO@example.com") self.assertTrue(User.objects.first().check_password("password")) self.assertEqual(dealer.user, User.objects.first()) self.assertEqual(dealer.name, "John Doe") self.assertEqual(dealer.arabic_name, "الاسم بالعربية") self.assertEqual(dealer.crn, "123456789") self.assertEqual(dealer.vrn, "123456789") self.assertEqual(dealer.phone_number, "123456789") self.assertEqual(dealer.address, "123 Main St") self.assertIsNotNone(dealer.entity) self.assertEqual(dealer.entity.name, dealer.name) self.assertEqual(dealer.entity.get_all_accounts().count(), 57) self.assertEqual(dealer.entity.get_uom_all().count(), 16) def test_car_creation_creates_product(self): dealer = self.dealer self.assertEqual(m.Car.objects.count(), 1) self.assertEqual(self.car.vin, "123456789") self.assertEqual(self.car.dealer, dealer) self.assertEqual(self.car.id_car_make, self.car_make) self.assertEqual(self.car.id_car_model, self.car_model) self.assertEqual(self.car.id_car_serie, self.car_serie) self.assertEqual(self.car.year, 2020) self.assertEqual(self.car.id_car_trim, self.trim) product = dealer.entity.get_items_all().filter(name=self.car.vin).first() self.assertEqual(product.name, self.car.vin) def test_car_finances_creation(self): self.assertEqual(m.CarFinance.objects.count(), 1) self.assertEqual(self.car_finances.car, self.car) self.assertEqual(self.car_finances.selling_price, 1000) self.assertEqual(self.car_finances.cost_price, 500) self.assertEqual(self.car_finances.discount_amount, 200) def test_car_finance_total(self): self.assertEqual(m.CarFinance.objects.count(), 1) self.assertEqual(self.car_finances.total, 1000) self.assertEqual(self.car_finances.total_discount, 800) self.assertEqual(self.car_finances.total_vat, 920) def test_car_additional_services_create_item_service(self): m.AdditionalServices.objects.create( name="Service", price=100, description="Description", dealer=self.dealer, taxable=True, uom=m.UnitOfMeasure.PIECE, ) self.assertEqual( m.ItemModel.objects.filter( name="Service", default_amount=100, is_product_or_service=True, item_role="service", ).count(), 1, ) class AuthenticationTest(TestCase): def setUp(self): self.client = Client() self.url = reverse("account_signup") def test_login(self): url = reverse("account_login") response = self.client.post(url, {"email": "RkzgO@example.com", "password": "password"}) self.assertEqual(response.status_code, 200) def test_valid_data(self): # Create valid JSON data data = { "wizardValidationForm1": { "email": "test@example.com", "password": "password123", "confirm_password": "password123" }, "wizardValidationForm2": { "name": "John Doe", "arabic_name": "جون دو", "phone_number": "1234567890" }, "wizardValidationForm3": { "crn": "123456", "vrn": "789012", "address": "123 Main St" } } # Send a POST request with the JSON data response = self.client.post( self.url, data=json.dumps(data), content_type='application/json' ) # Check the response self.assertEqual(response.status_code, 200) self.assertEqual(response.json(), {'message': 'User created successfully.'}) def test_passwords_do_not_match(self): # Create JSON data with mismatched passwords data = { "wizardValidationForm1": { "email": "test@example.com", "password": "password123", "confirm_password": "differentpassword" }, "wizardValidationForm2": { "name": "John Doe", "arabic_name": "جون دو", "phone_number": "1234567890" }, "wizardValidationForm3": { "crn": "123456", "vrn": "789012", "address": "123 Main St" } } # Send a POST request with the JSON data response = self.client.post( self.url, data=json.dumps(data), content_type='application/json' ) # Check the response self.assertEqual(response.status_code, 400) self.assertEqual(response.json(), {"error": "Passwords do not match."}) def test_missing_required_fields(self): # Create JSON data with missing required fields data = { "wizardValidationForm1": { "email": "test@example.com", "password": "password123", # Missing "confirm_password" }, "wizardValidationForm2": { "name": "John Doe", "arabic_name": "جون دو", "phone_number": "1234567890" }, "wizardValidationForm3": { "crn": "123456", "vrn": "789012", "address": "123 Main St" } } # Send a POST request with the JSON data response = self.client.post( self.url, data=json.dumps(data), content_type='application/json' ) # Check the response self.assertEqual(response.status_code, 400) self.assertIn("error", response.json()) # Assuming the view returns an error for missing fields class CarFinanceCalculatorTests(TestCase): def setUp(self): # Common setup for all tests self.mock_model = MagicMock() self.vat_rate = VatRate.objects.create(rate=Decimal('0.20'), is_active=True) def test_no_active_vat_rate_raises_error(self): VatRate.objects.all().delete() # Ensure no active VAT with self.assertRaises(ObjectDoesNotExist): CarFinanceCalculator(self.mock_model) def test_vat_rate_retrieval(self): calculator = CarFinanceCalculator(self.mock_model) self.assertEqual(calculator.vat_rate, Decimal('0.20')) def test_item_transactions_retrieval(self): mock_item = MagicMock() self.mock_model.get_itemtxs_data.return_value = [MagicMock(all=lambda: [mock_item])] calculator = CarFinanceCalculator(self.mock_model) self.assertEqual(calculator.item_transactions, [mock_item]) def test_get_car_data(self): mock_item = MagicMock() mock_item.ce_quantity = 2 mock_item.item_model = MagicMock() mock_item.item_model.item_number = '123' mock_item.item_model.additional_info = { CarFinanceCalculator.CAR_FINANCE_KEY: { 'selling_price': '10000', 'cost_price': '8000', 'discount_amount': '500', 'total_vat': '2000' }, CarFinanceCalculator.CAR_INFO_KEY: { 'vin': 'VIN123', 'make': 'Toyota', 'model': 'Camry', 'year': 2020, 'trim': 'LE', 'mileage': 15000 }, CarFinanceCalculator.ADDITIONAL_SERVICES_KEY: [ {'name': 'Service 1', 'price': '200', 'taxable': True, 'price_': '240'} ] } calculator = CarFinanceCalculator(self.mock_model) car_data = calculator._get_car_data(mock_item) self.assertEqual(car_data['item_number'], '123') self.assertEqual(car_data['vin'], 'VIN123') self.assertEqual(car_data['make'], 'Toyota') self.assertEqual(car_data['selling_price'], '10000') self.assertEqual(car_data['unit_price'], Decimal('10000')) self.assertEqual(car_data['quantity'], 2) self.assertEqual(car_data['total'], Decimal('20000')) self.assertEqual(car_data['total_vat'], '2000') self.assertEqual(car_data['additional_services'], [{'name': 'Service 1', 'price': '200', 'taxable': True, 'price_': '240'}]) def test_get_additional_services(self): mock_item1 = MagicMock() mock_item1.item_model.additional_info = { CarFinanceCalculator.ADDITIONAL_SERVICES_KEY: [ {'name': 'Service 1', 'price': '100', 'taxable': True, 'price_': '120'} ] } mock_item2 = MagicMock() mock_item2.item_model.additional_info = { CarFinanceCalculator.ADDITIONAL_SERVICES_KEY: [ {'name': 'Service 2', 'price': '200', 'taxable': False, 'price_': '200'} ] } self.mock_model.get_itemtxs_data.return_value = [MagicMock(all=lambda: [mock_item1, mock_item2])] calculator = CarFinanceCalculator(self.mock_model) services = calculator._get_additional_services() self.assertEqual(len(services), 2) self.assertEqual(services[0]['name'], 'Service 1') self.assertEqual(services[1]['name'], 'Service 2') self.assertEqual(services[0]['price_'], '120') self.assertEqual(services[1]['price_'], '200') def test_calculate_totals(self): mock_item1 = MagicMock() mock_item1.ce_quantity = 2 mock_item1.item_model.additional_info = { CarFinanceCalculator.CAR_FINANCE_KEY: { 'selling_price': '10000', 'discount_amount': '500' }, CarFinanceCalculator.ADDITIONAL_SERVICES_KEY: [ {'price_': '100'}, {'price_': '200'} ] } mock_item2 = MagicMock() mock_item2.quantity = 3 mock_item2.item_model.additional_info = { CarFinanceCalculator.CAR_FINANCE_KEY: { 'selling_price': '20000', 'discount_amount': '1000' }, CarFinanceCalculator.ADDITIONAL_SERVICES_KEY: [ {'price_': '300'} ] } self.mock_model.get_itemtxs_data.return_value = [MagicMock(all=lambda: [mock_item1, mock_item2])] calculator = CarFinanceCalculator(self.mock_model) totals = calculator.calculate_totals() expected_total_price = (Decimal('10000') * 2 + Decimal('20000') * 3) - (Decimal('500') + Decimal('1000')) expected_vat = expected_total_price * Decimal('0.15') expected_additionals = Decimal('100') + Decimal('200') + Decimal('300') expected_grand_total = (expected_total_price + expected_vat + expected_additionals).quantize(Decimal('0.00')) self.assertEqual(totals['total_price'], expected_total_price) self.assertEqual(totals['total_discount'], Decimal('1500')) self.assertEqual(totals['total_vat_amount'], expected_vat) self.assertEqual(totals['total_additionals'], expected_additionals) self.assertEqual(totals['grand_total'], expected_grand_total) def test_get_finance_data(self): mock_item = MagicMock() mock_item.ce_quantity = 1 mock_item.item_model = MagicMock() mock_item.item_model.item_number = '456' mock_item.item_model.additional_info = { CarFinanceCalculator.CAR_FINANCE_KEY: { 'selling_price': '15000', 'discount_amount': '1000', 'total_vat': '2800' }, CarFinanceCalculator.CAR_INFO_KEY: { 'vin': 'VIN456', 'make': 'Honda', 'model': 'Civic', 'year': 2021 }, CarFinanceCalculator.ADDITIONAL_SERVICES_KEY: [ {'name': 'Service', 'price': '150', 'taxable': True, 'price_': '180'} ] } self.mock_model.get_itemtxs_data.return_value = [MagicMock(all=lambda: [mock_item])] calculator = CarFinanceCalculator(self.mock_model) finance_data = calculator.get_finance_data() self.assertEqual(len(finance_data['cars']), 1) self.assertEqual(finance_data['quantity'], 1) self.assertEqual(finance_data['total_price'], Decimal('14000')) # 15000 - 1000 self.assertEqual(finance_data['total_vat'], Decimal('14000') + (Decimal('14000') * Decimal('0.20'))) self.assertEqual(finance_data['total_vat_amount'], Decimal('14000') * Decimal('0.20')) self.assertEqual(finance_data['total_additionals'], Decimal('180')) self.assertEqual(finance_data['additionals'][0]['name'], 'Service') self.assertEqual(finance_data['vat'], Decimal('0.20'))