404 lines
15 KiB
Python
404 lines
15 KiB
Python
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')) |