diff --git a/.DS_Store b/.DS_Store index b825cb4f..b188126a 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/db.sqlite b/db.sqlite index 0c1eff1c..2bb076b4 100644 Binary files a/db.sqlite and b/db.sqlite differ diff --git a/inventory/__pycache__/admin.cpython-311.pyc b/inventory/__pycache__/admin.cpython-311.pyc index 3f09b98a..58184d08 100644 Binary files a/inventory/__pycache__/admin.cpython-311.pyc and b/inventory/__pycache__/admin.cpython-311.pyc differ diff --git a/inventory/__pycache__/forms.cpython-311.pyc b/inventory/__pycache__/forms.cpython-311.pyc index 5cdcaabd..c2062cd9 100644 Binary files a/inventory/__pycache__/forms.cpython-311.pyc and b/inventory/__pycache__/forms.cpython-311.pyc differ diff --git a/inventory/__pycache__/models.cpython-311.pyc b/inventory/__pycache__/models.cpython-311.pyc index e0c43dc2..2801f796 100644 Binary files a/inventory/__pycache__/models.cpython-311.pyc and b/inventory/__pycache__/models.cpython-311.pyc differ diff --git a/inventory/__pycache__/urls.cpython-311.pyc b/inventory/__pycache__/urls.cpython-311.pyc index cf9231e3..c34c8ed6 100644 Binary files a/inventory/__pycache__/urls.cpython-311.pyc and b/inventory/__pycache__/urls.cpython-311.pyc differ diff --git a/inventory/__pycache__/views.cpython-311.pyc b/inventory/__pycache__/views.cpython-311.pyc index 944c9747..df5ea774 100644 Binary files a/inventory/__pycache__/views.cpython-311.pyc and b/inventory/__pycache__/views.cpython-311.pyc differ diff --git a/inventory/admin.py b/inventory/admin.py index 3e6f7337..4e52c6bd 100644 --- a/inventory/admin.py +++ b/inventory/admin.py @@ -3,6 +3,7 @@ from . import models admin.site.register(models.Dealer) +admin.site.register(models.Staff) admin.site.register(models.Vendor) admin.site.register(models.Customer) admin.site.register(models.SaleQuotation) diff --git a/inventory/forms.py b/inventory/forms.py index f62676f7..1fee52b7 100644 --- a/inventory/forms.py +++ b/inventory/forms.py @@ -21,7 +21,8 @@ from .models import ( Representative, Payment, SaleQuotationCar, - AdditionalServices + AdditionalServices, + Staff ) from django_ledger.models import ItemModel @@ -41,10 +42,10 @@ class PaymentForm(forms.ModelForm): model = Payment fields = ['amount','payment_method', 'reference_number'] -class UserForm(forms.ModelForm): - class Meta: - model = Dealer - fields = ['name', 'arabic_name', 'phone_number', 'address','dealer_type'] +# class UserForm(forms.ModelForm): +# class Meta: +# model = Staff +# fields = ['name', 'arabic_name', 'phone_number', 'address','staff_type'] # Dealer Form class DealerForm(forms.ModelForm): @@ -395,8 +396,10 @@ class WizardForm3(forms.Form): password = cleaned_data.get("password") confirm_password = cleaned_data.get("confirm_password") - if password and confirm_password and password != confirm_password: + if password != confirm_password: raise forms.ValidationError("Passwords do not match.") + else: + return cleaned_data class ItemForm(forms.Form): diff --git a/inventory/migrations/0008_alter_dealer_options_remove_dealer_dealer_type_and_more.py b/inventory/migrations/0008_alter_dealer_options_remove_dealer_dealer_type_and_more.py new file mode 100644 index 00000000..ce4e5e58 --- /dev/null +++ b/inventory/migrations/0008_alter_dealer_options_remove_dealer_dealer_type_and_more.py @@ -0,0 +1,55 @@ +# Generated by Django 5.1.4 on 2024-12-29 15:46 + +import django.db.models.deletion +import inventory.mixins +import phonenumber_field.modelfields +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('inventory', '0007_vendor_created_at'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.AlterModelOptions( + name='dealer', + options={'verbose_name': 'Dealer', 'verbose_name_plural': 'Dealers'}, + ), + migrations.RemoveField( + model_name='dealer', + name='dealer_type', + ), + migrations.RemoveField( + model_name='dealer', + name='parent_dealer', + ), + migrations.AddField( + model_name='dealer', + name='updated_at', + field=models.DateTimeField(auto_now=True, verbose_name='Updated At'), + ), + migrations.CreateModel( + name='Staff', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255, verbose_name='Name')), + ('arabic_name', models.CharField(max_length=255, verbose_name='Arabic Name')), + ('phone_number', phonenumber_field.modelfields.PhoneNumberField(max_length=128, region='SA', verbose_name='Phone Number')), + ('staff_type', models.CharField(choices=[('manager', 'Manager'), ('inventory', 'Inventory'), ('accountant', 'Accountant'), ('sales', 'Sales'), ('receptionist', 'Receptionist'), ('technician', 'Technician'), ('driver', 'Driver')], max_length=255, verbose_name='Staff Type')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), + ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated At')), + ('dealer', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='inventory.dealer')), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='staff', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'Staff', + 'verbose_name_plural': 'Staff', + 'permissions': [], + }, + bases=(models.Model, inventory.mixins.LocalizedNameMixin), + ), + ] diff --git a/inventory/models.py b/inventory/models.py index 8025b71b..1cd9aa44 100644 --- a/inventory/models.py +++ b/inventory/models.py @@ -33,7 +33,7 @@ from django_ledger.models import EntityModel class DealerUserManager(UserManager): def create_user_with_dealer(self, email, password, dealer_name, arabic_name, crn, vrn, address, **extra_fields): user = self.create_user(email=email, password=password, **extra_fields) - Dealer.objects.create(user=user, name=dealer_name, ) + Dealer.objects.create(user=user, name=dealer_name,arabic_name=arabic_name, crn=crn, vrn=vrn, address=address, **extra_fields) return user @@ -533,16 +533,17 @@ class Dealer(models.Model, LocalizedNameMixin): verbose_name=_("Logo")) entity = models.ForeignKey(EntityModel, on_delete=models.SET_NULL, null=True, blank=True) joined_at = models.DateTimeField(auto_now_add=True, verbose_name=_("Joined At")) - parent_dealer = models.ForeignKey( "self", - on_delete=models.SET_NULL, - blank=True, - null=True, - verbose_name=_("Parent Dealer"), - related_name="sub_dealers",) - dealer_type = models.CharField(max_length=255, - choices=DEALER_TYPES.choices, - verbose_name=_("Dealer Type"), - default=DEALER_TYPES.OWNER,) + updated_at = models.DateTimeField(auto_now=True, verbose_name=_("Updated At")) + # parent_dealer = models.ForeignKey( "self", + # on_delete=models.SET_NULL, + # blank=True, + # null=True, + # verbose_name=_("Parent Dealer"), + # related_name="sub_dealers",) + # dealer_type = models.CharField(max_length=255, + # choices=DEALER_TYPES.choices, + # verbose_name=_("Dealer Type"), + # default=DEALER_TYPES.OWNER,) objects = DealerUserManager() @property @@ -567,25 +568,25 @@ class Dealer(models.Model, LocalizedNameMixin): class Meta: verbose_name = _("Dealer") verbose_name_plural = _("Dealers") - permissions = [ - ('change_dealer_type', 'Can change dealer type'), - ] + # permissions = [ + # ('change_dealer_type', 'Can change dealer type'), + # ] def __str__(self): return self.name - @property - def get_sub_dealers(self): - if self.dealer_type == "OWNER": - return self.sub_dealers.all() - return None - - @property - def is_parent(self): - return self.dealer_type == "OWNER" - @property - def get_root_dealer(self): - return self.parent_dealer if self.parent_dealer else self + # @property + # def get_sub_dealers(self): + # if self.dealer_type == "OWNER": + # return self.sub_dealers.all() + # return None + # + # @property + # def is_parent(self): + # return self.dealer_type == "OWNER" + # @property + # def get_root_dealer(self): + # return self.parent_dealer if self.parent_dealer else self # @receiver(post_save, sender=User) # def create_dealer(instance, created, *args, **kwargs): @@ -593,30 +594,30 @@ class Dealer(models.Model, LocalizedNameMixin): # Dealer.objects.create(user=instance) -# class STAFF_TYPES(models.TextChoices): -# # Owner = "Owner", _("Owner") -# MANAGER = "manager", _("Manager") -# INVENTORY = "inventory", _("Inventory") -# ACCOUNTANT = "accountant", _("Accountant") -# SALES = "sales", _("Sales") -# RECEPTIONIST = "receptionist", _("Receptionist") -# TECHNICIAN = "technician", _("Technician") -# DRIVER = "driver", _("Driver") -# -# -# class Staff(models.Model, LocalizedNameMixin): -# user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="staff") -# dealer = models.ForeignKey(Dealer, on_delete=models.SET_NULL, null=True, blank=True) -# name = models.CharField(max_length=255, verbose_name=_("Name")) -# arabic_name = models.CharField(max_length=255, verbose_name=_("Arabic Name")) -# staff_type = models.CharField(choices=STAFF_TYPES.choices, max_length=255, verbose_name=_("Staff Type")) -# created_at = models.DateTimeField(auto_now_add=True, verbose_name=_("Created At")) -# updated_at = models.DateTimeField(auto_now=True, verbose_name=_("Updated At")) -# -# class Meta: -# verbose_name = _("Staff") -# verbose_name_plural = _("Staff") -# permissions = [] +class STAFF_TYPES(models.TextChoices): + MANAGER = "manager", _("Manager") + INVENTORY = "inventory", _("Inventory") + ACCOUNTANT = "accountant", _("Accountant") + SALES = "sales", _("Sales") + RECEPTIONIST = "receptionist", _("Receptionist") + TECHNICIAN = "technician", _("Technician") + DRIVER = "driver", _("Driver") + + +class Staff(models.Model, LocalizedNameMixin): + user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="staff") + dealer = models.ForeignKey(Dealer, on_delete=models.SET_NULL, null=True, blank=True) + name = models.CharField(max_length=255, verbose_name=_("Name")) + arabic_name = models.CharField(max_length=255, verbose_name=_("Arabic Name")) + phone_number = PhoneNumberField(region="SA", verbose_name=_("Phone Number")) + staff_type = models.CharField(choices=STAFF_TYPES.choices, max_length=255, verbose_name=_("Staff Type")) + created_at = models.DateTimeField(auto_now_add=True, verbose_name=_("Created At")) + updated_at = models.DateTimeField(auto_now=True, verbose_name=_("Updated At")) + + class Meta: + verbose_name = _("Staff") + verbose_name_plural = _("Staff") + permissions = [] # Vendor Model diff --git a/inventory/signals.py b/inventory/signals.py index 38559ba6..95b760aa 100644 --- a/inventory/signals.py +++ b/inventory/signals.py @@ -3,7 +3,7 @@ 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 +from django_ledger.models import EntityModel,AccountModel,ItemModel,ItemModelAbstract,UnitOfMeasureModel, VendorModel from . import models User = get_user_model() @@ -49,13 +49,13 @@ def create_car_location(sender, instance, created, **kwargs): """ try: if created: - if instance.dealer is None: + if instance.user.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, + owner=instance.user.dealer, + showroom=instance.user.dealer, description=f"Initial location set for car {instance.vin}." ) print("Car Location created") @@ -83,105 +83,103 @@ def update_car_status_on_reservation_delete(sender, instance, **kwargs): @receiver(post_save, sender=models.Dealer) def create_ledger_entity(sender, instance, created, **kwargs): if created: - root_dealer = instance.get_root_dealer - if not root_dealer.entity: - entity_name = f"{root_dealer.name}-{root_dealer.joined_at.date()}" - entity = EntityModel.create_entity( - name=entity_name, - admin=root_dealer.user, - use_accrual_method=False, - fy_start_month=1, + 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 Cash Account + entity.create_account( + coa_model=coa, + code="1010", + role=roles.ASSET_CA_CASH, + name=_("Cash"), + balance_type="debit", + active=True, ) - 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 Accounts Receivable Account + entity.create_account( + coa_model=coa, + code="1020", + role=roles.ASSET_CA_RECEIVABLES, + name=_("Accounts Receivable"), + balance_type="debit", + active=True, + ) - # Create Cash Account - entity.create_account( - coa_model=coa, - code="1010", - role=roles.ASSET_CA_CASH, - name=_("Cash"), - balance_type="debit", - active=True, - ) + # Create Inventory Account + entity.create_account( + coa_model=coa, + code="1030", + role=roles.ASSET_CA_INVENTORY, + name=_("Inventory"), + balance_type="debit", + active=True, + ) - # Create Accounts Receivable Account - entity.create_account( - coa_model=coa, - code="1020", - role=roles.ASSET_CA_RECEIVABLES, - name=_("Accounts Receivable"), - balance_type="debit", - active=True, - ) - - # Create Inventory Account - entity.create_account( - coa_model=coa, - code="1030", - role=roles.ASSET_CA_INVENTORY, - name=_("Inventory"), - balance_type="debit", - active=True, - ) + # Create Accounts Payable Account + entity.create_account( + coa_model=coa, + code="2010", + role=roles.LIABILITY_CL_ACC_PAYABLE, + name=_("Accounts Payable"), + balance_type="credit", + active=True, + ) - # Create Accounts Payable Account - entity.create_account( - coa_model=coa, - code="2010", - role=roles.LIABILITY_CL_ACC_PAYABLE, - name=_("Accounts Payable"), - balance_type="credit", - active=True, - ) + # Create Sales Revenue Account + entity.create_account( + coa_model=coa, + code="4010", + role=roles.INCOME_OPERATIONAL, + name=_("Sales Revenue"), + balance_type="credit", + active=True, + ) - # Create Sales Revenue Account - entity.create_account( - coa_model=coa, - code="4010", - role=roles.INCOME_OPERATIONAL, - name=_("Sales Revenue"), - balance_type="credit", - active=True, - ) + # Create Cost of Goods Sold Account + entity.create_account( + coa_model=coa, + code="5010", + role=roles.COGS, + name=_("Cost of Goods Sold"), + balance_type="debit", + active=True, + ) - # Create Cost of Goods Sold Account - entity.create_account( - coa_model=coa, - code="5010", - role=roles.COGS, - name=_("Cost of Goods Sold"), - balance_type="debit", - active=True, - ) + # Create Rent Expense Account + entity.create_account( + coa_model=coa, + code="6010", + role=roles.EXPENSE_OPERATIONAL, + name=_("Rent Expense"), + balance_type="debit", + active=True, + ) - # Create Rent Expense Account - entity.create_account( - coa_model=coa, - code="6010", - role=roles.EXPENSE_OPERATIONAL, - name=_("Rent Expense"), - balance_type="debit", - active=True, - ) - - # 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 Utilities Expense Account + entity.create_account( + coa_model=coa, + code="6020", + role=roles.EXPENSE_OPERATIONAL, + name=_("Utilities Expense"), + balance_type="debit", + active=True, + ) # Create Vendor @@ -191,8 +189,9 @@ def create_ledger_vendor(sender, instance, created, **kwargs): if created: entity = EntityModel.objects.filter(name=instance.dealer.name).first() - entity.create_vendor( - name=instance.name, + VendorModel.objects.create( + entity_model=entity, + vendor_name=instance.name, vendor_number=instance.crn, address_1=instance.address, phone=instance.phone_number, @@ -202,7 +201,8 @@ def create_ledger_vendor(sender, instance, created, **kwargs): additional_info={ "arabic_name": instance.arabic_name, "contact_person": instance.contact_person, - }) + } + ) print(f"VendorModel created for Vendor: {instance.name}") @@ -211,7 +211,7 @@ def create_ledger_vendor(sender, instance, created, **kwargs): @receiver(post_save, sender=models.Customer) def create_customer(sender, instance, created, **kwargs): if created: - dealer = instance.dealer.get_root_dealer + dealer = instance.dealer entity = dealer.entity name = f"{instance.first_name} {instance.middle_name} {instance.last_name}" if entity: @@ -241,14 +241,8 @@ def create_item_model(sender, instance, created, **kwargs): if not entity: return - uom_name = _("Car") - unit_abbr = _("C") - uom = entity.get_uom_all().filter(name=uom_name, unit_abbr=unit_abbr).first() - if not uom: - uom = entity.create_uom( - name=uom_name, - unit_abbr=unit_abbr - ) + + uom = entity.get_uom_all() entity.create_item_product( name=item_name, diff --git a/inventory/urls.py b/inventory/urls.py index c0c3bead..75132c61 100644 --- a/inventory/urls.py +++ b/inventory/urls.py @@ -87,11 +87,11 @@ urlpatterns = [ path('sales/quotations//payment/', views.payment_create, name='payment_create'), # Users URLs - path('user/create/', views.UserCreateView.as_view(), name='user_create'), - path('user//update/', views.UserUpdateView.as_view(), name='user_update'), - path('user//', views.UserDetailView.as_view(), name='user_detail'), - path('user/', views.UserListView.as_view(), name='user_list'), - path('user//confirm/', views.UserDeleteview, name='user_delete'), + # path('user/create/', views.UserCreateView.as_view(), name='user_create'), + # path('user//update/', views.UserUpdateView.as_view(), name='user_update'), + # path('user//', views.UserDetailView.as_view(), name='user_detail'), + # path('user/', views.UserListView.as_view(), name='user_list'), + # path('user//confirm/', views.UserDeleteview, name='user_delete'), # Organization URLs path('organizations/', views.OrganizationListView.as_view(), name='organization_list'), path('organizations//', views.OrganizationDetailView.as_view(), name='organization_detail'), diff --git a/inventory/views.py b/inventory/views.py index f988f2be..d3c6619b 100644 --- a/inventory/views.py +++ b/inventory/views.py @@ -1,3 +1,4 @@ +from django.views.decorators.csrf import csrf_exempt from django_ledger.models import EntityModel, InvoiceModel,BankAccountModel,AccountModel,JournalEntryModel,TransactionModel,EstimateModel,CustomerModel from django_ledger.forms.bank_account import BankAccountCreateForm,BankAccountUpdateForm @@ -46,6 +47,7 @@ from django.contrib.messages.views import SuccessMessageMixin from django.contrib.auth.models import Group from .utils import get_calculations from django.contrib.auth.models import User +from allauth.account import views logger = logging.getLogger(__name__) logging.basicConfig(level=logging.INFO) @@ -93,15 +95,16 @@ def dealer_signup(request, *args, **kwargs): wf1 = data.get("wizardValidationForm1") wf2 = data.get("wizardValidationForm2") wf3 = data.get("wizardValidationForm3") - name = wf1.get("name") - arabic_name = wf1.get("arabic_name") email = wf1.get("email") + password = wf1.get("password") + password_confirm = wf1.get("confirm_password") + name = wf2.get("name") + arabic_name = wf2.get("arabic_name") phone = wf2.get("phone_number") - crn = wf2.get("crn") - vrn = wf2.get("vrn") - address = wf2.get("address") - password = wf3.get("password") - password_confirm = wf3.get("confirm_password") + crn = wf3.get("crn") + vrn = wf3.get("vrn") + address = wf3.get("address") + if password != password_confirm: return JsonResponse({"error": "Passwords do not match."}, status=400) @@ -109,16 +112,14 @@ def dealer_signup(request, *args, **kwargs): try: with transaction.atomic(): user = User.objects.create(email=email, password=password) - user.set_password(password) - user.save() + models.Dealer.objects.create(user=user, name=name, arabic_name=arabic_name, crn=crn, vrn=vrn, phone_number=phone, - address=address, - dealer_type="OWNER",) + address=address,) return JsonResponse({"message": "User created successfully."}, status=200) except Exception as e: return JsonResponse({"error": str(e)}, status=400) @@ -143,8 +144,8 @@ class AccountingDashboard(LoginRequiredMixin, TemplateView): def dispatch(self, request, *args, **kwargs): if ( - not any(hasattr(request.user, attr) for attr in ["dealer", "subdealer"]) - or not request.user.is_authenticated + # not any(hasattr(request.user, attr) for attr in ["dealer", "subdealer"]) + not request.user.is_authenticated ): # messages.error(request, _("You are not associated with any dealer.")) return redirect("welcome") @@ -192,7 +193,7 @@ class CarCreateView(LoginRequiredMixin, CreateView): return reverse("inventory_stats") def form_valid(self, form): - form.instance.dealer = self.request.user.dealer.get_root_dealer + form.instance.dealer = self.request.user.dealer form.save() messages.success(self.request, "Car saved successfully.") return super().form_valid(form) @@ -347,7 +348,7 @@ class CarInventory(LoginRequiredMixin, ListView): trim_id = self.kwargs['trim_id'] cars = models.Car.objects.filter( - dealer=self.request.user.dealer.get_root_dealer, + dealer=self.request.user.dealer, id_car_make=make_id, id_car_model=model_id, id_car_trim=trim_id, @@ -391,7 +392,7 @@ def inventory_stats_view(request): # Annotate total cars by make, model, and trim cars = ( - models.Car.objects.filter(dealer=dealer.get_root_dealer) + models.Car.objects.filter(dealer=dealer) .select_related("id_car_make", "id_car_model", "id_car_trim") .annotate( make_total=Count("id_car_make"), @@ -636,17 +637,17 @@ class DealerUpdateView(LoginRequiredMixin, SuccessMessageMixin, UpdateView): def get_success_url(self): return reverse("dealer_detail", kwargs={"pk": self.object.pk}) - def get_form(self, form_class=None): - form = super().get_form(form_class) - if hasattr(form.fields, "dealer_type"): - form.fields.pop("dealer_type") - return form - - def get_form_class(self): - if self.request.user.dealer.dealer_type == "OWNER": - return forms.DealerForm - else: - return forms.UserForm + # def get_form(self, form_class=None): + # form = super().get_form(form_class) + # if hasattr(form.fields, "dealer_type"): + # form.fields.pop("dealer_type") + # return form + # + # def get_form_class(self): + # if self.request.user.dealer.dealer_type == "OWNER": + # return forms.DealerForm + # else: + # return forms.UserForm class CustomerListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): @@ -660,7 +661,7 @@ class CustomerListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): def get_queryset(self): query = self.request.GET.get("q") customers = models.Customer.objects.filter( - dealer=self.request.user.dealer.get_root_dealer + dealer=self.request.user.dealer ) if query: @@ -697,6 +698,10 @@ class CustomerCreateView( permission_required = ("inventory.add_customer",) success_message = _("Customer created successfully.") + def form_valid(self, form): + form.instance.dealer = self.request.user.dealer + return super().form_valid(form) + class CustomerUpdateView( @@ -784,7 +789,7 @@ class QuotationCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateVie permission_required = ("inventory.add_salequotation",) def form_valid(self, form): - dealer = self.request.user.dealer.get_root_dealer + dealer = self.request.user.dealer form.instance.dealer = dealer quotation = form.save() selected_cars = form.cleaned_data.get("cars") @@ -809,7 +814,7 @@ class QuotationListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): def get_queryset(self): status = self.request.GET.get("status") - queryset = self.request.user.dealer.get_root_dealer.sales.all() + queryset = self.request.user.dealer.sales.all() if status: queryset = queryset.filter(status=status) return queryset @@ -834,7 +839,7 @@ class QuotationDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailVie @login_required def generate_invoice(request, pk): quotation = get_object_or_404(models.SaleQuotation, pk=pk) - dealer = request.user.dealer.get_root_dealer + dealer = request.user.dealer entity = dealer.entity if not quotation.is_approved: messages.error( @@ -981,7 +986,7 @@ def generate_invoice(request, pk): @login_required def post_quotation(request, pk): qoutation = get_object_or_404(models.SaleQuotation, pk=pk) - dealer = request.user.dealer.get_root_dealer + dealer = request.user.dealer entity = dealer.entity if qoutation.posted: messages.error(request, "Quotation is already posted") @@ -1037,7 +1042,7 @@ def post_quotation(request, pk): def mark_quotation(request, pk): qoutation = get_object_or_404(models.SaleQuotation, pk=pk) status = request.GET.get("status") - dealer = request.user.dealer.get_root_dealer + dealer = request.user.dealer entity = dealer.entity date = datetime.datetime.now() customer = entity.get_customers().filter(customer_name=qoutation.customer.get_full_name).first() @@ -1052,7 +1057,7 @@ def mark_quotation(request, pk): messages.error(request, "Quotation is not ready for approval") return redirect("quotation_detail", pk=pk) - invoice_model.mark_as_approved(entity_slug=entity.slug, user_model=request.user.dealer.get_root_dealer.user) + invoice_model.mark_as_approved(entity_slug=entity.slug, user_model=request.user.dealer) invoice_model.date_approved = date qoutation.date_approved = date invoice_model.save() @@ -1072,7 +1077,7 @@ def mark_quotation(request, pk): messages.error(request, "Quotation is not ready for payment") return redirect("quotation_detail", pk=pk) - invoice_model.mark_as_paid(entity_slug=entity.slug, user_model=request.user.dealer.get_root_dealer.user) + invoice_model.mark_as_paid(entity_slug=entity.slug, user_model=request.user.dealer) invoice_model.date_paid = date qoutation.date_paid = date invoice_model.save() @@ -1117,115 +1122,115 @@ class SalesOrderDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailVi # Users -class UserListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): - model = models.Dealer - context_object_name = "users" - paginate_by = 10 - template_name = "users/user_list.html" - permission_required = ("inventory.view_dealer",) - - def get_queryset(self): - query = self.request.GET.get("q") - users = self.request.user.dealer.sub_dealers - - if query: - users = users.filter( - Q(name__icontains=query) - | Q(arabic_name__icontains=query) - | Q(phone_number__icontains=query) - | Q(address__icontains=query) - ) - return users.all() +# class UserListView(LoginRequiredMixin, PermissionRequiredMixin, ListView): +# model = models.Staff +# context_object_name = "users" +# paginate_by = 10 +# template_name = "users/user_list.html" +# permission_required = ("inventory.view_dealer",) +# +# def get_queryset(self): +# query = self.request.GET.get("q") +# users = self.request.user.dealer.staff.all() +# +# if query: +# users = users.filter( +# Q(name__icontains=query) +# | Q(arabic_name__icontains=query) +# | Q(phone_number__icontains=query) +# | Q(address__icontains=query) +# ) +# return users.all() +# +# +# class UserDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView): +# model = models.Staff +# template_name = "users/user_detail.html" +# context_object_name = "user_" +# permission_required = ("inventory.view_dealer",) -class UserDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView): - model = models.Dealer - template_name = "users/user_detail.html" - context_object_name = "user_" - permission_required = ("inventory.view_dealer",) +# class UserCreateView( +# LoginRequiredMixin, +# PermissionRequiredMixin, +# SuccessMessageMixin, +# CreateView, +# ): +# model = models.Staff +# form_class = forms.UserForm +# template_name = "users/user_form.html" +# success_url = reverse_lazy("user_list") +# permission_required = ("inventory.add_dealer",) +# success_message = _("User created successfully.") +# +# def get_form(self, form_class=None): +# form = super().get_form(form_class) +# form.fields["staff_type"].choices = [ +# t for t in form.fields["staff_type"].choices if t[0] != "OWNER" +# ] +# return form +# +# def form_valid(self, form): +# dealer = self.request.user.dealer +# if dealer.sub_dealers.count() >= dealer.get_active_plan.max_users: +# messages.error( +# self.request, _("You have reached the maximum number of users.") +# ) +# return redirect("user_list") +# +# user = User.objects.create_user(username=form.cleaned_data["name"]) +# user.set_password("Tenhal@123") +# user.save() +# form.instance.user = user +# form.instance.parent_dealer = dealer +# for group in user.groups.all(): +# group.user_set.remove(user) +# Group.objects.get(name=form.cleaned_data["dealer_type"].lower()).user_set.add( +# user +# ) +# form.save() +# return super().form_valid(form) -class UserCreateView( - LoginRequiredMixin, - PermissionRequiredMixin, - SuccessMessageMixin, - CreateView, -): - model = models.Dealer - form_class = forms.UserForm - template_name = "users/user_form.html" - success_url = reverse_lazy("user_list") - permission_required = ("inventory.add_dealer",) - success_message = _("User created successfully.") - - def get_form(self, form_class=None): - form = super().get_form(form_class) - form.fields["dealer_type"].choices = [ - t for t in form.fields["dealer_type"].choices if t[0] != "OWNER" - ] - return form - - def form_valid(self, form): - dealer = self.request.user.dealer.get_root_dealer - if dealer.sub_dealers.count() >= dealer.get_active_plan.max_users: - messages.error( - self.request, _("You have reached the maximum number of users.") - ) - return redirect("user_list") - - user = User.objects.create_user(username=form.cleaned_data["name"]) - user.set_password("Tenhal@123") - user.save() - form.instance.user = user - form.instance.parent_dealer = dealer - for group in user.groups.all(): - group.user_set.remove(user) - Group.objects.get(name=form.cleaned_data["dealer_type"].lower()).user_set.add( - user - ) - form.save() - return super().form_valid(form) +# class UserUpdateView( +# LoginRequiredMixin, +# PermissionRequiredMixin, +# SuccessMessageMixin, +# UpdateView, +# ): +# model = models.Dealer +# form_class = forms.UserForm +# template_name = "users/user_form.html" +# success_url = reverse_lazy("user_list") +# permission_required = ("inventory.change_dealer",) +# success_message = _("User updated successfully.") +# +# def get_form(self, form_class=None): +# form = super().get_form(form_class) +# if not self.request.user.has_perms(["inventory.change_dealer_type"]): +# field = form.fields["dealer_type"] +# field.widget = field.hidden_widget() +# form.fields["dealer_type"].choices = [ +# t for t in form.fields["dealer_type"].choices if t[0] != "Owner" +# ] +# return form +# +# def form_valid(self, form): +# user = form.instance.user +# for group in user.groups.all(): +# group.user_set.remove(user) +# Group.objects.get(name=form.cleaned_data["dealer_type"].lower()).user_set.add( +# user +# ) +# form.save() +# return super().form_valid(form) -class UserUpdateView( - LoginRequiredMixin, - PermissionRequiredMixin, - SuccessMessageMixin, - UpdateView, -): - model = models.Dealer - form_class = forms.UserForm - template_name = "users/user_form.html" - success_url = reverse_lazy("user_list") - permission_required = ("inventory.change_dealer",) - success_message = _("User updated successfully.") - - def get_form(self, form_class=None): - form = super().get_form(form_class) - if not self.request.user.has_perms(["inventory.change_dealer_type"]): - field = form.fields["dealer_type"] - field.widget = field.hidden_widget() - form.fields["dealer_type"].choices = [ - t for t in form.fields["dealer_type"].choices if t[0] != "Owner" - ] - return form - - def form_valid(self, form): - user = form.instance.user - for group in user.groups.all(): - group.user_set.remove(user) - Group.objects.get(name=form.cleaned_data["dealer_type"].lower()).user_set.add( - user - ) - form.save() - return super().form_valid(form) - - -def UserDeleteview(request, pk): - user = get_object_or_404(models.Dealer, pk=pk) - user.delete() - messages.success(request, _("User deleted successfully.")) - return redirect("user_list") +# def UserDeleteview(request, pk): +# user = get_object_or_404(models.Dealer, pk=pk) +# user.delete() +# messages.success(request, _("User deleted successfully.")) +# return redirect("user_list") # errors @@ -1266,7 +1271,7 @@ class OrganizationCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView def form_valid(self, form): if form.is_valid(): - form.instance.dealer = self.request.user.dealer.get_root_dealer + form.instance.dealer = self.request.user.dealer form.save() return super().form_valid(form) else: @@ -1309,7 +1314,7 @@ class RepresentativeCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateVi def form_valid(self, form): if form.is_valid(): - form.instance.dealer = self.request.user.dealer.get_root_dealer + form.instance.dealer = self.request.user.dealer form.save() return super().form_valid(form) else: @@ -1382,7 +1387,7 @@ def download_quotation_pdf(request, quotation_id): @login_required def invoice_detail(request,pk): quotation = get_object_or_404(models.SaleQuotation, pk=pk) - dealer = request.user.dealer.get_root_dealer + dealer = request.user.dealer entity = dealer.entity customer = entity.get_customers().filter(customer_name=quotation.customer.get_full_name).first() invoice_model = entity.get_invoices() @@ -1395,7 +1400,7 @@ def invoice_detail(request,pk): @login_required def payment_invoice(request,pk): quotation = get_object_or_404(models.SaleQuotation, pk=pk) - dealer = request.user.dealer.get_root_dealer + dealer = request.user.dealer entity = dealer.entity customer = entity.get_customers().filter(customer_name=quotation.customer.get_full_name).first() invoice_model = entity.get_invoices() @@ -1425,14 +1430,14 @@ def payment_invoice(request,pk): def payment_create(request, pk): quotation = get_object_or_404(models.SaleQuotation, pk=pk) - dealer = request.user.dealer.get_root_dealer + dealer = request.user.dealer if request.method == "POST": form = forms.PaymentForm(request.POST) if form.is_valid(): form.instance.quotation = quotation insatnce = form.save() - dealer = request.user.dealer.get_root_dealer + dealer = request.user.dealer entity = dealer.entity customer = entity.get_customers().filter(customer_name=quotation.customer.get_full_name).first() coa_qs, coa_map = entity.get_all_coa_accounts() @@ -1461,7 +1466,7 @@ def payment_create(request, pk): invoice_model = entity.get_invoices().filter(date_approved=quotation.date_approved).first() - invoice_model.mark_as_paid(entity_slug=entity.slug, user_model=request.user.dealer.get_root_dealer.user) + invoice_model.mark_as_paid(entity_slug=entity.slug, user_model=request.user.dealer) date = timezone.now() invoice_model.date_paid = date quotation.date_paid = date diff --git a/templates/.DS_Store b/templates/.DS_Store index 85faf9e3..de0efc82 100644 Binary files a/templates/.DS_Store and b/templates/.DS_Store differ diff --git a/templates/account/signup-wizard.html b/templates/account/signup-wizard.html index 4ea97776..d42a2faf 100644 --- a/templates/account/signup-wizard.html +++ b/templates/account/signup-wizard.html @@ -1,4 +1,4 @@ -{% extends "base.html" %} +{% extends "auth_base.html" %} {% load crispy_forms_filters %} {% load i18n static %} diff --git a/templates/auth_base.html b/templates/auth_base.html new file mode 100644 index 00000000..284d9b76 --- /dev/null +++ b/templates/auth_base.html @@ -0,0 +1,229 @@ +{% load static %} {% load i18n %} + +{% get_current_language as LANGUAGE_CODE %} + + + + + + + + + {% block title %}{% trans 'HAIKAL' %}{% endblock %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {% if LANGUAGE_CODE == 'en' %} + + + {% else %} + + + {% endif %} + + + + + {% include 'messages.html' %} +
+ +
+ +{% block content %} + +{% endblock %} + + +
+ + + +
+ + + + + {% block extra_js %}{% endblock extra_js %} + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file