from django.db.models.signals import post_save, post_delete, pre_delete, pre_save from django.dispatch import receiver from django.utils.translation import gettext_lazy as _ from django.contrib.auth import get_user_model from django_ledger.io import roles from django_ledger.models import ( EntityModel, AccountModel, ItemModel, ItemModelAbstract, UnitOfMeasureModel, VendorModel, ) from . import models User = get_user_model() # @receiver(post_save, sender=models.SaleQuotation) # def link_quotation_to_entity(sender, instance, created, **kwargs): # if created: # # Get the corresponding Django Ledger entity for the dealer # entity = EntityModel.objects.get(name=instance.dealer.get_root_dealer.name) # instance.entity = entity # instance.save() # @receiver(pre_delete, sender=models.Dealer) # def remove_user_account(sender, instance, **kwargs): # user = instance.user # if user: # user.delete() # # @receiver(post_save, sender=User) # def create_dealer(instance, created, *args, **kwargs): # if created: # if not instance.dealer: # # models.Dealer.objects.create(user=instance,name=instance.username,email=instance.email) # # @receiver(post_save, sender=models.Dealer) # def create_user_account(sender, instance, created, **kwargs): # if created: # if instance.dealer_type != "Owner": # user = User.objects.create_user( # username=instance.name, # email=instance.email, # ) # user.set_password("Tenhal@123") # user.save() # instance.user = user # instance.save() # check with marwan @receiver(post_save, sender=models.Car) def create_car_location(sender, instance, created, **kwargs): """ Signal to create or update the car's location when a car instance is saved. """ try: if created: if instance.dealer is None: raise ValueError( f"Cannot create CarLocation for car {instance.vin}: dealer is missing." ) models.CarLocation.objects.create( car=instance, owner=instance.dealer, showroom=instance.dealer, description=f"Initial location set for car {instance.vin}.", ) print("Car Location created") except Exception as e: print(f"Failed to create CarLocation for car {instance.vin}: {e}") # @receiver(post_save, sender=models.CarReservation) # def update_car_status_on_reservation(sender, instance, created, **kwargs): # if created: # car = instance.car # car.status = models.CarStatusChoices.RESERVED # car.save() # @receiver(post_delete, sender=models.CarReservation) # def update_car_status_on_reservation_delete(sender, instance, **kwargs): # car = instance.car # if not car.is_reserved(): # car.status = models.CarStatusChoices.AVAILABLE # car.save() # Create Entity @receiver(post_save, sender=models.Dealer) def create_ledger_entity(sender, instance, created, **kwargs): if created: entity_name = instance.user.dealer.name entity = EntityModel.create_entity( name=entity_name, admin=instance.user, use_accrual_method=False, fy_start_month=1, ) if entity: instance.entity = entity instance.save() coa = entity.create_chart_of_accounts( assign_as_default=True, commit=True, coa_name=_(f"{entity_name}-COA") ) if coa: # entity.populate_default_coa(activate_accounts=True, coa_model=coa) print(f"Ledger entity created for Dealer: {instance.name}") # Create unit of measures entity.create_uom(name="Unit", unit_abbr="unit") for u in models.UnitOfMeasure.choices: entity.create_uom(name=u[1], unit_abbr=u[0]) # Create Cash Account asset_ca_cash = entity.create_account( coa_model=coa, code="1010", role=roles.ASSET_CA_CASH, name=_("Cash"), balance_type="debit", active=True, ) asset_ca_cash.role_default = True asset_ca_cash.save() # Create Accounts Receivable Account asset_ca_receivables = entity.create_account( coa_model=coa, code="1102", role=roles.ASSET_CA_RECEIVABLES, name=_("Accounts Receivable"), balance_type="debit", active=True, ) asset_ca_receivables.role_default = True asset_ca_receivables.save() # Create Inventory Account asset_ca_inventory = entity.create_account( coa_model=coa, code="1103", role=roles.ASSET_CA_INVENTORY, name=_("Inventory"), balance_type="debit", active=True, ) asset_ca_inventory.role_default = True asset_ca_inventory.save() # Create Accounts Payable Account asset_ca_accounts_payable = entity.create_account( coa_model=coa, code="2101", role=roles.LIABILITY_CL_ACC_PAYABLE, name=_("Accounts Payable"), balance_type="credit", active=True, ) # add Bank # asset_ca_accounts_payable = entity.create_account( # coa_model=coa, # code="2101", # role=roles.LIABILITY_CL_ACC_PAYABLE, # name=_("Accounts Payable"), # balance_type="credit", # active=True, # ) asset_ca_accounts_payable.role_default = True asset_ca_accounts_payable.save() # Create Equity Account asset_ca_equity = entity.create_account( coa_model=coa, code="3101", role=roles.EQUITY_CAPITAL, name=_("Partners Current"), balance_type="credit", active=True, ) asset_ca_equity.role_default = True asset_ca_equity.save() # Create Sales Revenue Account asset_ca_revenue = entity.create_account( coa_model=coa, code="4101", role=roles.INCOME_OPERATIONAL, name=_("Sales Revenue"), balance_type="credit", active=True, ) asset_ca_revenue.role_default = True asset_ca_revenue.save() # Create Cost of Goods Sold Account asset_ca_cogs = entity.create_account( coa_model=coa, code="5101", role=roles.COGS, name=_("Cost of Goods Sold"), balance_type="debit", active=True, ) asset_ca_cogs.role_default = True asset_ca_cogs.save() # Create Rent Expense Account expense = entity.create_account( coa_model=coa, code="6101", role=roles.EXPENSE_OPERATIONAL, name=_("Rent Expense"), balance_type="debit", active=True, ) expense.role_default = True expense.save() # Create Utilities Expense Account entity.create_account( coa_model=coa, code="6020", role=roles.EXPENSE_OPERATIONAL, name=_("Utilities Expense"), balance_type="debit", active=True, ) # Create Deferred Revenue Account unearned_account = entity.create_account( coa_model=coa, code="2060", role=roles.LIABILITY_CL_DEFERRED_REVENUE, name=_("Deferred Revenue"), balance_type="credit", active=True, ) unearned_account.role_default = True unearned_account.save() # Create Vendor @receiver(post_save, sender=models.Vendor) def create_ledger_vendor(sender, instance, created, **kwargs): if created: entity = EntityModel.objects.filter(name=instance.dealer.name).first() entity.create_vendor( vendor_model_kwargs={ "vendor_name": instance.name, "vendor_number": instance.crn, "address_1": instance.address, "phone": instance.phone_number, "tax_id_number": instance.vrn, "active": True, "hidden": False, "additional_info": { "arabic_name": instance.arabic_name, "contact_person": instance.contact_person, }, } ) print(f"VendorModel created for Vendor: {instance.name}") @receiver(post_save, sender=models.Customer) def create_customer(sender, instance, created, **kwargs): if created: dealer = instance.dealer entity = dealer.entity name = f"{instance.first_name} {instance.middle_name} {instance.last_name}" if entity: entity.create_customer( customer_model_kwargs={ "customer_name": name, "address_1": instance.address, "phone": instance.phone_number, "email": instance.email, "sales_tax_rate": 0.15, "active": True, "hidden": False, "additional_info": {}, } ) print(f"Customer created: {name}") # Create Item @receiver(post_save, sender=models.Car) def create_item_model(sender, instance, created, **kwargs): name = instance.dealer.name entity = EntityModel.objects.filter(name=name).first() if created: coa = entity.get_default_coa() uom = entity.get_uom_all().get(name="Unit") if not entity.get_items_all().filter(name=instance.vin).first(): entity.create_item_product( name=f"{instance.vin}", item_type=ItemModel.ITEM_TYPE_MATERIAL, uom_model=uom, coa_model=coa, ) entity.create_item_inventory( name=f"{instance.vin}", item_type=ItemModel.ITEM_TYPE_MATERIAL, uom_model=uom, coa_model=coa, ) # # update price - CarFinance @receiver(post_save, sender=models.CarFinance) def update_item_model_cost(sender, instance, created, **kwargs): ItemModel.objects.filter(item_id=instance.car.vin).update( inventory_received_value=instance.cost_price, default_amount=instance.cost_price, ) print(f"Inventory item updated with CarFinance data for Car: {instance.car}") # @receiver(pre_save, sender=models.SaleQuotation) # def update_quotation_status(sender, instance, **kwargs): # if instance.valid_until and timezone.now() > instance.valid_until: # instance.status = 'expired' # # instance.total_price = instance.calculate_total_price() # # # @receiver(post_save, sender=models.Payment) # def update_status_on_payment(sender, instance, created, **kwargs): # if created: # quotation = instance.sale_quotation # total_payments = sum(payment.amount for payment in quotation.payments.all()) # if total_payments >= quotation.amount: # quotation.status = 'completed' # # SalesInvoice.objects.create(sales_order=order) # elif total_payments > 0: # quotation.status = 'partially_paid' # else: # quotation.status = 'pending' # quotation.save() @receiver(post_save, sender=models.Opportunity) def notify_staff_on_deal_stage_change(sender, instance, **kwargs): if instance.pk: previous = models.Opportunity.objects.get(pk=instance.pk) if previous.stage != instance.deal_status: message = f"Deal '{instance.deal_name}' status changed from {previous.stage} to {instance.stage}." models.Notification.objects.create( staff=instance.created_by, message=message ) # @receiver(post_save, sender=models.Opportunity) # def log_opportunity_creation(sender, instance, created, **kwargs): # if created: # models.OpportunityLog.objects.create( # opportunity=instance, # action="create", # user=instance.created_by, # details=f"Opportunity '{instance.deal_name}' was created.", # ) # @receiver(pre_save, sender=models.Opportunity) # def log_opportunity_update(sender, instance, **kwargs): # if instance.pk: # previous = models.Opportunity.objects.get(pk=instance.pk) # if previous.stage != instance.deal_status: # models.OpportunityLog.objects.create( # opportunity=instance, # action="status_change", # user=instance.created_by, # old_status=previous.deal_status, # new_status=instance.deal_status, # details=f"Status changed from {previous.deal_status} to {instance.deal_status}.", # ) # else: # models.OpportunityLog.objects.create( # opportunity=instance, # action="update", # user=instance.created_by, # details=f"Opportunity '{instance.deal_name}' was updated.", # ) @receiver(post_save, sender=models.AdditionalServices) def create_item_service(sender, instance, created, **kwargs): if created: entity = instance.dealer.entity uom = entity.get_uom_all().get(unit_abbr=instance.uom) cogs = entity.get_all_accounts().get(role=roles.COGS) # price = (float(instance.price) * float(vat.rate)) + float(instance.price) if instance.taxable else instance.price service_model = ItemModel.objects.create( name=instance.name, uom=uom, default_amount=instance.price, entity=entity, is_product_or_service=True, sold_as_unit=True, is_active=True, item_role="service", for_inventory=False, cogs_account=cogs, ) instance.item = service_model instance.save()