haikal/inventory/utils.py
2025-01-21 11:35:58 +00:00

472 lines
15 KiB
Python

import json
import random
import datetime
from django.shortcuts import redirect
from django.contrib import messages
from django.utils import timezone
from django_ledger.models.entity import UnitOfMeasureModel
from django_ledger.models.journal_entry import JournalEntryModel
from django_ledger.models.ledger import LedgerModel
from django_ledger.models.transactions import TransactionModel
import requests
from inventory import models
from django.conf import settings
from django.core.mail import send_mail
from django.utils.translation import gettext_lazy as _
from inventory.utilities.financials import get_financial_value
from django_ledger.models.items import ItemModel
from django_ledger.models import InvoiceModel, EstimateModel,BillModel
from decimal import Decimal
def get_jwt_token():
url = "https://carapi.app/api/auth/login"
headers = {
"accept": "text/plain",
"Content-Type": "application/json",
}
data = {
"api_token": "f5204a00-6f31-4de2-96d8-ed998e0d230c",
"api_secret": "8c11320781a5b8f4f327b6937e6f8241",
}
try:
response = requests.post(url, headers=headers, json=data)
response.raise_for_status()
return response.text
except requests.exceptions.RequestException as e:
print(f"Error obtaining JWT token: {e}")
return None
def localize_some_words():
success = _("success")
error = _("error")
forget = _("Forgot Password?")
return None
def get_calculations(quotation):
context = {}
qc_len = quotation.quotation_cars.count()
cars = [x.car for x in quotation.quotation_cars.all()]
finances = models.CarFinance.objects.filter(car__in=cars)
services = ItemModel.objects.filter(additional_finances__in=finances).all()
data = [
{
"name": x.name,
"price": x.default_amount,
"total_price": x.default_amount * qc_len,
"vated": float(x.default_amount) * 0.15 * float(qc_len),
"total_price_vat": float(x.default_amount)
+ (float(x.default_amount) * 0.15 * float(qc_len)),
}
for x in services
]
context["services"] = data
context["total_cost"] = 0
context["total_vat"] = 0
context["total_cost_vat"] = 0
for k in context["services"]:
context["total_cost"] += k["total_price"]
context["total_vat"] += k["vated"]
context["total_cost_vat"] = float(context["total_cost"]) + float(
context["total_vat"]
)
return context
def send_email(from_, to_, subject, message):
subject = subject
message = message
from_email = from_
recipient_list = [to_]
send_mail(subject, message, from_email, recipient_list)
def get_user_type(request):
dealer = ""
if hasattr(request.user, "dealer"):
dealer = request.user.dealer
elif hasattr(request.user, "staff"):
dealer = request.user.staff.dealer
return dealer
def get_dealer_from_instance(instance):
if instance.dealer.staff:
return instance.dealer
else:
return instance.dealer
def reserve_car(car, request):
try:
reserved_until = timezone.now() + timezone.timedelta(hours=24)
models.CarReservation.objects.create(
car=car, reserved_by=request.user, reserved_until=reserved_until
)
car.status = models.CarStatusChoices.RESERVED
car.save()
messages.success(request, _("Car reserved successfully."))
except Exception as e:
messages.error(request, f"Error reserving car: {e}")
return redirect("car_detail", pk=car.pk)
def calculate_vat_amount(amount):
vat = models.VatRate.objects.filter(is_active=True).first()
if vat:
return ((amount * Decimal(vat.rate)).quantize(Decimal("0.01")), vat.rate)
return amount
def get_financial_values(model):
vat = models.VatRate.objects.filter(is_active=True).first()
if not model.get_itemtxs_data()[0].exists():
return {
"vat_amount": 0,
"total": 0,
"grand_total": 0,
"discount_amount": 0,
"vat": 0,
"car_and_item_info": [],
"additional_services": [],
}
data = model.get_itemtxs_data()[0].all()
if isinstance(model, InvoiceModel):
data = model.ce_model.get_itemtxs_data()[0].all()
car_and_item_info = [
{
"car": models.Car.objects.get(vin=x.item_model.name),
"total": models.Car.objects.get(
vin=x.item_model.name
).finances.selling_price
* Decimal(x.ce_quantity),
"itemmodel": x,
}
for x in data
]
total = sum(
Decimal(models.Car.objects.get(vin=x.item_model.name).finances.total)
* Decimal(x.ce_quantity)
for x in data
)
discount_amount = sum(
models.CarFinance.objects.get(car__vin=i.item_model.name).discount_amount
for i in data
)
additional_services = []
for i in data:
cf = models.CarFinance.objects.get(car__vin=i.item_model.name)
if cf.additional_services.exists():
additional_services.extend(
[
{"name": x.name, "price": x.price}
for x in cf.additional_services.all()
]
)
grand_total = Decimal(total) - Decimal(discount_amount)
vat_amount = round(Decimal(grand_total) * Decimal(vat.rate), 2)
return {
"car_and_item_info": car_and_item_info,
"total": total,
"discount_amount": discount_amount,
"additional_services": additional_services,
"grand_total": grand_total + vat_amount,
"vat_amount": vat_amount,
"vat": vat.rate,
}
def set_invoice_payment(dealer, entity, invoice, amount, payment_method):
vat_amount = 0
total_amount = 0
if invoice.terms == "on_receipt":
for x in invoice.get_itemtxs_data()[0].all():
vat_amount += models.Car.objects.get(
vin=x.item_model.name
).finances.vat_amount * Decimal(x.quantity)
total_amount += Decimal(x.unit_cost) * Decimal(x.quantity)
grand_total = total_amount - Decimal(vat_amount)
ledger = LedgerModel.objects.filter(
name__icontains=str(invoice.pk), entity=entity
).first()
journal = JournalEntryModel.objects.create(
posted=False,
description=f"Payment for Invoice {invoice.invoice_number}",
ledger=ledger,
locked=False,
origin="Payment",
)
credit_account = entity.get_default_coa_accounts().get(name="Sales Revenue")
debit_account = None
if payment_method == "cash":
debit_account = entity.get_default_coa_accounts().get(name="Cash", active=True)
elif payment_method == "credit":
debit_account = entity.get_default_coa_accounts().get(
name="Accounts Receivable", active=True
)
else:
debit_account = entity.get_default_coa_accounts().get(
name="Cash in Bank", active=True
)
vat_payable_account = entity.get_default_coa_accounts().get(
name="VAT Payable", active=True
)
TransactionModel.objects.create(
journal_entry=journal,
account=debit_account, # Debit Cash
amount=amount, # Payment amount
tx_type="debit",
description="Payment Received",
)
TransactionModel.objects.create(
journal_entry=journal,
account=credit_account, # Credit Accounts Receivable
amount=grand_total, # Payment amount
tx_type="credit",
description="Payment Received",
)
if vat_amount > 0:
TransactionModel.objects.create(
journal_entry=journal,
account=vat_payable_account, # Credit VAT Payable
amount=vat_amount,
tx_type="credit",
description="VAT Payable on Invoice",
)
invoice.make_payment(amount)
invoice.save()
def set_bill_payment(dealer, entity, bill, amount, payment_method):
total_amount = 0
for x in bill.get_itemtxs_data()[0].all():
total_amount += Decimal(x.unit_cost) * Decimal(x.quantity)
journal = JournalEntryModel.objects.create(
posted=False,
description=f"Payment for bill {bill.bill_number}",
ledger=bill.ledger,
locked=False,
origin="Payment",
)
cash_account = entity.get_default_coa_accounts().get(name="Cash", active=True)
account_payable = entity.get_default_coa_accounts().get(
name="Accounts Payable", active=True
)
TransactionModel.objects.create(
journal_entry=journal,
account=cash_account, # Debit Cash
amount=amount, # Payment amount
tx_type="debit",
description="Payment Received",
)
TransactionModel.objects.create(
journal_entry=journal,
account=account_payable, # Credit Accounts Receivable
amount=amount, # Payment amount
tx_type="credit",
description="Payment Received",
)
bill.make_payment(amount)
bill.save()
def transfer_to_dealer(request,cars, to_dealer, remarks=None):
dealer = get_user_type(request)
if not cars:
raise ValueError("No cars selected for transfer.")
from_dealer = cars[0].dealer # Assume all cars are from the same dealer
# Validate that all cars are from the same dealer
for car in cars:
if car.dealer != from_dealer:
raise ValueError("All cars must be from the same dealer.")
if from_dealer == to_dealer:
raise ValueError("Cannot transfer cars to the same dealer.")
# Log the transfer
transfer_log = models.CarTransferLog.objects.create(
from_dealer=from_dealer,
to_dealer=to_dealer,
remarks=remarks,
)
transfer_log.cars.set(cars) # Associate the cars with the transfer log
# Update the dealer for all cars
for car in cars:
car.dealer = to_dealer
car.save()
def transfer_car(car,transfer):
from_dealer = transfer.from_dealer
to_dealer = transfer.to_dealer
# add transfer.to_dealer as customer in transfer.from_dealer entity
instance = models.Customer.objects.filter(
dealer=from_dealer,
email=to_dealer.user.email,
).first()
if not instance:
instance = models.Customer.objects.create(
dealer=from_dealer,
title=models.Title.MR,
email=to_dealer.user.email,
first_name=to_dealer.user.first_name,
last_name=to_dealer.user.last_name,
phone_number=f"05685412{random.randint(10, 99)}",
address=to_dealer.address,
national_id=f"{random.randint(100, 9999)}",
dob="1990-01-01",
)
# create invoice from transfer.from_dealer to transfer.to_dealer
name = f"{instance.first_name} {instance.middle_name} {instance.last_name}"
customer = from_dealer.entity.get_customers().filter(customer_name=name).first()
invoice = from_dealer.entity.create_invoice(
customer_model=customer,
terms=InvoiceModel.TERMS_NET_30,
cash_account=from_dealer.entity.get_default_coa_accounts().get(name="Cash", active=True),
prepaid_account=from_dealer.entity.get_default_coa_accounts().get(name="Accounts Receivable", active=True),
coa_model=from_dealer.entity.get_default_coa(),
)
ledger = from_dealer.entity.create_ledger(name=str(invoice.pk))
invoice.ledgar = ledger
ledger.invoicemodel = invoice
ledger.save()
invoice.save()
item = from_dealer.entity.get_items_products().filter(name=car.vin).first()
if not item:
return
invoice_itemtxs = {
item.item_number: {
"unit_cost": car.finances.cost_price,
"quantity": transfer.quantity,
"total_amount": transfer.total_price,
}
}
invoice_itemtxs = invoice.migrate_itemtxs(
itemtxs=invoice_itemtxs,
commit=True,
operation=InvoiceModel.ITEMIZE_APPEND,
)
invoice.mark_as_review()
invoice.mark_as_approved(from_dealer.entity.slug, from_dealer.entity.admin)
invoice.mark_as_paid(from_dealer.entity.slug, from_dealer.entity.admin)
invoice.save()
#create car item product in to_dealer entity
uom = to_dealer.entity.get_uom_all().filter(name=item.uom.name).first()
product = to_dealer.entity.create_item_product(
name=item.name,
uom_model=uom,
item_type=item.item_type,
coa_model=to_dealer.entity.get_default_coa(),
)
car_dict = vars(car).copy()
del car_dict["_state"]
for key, value in car_dict.items():
if isinstance(value, datetime.datetime):
car_dict[key] = value.strftime('%Y-%m-%d %H:%M:%S')
product.additional_info = json.dumps({"car_info": car_dict})
product.save()
#add the sender as vendor and create a bill for it
vendor_instance, created = models.Vendor.objects.get_or_create(
dealer=to_dealer,
crn=from_dealer.crn,
vrn=from_dealer.vrn,
name=from_dealer.name,
email=from_dealer.user.email,
arabic_name=from_dealer.arabic_name,
address=from_dealer.address,
phone_number=from_dealer.phone_number,
contact_person='',
)
#transfer the car to to_dealer and create items record
vendor = to_dealer.entity.get_vendors().filter(vendor_name=vendor_instance.name).first()
bill = to_dealer.entity.create_bill(
vendor_model=vendor,
terms=BillModel.TERMS_NET_30,
cash_account=to_dealer.entity.get_default_coa_accounts().get(name="Cash", active=True),
prepaid_account=to_dealer.entity.get_default_coa_accounts().get(name="Prepaid Expenses", active=True),
coa_model=to_dealer.entity.get_default_coa(),
)
bill_itemtxs = {
item.item_number: {
"unit_cost": car.finances.cost_price,
"quantity": transfer.quantity,
"total_amount": transfer.total_price,
}
}
bill_itemtxs = bill.migrate_itemtxs(itemtxs=bill_itemtxs,
commit=True,
operation=BillModel.ITEMIZE_REPLACE)
car.dealer = to_dealer
car.vendor = vendor_instance
car.receiving_date = datetime.datetime.now()
car.finances.additional_services.clear()
if hasattr(car, "custom_cards"):
car.custom_cards.delete()
# car.finances.cost_price = 0
car.finances.selling_price = 0
car.finances.discount_amount = 0
car.finances.save()
car.location.owner = to_dealer
car.location.showroom = to_dealer
car.location.description = ""
car.location.save()
# car.reservations.all().delete()
car.status = models.CarStatusChoices.AVAILABLE
transfer.status = models.CarTransferStatusChoices.success
transfer.active = False
transfer.save()
car.save()
return True
#pay the pill
# set_bill_payment(to_dealer,to_dealer.entity,bill,transfer.total_price,"credit")