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,VendorModel,CustomerModel 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() for item in data: if not item.item_model.additional_info.get("car_finance"): return { "vat_amount": 0, "total": 0, "grand_total": 0, "discount_amount": 0, "vat": 0, "car_and_item_info": [], "additional_services": [], } if isinstance(model, InvoiceModel): if model.ce_model: data = model.ce_model.get_itemtxs_data()[0].all() else: data = model.get_itemtxs_data()[0].all() total = sum([Decimal(item.item_model.additional_info["car_finance"]["selling_price"]) * Decimal(item.ce_quantity or item.quantity) for item in data]) discount_amount = sum( Decimal(i.item_model.additional_info['car_finance']["discount_amount"]) for i in data ) additional_services = [] for i in data: if i.item_model.additional_info['additional_services']: additional_services.extend( [ {"name": x.name, "price": x.price} for x in i.item_model.additional_info['additional_services'] ] ) grand_total = Decimal(total) - Decimal(discount_amount) vat_amount = round(Decimal(grand_total) * Decimal(vat.rate), 2) car_and_item_info = [ { "info": x.item_model.additional_info['car_info'], "finances": x.item_model.additional_info['car_finance'], "quantity": x.ce_quantity or x.quantity, "total": Decimal(x.item_model.additional_info['car_finance']['selling_price']) * Decimal(x.ce_quantity or x.quantity), } for x in data ] return { "total": total, "discount_amount": discount_amount, "car_and_item_info": car_and_item_info, "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) total_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", ) # if total_amount + invoice. TransactionModel.objects.create( journal_entry=journal, account=credit_account, # Credit Accounts Receivable amount=total_amount, # 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 customer = from_dealer.entity.get_customers().filter( email=to_dealer.user.email).first() if not customer: customer = from_dealer.entity.create_customer( customer_model_kwargs={ "customer_name": to_dealer.name, "email": to_dealer.user.email, "address_1": to_dealer.address } ) customer.additional_info.update({"type":"organization"}) customer.save() 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": transfer.total_price, "quantity": transfer.quantity, "total_amount": transfer.total_price, } } invoice_itemtxs = invoice.migrate_itemtxs( itemtxs=invoice_itemtxs, commit=True, operation=InvoiceModel.ITEMIZE_APPEND, ) invoice.save() 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() #create item product in the reciever ledger 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(), ) product.additional_info.update({'car_info': car.to_dict()}) product.save() #add the sender as vendor and create a bill for it vendor = None vendor = to_dealer.entity.get_vendors().filter(vendor_name=from_dealer.name).first() if not vendor: vendor = VendorModel.objects.create(entity_model=to_dealer.entity, vendor_name=from_dealer.name,additional_info={"info":to_dict(from_dealer)}) #transfer the car to to_dealer and create items record 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.additional_info = {} bill_itemtxs = { product.item_number: { "unit_cost": transfer.total_price, "quantity": transfer.quantity, "total_amount": transfer.total_price, } } bill_itemtxs = bill.migrate_itemtxs(itemtxs=bill_itemtxs, commit=True, operation=BillModel.ITEMIZE_APPEND) bill.additional_info.update({'car_info': car.to_dict()}) bill.additional_info.update({'car_finance': car.finances.to_dict()}) bill.mark_as_review() bill.mark_as_approved(to_dealer.entity.slug, to_dealer.entity.admin) bill.save() car.dealer = to_dealer car.vendor = vendor car.receiving_date = datetime.datetime.now() car.finances.additional_services.clear() if hasattr(car, "custom_cards"): car.custom_cards.delete() car.finances.cost_price = transfer.total_price 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.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") def to_dict(obj): obj_dict = vars(obj).copy() if '_state' in vars(obj): del obj_dict["_state"] for key, value in obj_dict.items(): if isinstance(value, datetime.datetime): obj_dict[key] = value.strftime('%Y-%m-%d %H:%M:%S') elif hasattr(value,'pk') or hasattr(value,'id'): try: obj_dict[key] = value.name except AttributeError: obj_dict[key] = str(value) else: obj_dict[key] = str(value) return obj_dict