clean base V1-update

This commit is contained in:
ismail 2025-04-28 14:40:08 +03:00
parent 8556078b59
commit 18dd7829d9
39 changed files with 1545 additions and 1412 deletions

157
.gitignore vendored
View File

@ -15,11 +15,12 @@ car*.json
car_inventory/settings.py car_inventory/settings.py
car_inventory/__pycache__ car_inventory/__pycache__
scripts/dsrpipe.py scripts/dsrpipe.py
# Backup files # def_venv
*.bak # Backup files #
*.bak
# If you are using PyCharm # # If you are using PyCharm #
# User-specific stuff # User-specific stuff
.idea/**/workspace.xml .idea/**/workspace.xml
.idea/**/tasks.xml .idea/**/tasks.xml
@ -55,95 +56,95 @@ out/
# JIRA plugin # JIRA plugin
atlassian-ide-plugin.xml atlassian-ide-plugin.xml
# Python # # Python #
*.py[cod] *.py[cod]
*$py.class *$py.class
# Distribution / packaging # Distribution / packaging
.Python build/ .Python build/
develop-eggs/ develop-eggs/
dist/ dist/
downloads/ downloads/
eggs/ eggs/
.eggs/ .eggs/
lib/ lib/
lib64/ lib64/
parts/ parts/
sdist/ sdist/
var/ var/
wheels/ wheels/
*.whl *.whl
*.egg-info/ *.egg-info/
.installed.cfg .installed.cfg
*.egg *.egg
*.manifest *.manifest
*.spec *.spec
inventory/management/commands/run.py inventory/management/commands/run.py
# Installer logs # Installer logs
pip-log.txt pip-log.txt
pip-delete-this-directory.txt pip-delete-this-directory.txt
# Unit test / coverage reports # Unit test / coverage reports
htmlcov/ htmlcov/
.tox/ .tox/
.coverage .coverage
.coverage.* .coverage.*
.cache .cache
.pytest_cache/ .pytest_cache/
nosetests.xml nosetests.xml
coverage.xml coverage.xml
*.cover *.cover
.hypothesis/ .hypothesis/
# Jupyter Notebook # Jupyter Notebook
.ipynb_checkpoints .ipynb_checkpoints
# pyenv # pyenv
.python-version .python-version
# celery # celery
celerybeat-schedule.* celerybeat-schedule.*
# SageMath parsed files # SageMath parsed files
*.sage.py *.sage.py
# Environments # Environments
.env .env
.venv .venv
env/ env/
venv/ venv/
ENV/ ENV/
env.bak/ env.bak/
venv.bak/ venv.bak/
# mkdocs documentation # mkdocs documentation
/site /site
# mypy # mypy
.mypy_cache/ .mypy_cache/
# Sublime Text # # Sublime Text #
*.tmlanguage.cache *.tmlanguage.cache
*.tmPreferences.cache *.tmPreferences.cache
*.stTheme.cache *.stTheme.cache
*.sublime-workspace *.sublime-workspace
*.sublime-project *.sublime-project
# sftp configuration file # sftp configuration file
sftp-config.json sftp-config.json
# Package control specific files Package # Package control specific files Package
Control.last-run Control.last-run
Control.ca-list Control.ca-list
Control.ca-bundle Control.ca-bundle
Control.system-ca-bundle Control.system-ca-bundle
GitHub.sublime-settings GitHub.sublime-settings
# Visual Studio Code # # Visual Studio Code #
.vscode/* .vscode/*
!.vscode/settings.json !.vscode/settings.json
!.vscode/tasks.json !.vscode/tasks.json
!.vscode/launch.json !.vscode/launch.json
!.vscode/extensions.json !.vscode/extensions.json
.history .history

View File

@ -4,18 +4,23 @@ FROM python:3.11.11-slim-bullseye
# Set the working directory to /app # Set the working directory to /app
WORKDIR /app WORKDIR /app
# Install the dependencies
RUN apt-get update && apt-get install -y libgl1
RUN apt-get update && apt-get install -y libglib2.0-dev
RUN apt-get update && apt-get install -y libzbar0
RUN apt-get update && apt-get install -y cmake build-essential xmlsec1 libxmlsec1-dev
RUN apt-get install pkg-config libxml2-dev libxmlsec1-dev libxmlsec1-openssl
COPY requirements_dev.txt .
RUN pip install --upgrade pip
RUN pip install -r requirements_dev.txt
# Create a new user and group # Create a new user and group
RUN groupadd -r appgroup RUN groupadd -r appgroup
RUN useradd -r -g appgroup -G appgroup -m -d /app -s /bin/false appuser RUN useradd -r -g appgroup -G appgroup -m -d /app -s /bin/false appuser
# Copy the requirements file # Copy the requirements file
COPY requirements.txt .
# Install the dependencies
RUN pip install -r requirements.txt
RUN apt-get update && apt-get install -y libgl1
RUN apt-get update && apt-get install -y libglib2.0-dev
RUN apt-get update && apt-get install -y libzbar0
# Copy the application code # Copy the application code
COPY . . COPY . .
@ -23,17 +28,12 @@ COPY . .
# Expose the port # Expose the port
EXPOSE 8000 EXPOSE 8000
# Copy the entrypoint script
COPY entrypoint.sh /app/entrypoint.sh
# Make the script executable # Make the script executable
RUN chmod +x /app/entrypoint.sh RUN chmod +x *.sh
# Change ownership of the app directory to the new user # Change ownership of the app directory to the new user
RUN chown -R appuser:appgroup /app RUN chown -R appuser:appgroup /app
RUN find /app -path "*/migrations/*.py" -not -name "__init__.py" -delete
RUN find /app -path "*/migrations/*.pyc" -delete
# Set the entrypoint to execute the script as the new user # Set the entrypoint to execute the script as the new user
ENTRYPOINT ["sh", "-c", "python3 manage.py makemigrations && python3 manage.py migrate && python3 manage.py collectstatic --no-input && python3 manage.py runserver 0.0.0.0:8000"] ENTRYPOINT ["sh", "-c", "python3 manage.py runserver 0.0.0.0:8000"]

View File

@ -11,7 +11,7 @@ from django.shortcuts import render
from inventory.utils import get_user_type from inventory.utils import get_user_type
from . import models, serializers from . import models, serializers
from .services import get_car_data, get_from_cardatabase from .services import get_car_data, get_from_cardatabase
from rest_framework.authtoken.models import Token # from rest_framework.authtoken.models import Token
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from inventory import models as inventory_models from inventory import models as inventory_models
@ -20,20 +20,20 @@ from inventory import models as inventory_models
class LoginView(APIView): class LoginView(APIView):
permission_classes = [permissions.AllowAny,] permission_classes = [permissions.AllowAny,]
def post(self, request, *args, **kwargs): # def post(self, request, *args, **kwargs):
username = request.data.get('username') # username = request.data.get('username')
password = request.data.get('password') # password = request.data.get('password')
if username is None or password is None: # if username is None or password is None:
return Response({'error': 'Please provide both username and password.'}, status=status.HTTP_400_BAD_REQUEST) # return Response({'error': 'Please provide both username and password.'}, status=status.HTTP_400_BAD_REQUEST)
user = authenticate(username=username, password=password) # user = authenticate(username=username, password=password)
if not user: # if not user:
return Response({'error': 'Invalid credentials.'}, status=status.HTTP_401_UNAUTHORIZED) # return Response({'error': 'Invalid credentials.'}, status=status.HTTP_401_UNAUTHORIZED)
token, created = Token.objects.get_or_create(user=user) # token, created = Token.objects.get_or_create(user=user)
return Response({'token': token.key, 'user_id': user.id, 'username': user.username}, status=status.HTTP_200_OK) # return Response({'token': token.key, 'user_id': user.id, 'username': user.username}, status=status.HTTP_200_OK)
class CarVINViewSet(APIView): class CarVINViewSet(APIView):

21
apply_initial_migrations.sh Executable file
View File

@ -0,0 +1,21 @@
#!/bin/sh
echo "Delete Old Migrations"
find ./inventory -type f -iname "000*.py" -delete
echo "Delete Old Cache"
find ./car_inventory -type d -iname "__pycache__"|xargs rm -rf
find ./inventory -type d -iname "__pycache__"|xargs rm -rf
echo "Apply Base Migrate"
python3 manage.py migrate
echo "Apply Make Migratinos"
python3 manage.py makemigrations
echo "Apply Final Migrate"
python3 manage.py migrate
echo "Collect Static"
python3 manage.py collectstatic --no-input
echo "Done"

View File

@ -4,16 +4,16 @@ from django.conf.urls.static import static
from django.conf import settings from django.conf import settings
from django.conf.urls.i18n import i18n_patterns from django.conf.urls.i18n import i18n_patterns
from inventory import views from inventory import views
import debug_toolbar # import debug_toolbar
from schema_graph.views import Schema # from schema_graph.views import Schema
# from two_factor.urls import urlpatterns as tf_urls # from two_factor.urls import urlpatterns as tf_urls
urlpatterns = [ urlpatterns = [
path('__debug__/', include(debug_toolbar.urls)), # path('__debug__/', include(debug_toolbar.urls)),
path('silk/', include('silk.urls', namespace='silk')), # path('silk/', include('silk.urls', namespace='silk')),
path('api-auth/', include('rest_framework.urls')), path('api-auth/', include('rest_framework.urls')),
path('api/', include('api.urls')), # path('api/', include('api.urls')),
path('dj-rest-auth/', include('dj_rest_auth.urls')), # path('dj-rest-auth/', include('dj_rest_auth.urls')),
] ]
@ -21,13 +21,13 @@ urlpatterns += i18n_patterns(
path('admin/', admin.site.urls), path('admin/', admin.site.urls),
path('switch_language/', views.switch_language, name='switch_language'), path('switch_language/', views.switch_language, name='switch_language'),
path('accounts/', include('allauth.urls')), path('accounts/', include('allauth.urls')),
path('prometheus/', include('django_prometheus.urls')), # path('prometheus/', include('django_prometheus.urls')),
path('', include('inventory.urls')), path('', include('inventory.urls')),
path('ledger/', include('django_ledger.urls', namespace='django_ledger')), path('ledger/', include('django_ledger.urls', namespace='django_ledger')),
path("haikalbot/", include("haikalbot.urls")), # path("haikalbot/", include("haikalbot.urls")),
path('appointment/', include('appointment.urls')), path('appointment/', include('appointment.urls')),
path('plans/', include('plans.urls')), path('plans/', include('plans.urls')),
path("schema/", Schema.as_view()), # path("schema/", Schema.as_view()),
# path('', include(tf_urls)), # path('', include(tf_urls)),
) )

View File

@ -5,7 +5,7 @@ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "car_inventory.settings")
django.setup() django.setup()
from inventory.models import * from inventory.models import *
from rich import print # from rich import print
import random import random
import datetime import datetime

View File

@ -1,23 +0,0 @@
# Generated by Django 4.2.20 on 2025-03-20 17:15
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='ChatLog',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('user_message', models.TextField()),
('chatbot_response', models.TextField()),
('timestamp', models.DateTimeField(auto_now_add=True)),
],
),
]

View File

@ -1,22 +0,0 @@
# Generated by Django 4.2.20 on 2025-03-20 17:15
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('inventory', '0001_initial'),
('haikalbot', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='chatlog',
name='dealer',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='chatlogs', to='inventory.dealer'),
),
]

View File

@ -1,9 +1,9 @@
from appointment.models import Appointment # from appointment.models import Appointment
from django.contrib import admin from django.contrib import admin
from . import models from . import models
from django_ledger import models as ledger_models from django_ledger import models as ledger_models
from django_pdf_actions.actions import export_to_pdf_landscape, export_to_pdf_portrait # from django_pdf_actions.actions import export_to_pdf_landscape, export_to_pdf_portrait
from appointment import models as appointment_models # from appointment import models as appointment_models
from import_export.admin import ExportMixin from import_export.admin import ExportMixin
from import_export.resources import ModelResource from import_export.resources import ModelResource
@ -72,14 +72,14 @@ admin.site.register(models.UserActivityLog)
@admin.register(models.Car) @admin.register(models.Car)
class CarAdmin(admin.ModelAdmin): class CarAdmin(admin.ModelAdmin):
search_fields = ('vin',) search_fields = ('vin',)
actions = [export_to_pdf_landscape, export_to_pdf_portrait] # actions = [export_to_pdf_landscape, export_to_pdf_portrait]
@admin.register(models.CarMake) @admin.register(models.CarMake)
class CarMakeAdmin(admin.ModelAdmin): class CarMakeAdmin(admin.ModelAdmin):
list_display = ('name', 'arabic_name', 'is_sa_import') list_display = ('name', 'arabic_name', 'is_sa_import')
search_fields = ('name', 'arabic_name') search_fields = ('name', 'arabic_name')
list_filter = ('is_sa_import', 'name',) list_filter = ('is_sa_import', 'name',)
actions = [export_to_pdf_landscape, export_to_pdf_portrait] # actions = [export_to_pdf_landscape, export_to_pdf_portrait]
class Meta: class Meta:
verbose_name = "Car Make" verbose_name = "Car Make"
@ -152,9 +152,9 @@ class CarOptionAdmin(admin.ModelAdmin):
# search_fields = ('user__username', 'action') # search_fields = ('user__username', 'action')
# list_filter = ('timestamp',) # list_filter = ('timestamp',)
@admin.register(ledger_models.ItemTransactionModel) # @admin.register(ledger_models.ItemTransactionModel)
class ItemTransactionModelAdmin(admin.ModelAdmin): # class ItemTransactionModelAdmin(admin.ModelAdmin):
actions = [export_to_pdf_landscape, export_to_pdf_portrait] # actions = [export_to_pdf_landscape, export_to_pdf_portrait]

View File

@ -6,7 +6,7 @@ class InventoryConfig(AppConfig):
def ready(self): def ready(self):
import inventory.signals import inventory.signals
# from decimal import Decimal #from decimal import Decimal
# from inventory.models import VatRate #from inventory.models import VatRate
# VatRate.objects.get_or_create(rate=Decimal('0.15'), is_active=True) #VatRate.objects.get_or_create(rate=Decimal('0.15'), is_active=True)

View File

@ -1,19 +1,12 @@
from django.core.cache import cache from django.core.cache import cache
from django.contrib.auth.models import Permission from django.contrib.auth.models import Permission
from django.contrib.auth.models import Group from appointment.models import Service
from appointment.models import Appointment, Service, StaffMember
from django.urls import reverse
from django_countries.widgets import CountrySelectWidget
from django_ledger.models import CustomerModel
from phonenumber_field.formfields import PhoneNumberField from phonenumber_field.formfields import PhoneNumberField
from django.core.validators import MinLengthValidator from django.core.validators import MinLengthValidator
from django.core.validators import RegexValidator
from django import forms from django import forms
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from phonenumber_field.phonenumber import PhoneNumber
from .models import CustomGroup, Status, Stage from .models import CustomGroup, Status, Stage
from .mixins import AddClassMixin from .mixins import AddClassMixin
from django.forms.models import inlineformset_factory
from django_ledger.forms.invoice import ( from django_ledger.forms.invoice import (
InvoiceModelCreateForm as InvoiceModelCreateFormBase, InvoiceModelCreateForm as InvoiceModelCreateFormBase,
) )
@ -21,17 +14,14 @@ from django_ledger.forms.estimate import (
EstimateModelCreateForm as EstimateModelCreateFormBase, EstimateModelCreateForm as EstimateModelCreateFormBase,
) )
# from django_ledger.forms.ledger import LedgerModelCreateForm as LedgerModelCreateFormBase
from django_ledger.forms.bill import BillModelCreateForm as BillModelCreateFormBase from django_ledger.forms.bill import BillModelCreateForm as BillModelCreateFormBase
from django_ledger.forms.journal_entry import JournalEntryModelCreateForm as JournalEntryModelCreateFormBase from django_ledger.forms.journal_entry import JournalEntryModelCreateForm as JournalEntryModelCreateFormBase
from .models import ( from .models import (
Dealer, Dealer,
DealersMake, DealersMake,
# Branch,
Vendor, Vendor,
Schedule, Schedule,
Customer,
Car, Car,
CarTransfer, CarTransfer,
CarFinance, CarFinance,
@ -40,16 +30,11 @@ from .models import (
CarColors, CarColors,
ExteriorColors, ExteriorColors,
InteriorColors, InteriorColors,
# SaleQuotation,
CarLocation, CarLocation,
Representative, Representative,
# SaleQuotationCar,
AdditionalServices, AdditionalServices,
Staff, Staff,
Opportunity, Opportunity,
Lead, Lead,
Activity, Activity,
Notes, Notes,
@ -65,7 +50,6 @@ from django.forms import (
) )
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
import django_tables2 as tables import django_tables2 as tables
from django.forms import formset_factory
User = get_user_model() User = get_user_model()
@ -90,14 +74,6 @@ class AdditionalServiceForm(forms.ModelForm):
model = AdditionalServices model = AdditionalServices
fields = ["name", "price", "description", "taxable", "uom"] fields = ["name", "price", "description", "taxable", "uom"]
# class PaymentForm(forms.ModelForm):
# invoice = forms.ModelChoiceField(queryset=InvoiceModel.objects.all(),label="Invoice", required=True)
# class Meta:
# model = Payment
# fields = ['amount','payment_method', 'reference_number']
class StaffForm(forms.ModelForm): class StaffForm(forms.ModelForm):
""" """
Represents a form for managing Staff entities, including associated user email updates Represents a form for managing Staff entities, including associated user email updates
@ -128,22 +104,6 @@ class StaffForm(forms.ModelForm):
model = Staff model = Staff
fields = ["name", "arabic_name", "phone_number", "staff_type"] fields = ["name", "arabic_name", "phone_number", "staff_type"]
# def __init__(self, *args, **kwargs):
# user_instance = kwargs.get("instance")
# if user_instance and user_instance.user:
# initial = kwargs.setdefault("initial", {})
# initial["email"] = user_instance.user.email
# super().__init__(*args, **kwargs)
#
# def save(self, commit=True):
# user_instance = super().save(commit=False)
# user = user_instance.user
# user.email = self.cleaned_data["email"]
# if commit:
# user.save()
# user_instance.save()
# return user_instance
# Dealer Form # Dealer Form
class DealerForm(forms.ModelForm): class DealerForm(forms.ModelForm):
@ -258,28 +218,6 @@ class OrganizationForm(CustomerForm):
logo = forms.ImageField(required=False) logo = forms.ImageField(required=False)
# class CustomerForm(forms.ModelForm, AddClassMixin):
# class Meta:
# model = Customer
# fields = [
# "title",
# "first_name",
# "middle_name",
# "last_name",
# "gender",
# "dob",
# "email",
# "national_id",
# "phone_number",
# "address",
# ]
# widgets = {
# "phone_number": forms.TextInput(attrs={"class": "phone"}),
# "dob": forms.DateInput(attrs={"type": "date"}),
# }
class CarForm( class CarForm(
forms.ModelForm, forms.ModelForm,
AddClassMixin, AddClassMixin,
@ -338,10 +276,6 @@ class CarForm(
self.fields["vendor"].queryset = ledger_models.VendorModel.objects.filter( self.fields["vendor"].queryset = ledger_models.VendorModel.objects.filter(
active=True active=True
) )
# queryset = self.fields["vendor"].queryset
# self.fields["vendor"].choices = [
# (obj.pk, obj.get_local_name()) for obj in queryset
# ]
class CarUpdateForm(forms.ModelForm, AddClassMixin): class CarUpdateForm(forms.ModelForm, AddClassMixin):
@ -382,19 +316,6 @@ class CarUpdateForm(forms.ModelForm, AddClassMixin):
dealer = kwargs.pop("dealer", None) dealer = kwargs.pop("dealer", None)
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
# if dealer and 'branch' in self.fields:
# self.fields['branch'].queryset = Branch.objects.filter(dealer=dealer)
# self.fields['branch'].choices = [
# (branch.id, branch.get_local_name()) for branch in self.fields['branch'].queryset
# ]
# if "vendor" in self.fields:
# queryset = self.fields["vendor"].queryset
# if queryset:
# self.fields["vendor"].choices = [
# (vendor.id, vendor.get_local_name()) for vendor in queryset
# ]
class CarFinanceForm(forms.ModelForm): class CarFinanceForm(forms.ModelForm):
""" """
@ -424,13 +345,6 @@ class CarFinanceForm(forms.ModelForm):
"additional_services", "additional_services",
] ]
# def __init__(self, *args, **kwargs):
# super().__init__(*args, **kwargs)
# if self.instance.pk:
# self.fields[
# "additional_finances"
# ].initial = self.instance.additional_services.all()
def save(self, commit=True): def save(self, commit=True):
instance = super().save() instance = super().save()
instance.additional_services.set(self.cleaned_data["additional_finances"]) instance.additional_services.set(self.cleaned_data["additional_finances"])
@ -617,43 +531,6 @@ class CarColorsForm(forms.ModelForm):
return cleaned_data return cleaned_data
# class QuotationForm(forms.ModelForm):
# cars = ModelMultipleChoiceField(
# queryset=Car.objects.none(), # Default empty queryset
# widget=forms.CheckboxSelectMultiple,
# label="Select Cars",
# )
#
# class Meta:
# model = SaleQuotation
# fields = ["customer", "cars", "remarks"]
#
# def __init__(self, *args, **kwargs):
# super().__init__(*args, **kwargs)
#
# self.fields["cars"].queryset = Car.objects.filter(
# finances__isnull=False
# ).distinct()
# class OrganizationForm(forms.ModelForm):
# class Meta:
# model = Organization
# fields = [
# "name",
# "arabic_name",
# "crn",
# "vrn",
# "phone_number",
# "address",
# "logo",
# ]
# def __init__(self, *args, **kwargs):
# dealer = kwargs.pop("dealer", None)
# super().__init__(*args, **kwargs)
class RepresentativeForm(forms.ModelForm): class RepresentativeForm(forms.ModelForm):
""" """
A form for creating or updating instances of the Representative model. A form for creating or updating instances of the Representative model.
@ -958,17 +835,6 @@ class WizardForm3(forms.Form):
}, },
) )
# def clean(self):
# cleaned_data = super().clean()
# password = cleaned_data.get("password")
# confirm_password = cleaned_data.get("confirm_password")
# if password != confirm_password:
# raise forms.ValidationError("Passwords do not match.")
# else:
# return cleaned_data
class ItemForm(forms.Form): class ItemForm(forms.Form):
""" """
A form for handling item-related inputs in the application. A form for handling item-related inputs in the application.
@ -991,9 +857,6 @@ class ItemForm(forms.Form):
validators=[MinLengthValidator(5)], validators=[MinLengthValidator(5)],
) )
quantity = forms.DecimalField(label="Quantity", required=True) quantity = forms.DecimalField(label="Quantity", required=True)
# unit = forms.DecimalField(label="Unit", required=True)
# unit_cost = forms.DecimalField(label="Unit Cost", required=True)
# unit_sales_price = forms.DecimalField(label="Unit Sales Price", required=True)
class PaymentForm(forms.Form): class PaymentForm(forms.Form):
@ -1278,10 +1141,6 @@ class BillModelCreateForm(BillModelCreateFormBase):
self.fields["cash_account"].widget = forms.HiddenInput() self.fields["cash_account"].widget = forms.HiddenInput()
self.fields["prepaid_account"].widget = forms.HiddenInput() self.fields["prepaid_account"].widget = forms.HiddenInput()
self.fields["unearned_account"].widget = forms.HiddenInput() self.fields["unearned_account"].widget = forms.HiddenInput()
# self.fields["date_draft"] = forms.DateField(
# widget=DateInput(attrs={"type": "date"})
# )
class SaleOrderForm(forms.ModelForm): class SaleOrderForm(forms.ModelForm):
""" """
@ -1568,6 +1427,3 @@ class JournalEntryModelCreateForm(JournalEntryModelCreateFormBase):
:type bar: int :type bar: int
""" """
pass pass
# class LedgerModelCreateForm(LedgerModelCreateFormBase):
# pass

File diff suppressed because it is too large Load Diff

View File

@ -28,9 +28,9 @@ def get_make(item):
:rtype: CarMake or None :rtype: CarMake or None
""" """
data = CarMake.objects.filter(name__iexact=item).first() data = CarMake.objects.filter(name__iexact=item).first()
if not data: if not data:
r = item.split(" ") r = item.split(" ")
for i in r: for i in r:
if data:= CarMake.objects.filter(name__iexact=i).first(): if data:= CarMake.objects.filter(name__iexact=i).first():
break break
return data return data
@ -48,9 +48,9 @@ def get_model(item,make):
or None if no match is found. or None if no match is found.
""" """
data = make.carmodel_set.filter(name__iexact=item).first() data = make.carmodel_set.filter(name__iexact=item).first()
if not data: if not data:
r = item.split(" ") r = item.split(" ")
for i in r: for i in r:
if data:=make.carmodel_set.filter(name__iexact=i).first(): if data:=make.carmodel_set.filter(name__iexact=i).first():
break break
return data return data
@ -72,6 +72,7 @@ def normalize_name(name):
def decodevin(vin): def decodevin(vin):
""" """
Decodes a Vehicle Identification Number (VIN) using multiple decoding functions Decodes a Vehicle Identification Number (VIN) using multiple decoding functions
and returns the decoded result. This function attempts to decode the VIN using and returns the decoded result. This function attempts to decode the VIN using
@ -112,7 +113,7 @@ def decode_vin(vin):
""" """
v = VIN(vin) v = VIN(vin)
data = {} data = {}
if v: if v:
data = { data = {
"maker": v.Make, "maker": v.Make,
"model": v.Model, "model": v.Model,
@ -159,4 +160,5 @@ def elm(vin):
"model": response["data"]["model"], "model": response["data"]["model"],
"modelYear": response["data"]["modelYear"], "modelYear": response["data"]["modelYear"],
} }
print(data)
return data if all([x for x in data.values()]) else None return data if all([x for x in data.values()]) else None

View File

@ -1,3 +1,4 @@
from inventory.tasks import create_coa_accounts,create_accounts_for_make,create_settings
from django.contrib.auth.models import Group from django.contrib.auth.models import Group
from decimal import Decimal from decimal import Decimal
from django.db.models.signals import post_save, post_delete, pre_delete, pre_save from django.db.models.signals import post_save, post_delete, pre_delete, pre_save
@ -142,519 +143,10 @@ def create_ledger_entity(sender, instance, created, **kwargs):
for u in models.UnitOfMeasure.choices: for u in models.UnitOfMeasure.choices:
entity.create_uom(name=u[1], unit_abbr=u[0]) entity.create_uom(name=u[1], unit_abbr=u[0])
# Cash Account # Create COA accounts, background task
asset_ca_cash = entity.create_account( create_coa_accounts(instance.pk)
coa_model=coa, create_settings(instance.pk)
code="1101", # create_accounts_for_make(instance.pk)
role=roles.ASSET_CA_CASH,
name=_("Cash"),
balance_type="debit",
active=True,
)
asset_ca_cash.role_default = True
asset_ca_cash.save()
# 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()
# 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()
# Prepaid Expenses Account
asset_ca_prepaid = entity.create_account(
coa_model=coa,
code="1104",
role=roles.ASSET_CA_PREPAID,
name=_("Prepaid Expenses"),
balance_type="debit",
active=True,
)
asset_ca_prepaid.role_default = True
asset_ca_prepaid.save()
# Employee Expenses Account
asset_ca_prepaid_employee = entity.create_account(
coa_model=coa,
code="1105",
role=roles.ASSET_CA_PREPAID,
name=_("Employee Advance"),
balance_type="debit",
active=True,
)
# VAT Payable Account
liability_ltl_vat_receivable = entity.create_account(
coa_model=coa,
code="1106",
role=roles.ASSET_CA_RECEIVABLES,
name=_("VAT Receivable"),
balance_type="debit",
active=True,
)
# Buildings Accumulated Depreciation Account
asset_ppe_buildings_accum_depreciation = entity.create_account(
coa_model=coa,
code="1201",
role=roles.ASSET_PPE_BUILDINGS_ACCUM_DEPRECIATION,
name=_("Buildings - Accum. Depreciation"),
balance_type="credit",
active=True,
)
asset_ppe_buildings_accum_depreciation.role_default = True
asset_ppe_buildings_accum_depreciation.save()
# intangible Account
asset_lti_land_intangable = entity.create_account(
coa_model=coa,
code="1202",
role=roles.ASSET_INTANGIBLE_ASSETS,
name=_("Intangible Assets"),
balance_type="debit",
active=True,
)
asset_lti_land_intangable.role_default = True
asset_lti_land_intangable.save()
# investment property Account
asset_lti_land_investment = entity.create_account(
coa_model=coa,
code="1204",
role=roles.ASSET_LTI_SECURITIES,
name=_("Investments"),
balance_type="debit",
active=True,
)
asset_lti_land_investment.role_default = True
asset_lti_land_investment.save()
# # Notes Receivable Account
# asset_lti_notes_receivable = entity.create_account(
# coa_model=coa,
# code="1201",
# role=roles.ASSET_LTI_NOTES_RECEIVABLE,
# name=_("Notes Receivable"),
# balance_type="debit",
# active=True,
# )
# asset_lti_notes_receivable.role_default = True
# asset_lti_notes_receivable.save()
# # Land Account
# asset_lti_land = entity.create_account(
# coa_model=coa,
# code="1202",
# role=roles.ASSET_LTI_LAND,
# name=_("Land"),
# balance_type="debit",
# active=True,
# )
# asset_lti_land.role_default = True
# asset_lti_land.save()
# Buildings Account
asset_ppe_buildings = entity.create_account(
coa_model=coa,
code="1301",
role=roles.ASSET_PPE_BUILDINGS,
name=_("Buildings"),
balance_type="debit",
active=True,
)
asset_ppe_buildings.role_default = True
asset_ppe_buildings.save()
# Accounts Payable Account
liability_cl_acc_payable = entity.create_account(
coa_model=coa,
code="2101",
role=roles.LIABILITY_CL_ACC_PAYABLE,
name=_("Accounts Payable"),
balance_type="credit",
active=True,
)
liability_cl_acc_payable.role_default = True
liability_cl_acc_payable.save()
# Deferred Revenue Account
liability_cl_def_rev = entity.create_account(
coa_model=coa,
code="2103",
role=roles.LIABILITY_CL_DEFERRED_REVENUE,
name=_("Deferred Revenue"),
balance_type="credit",
active=True,
)
liability_cl_def_rev.role_default = True
liability_cl_def_rev.save()
# Wages Payable Account
liability_cl_wages_payable = entity.create_account(
coa_model=coa,
code="2102",
role=roles.LIABILITY_CL_WAGES_PAYABLE,
name=_("Wages Payable"),
balance_type="credit",
active=True,
)
liability_cl_wages_payable.role_default = True
liability_cl_wages_payable.save()
# Long-Term Notes Payable Account
liability_ltl_notes_payable = entity.create_account(
coa_model=coa,
code="2201",
role=roles.LIABILITY_LTL_NOTES_PAYABLE,
name=_("Long-Term Notes Payable"),
balance_type="credit",
active=True,
)
liability_ltl_notes_payable.role_default = True
liability_ltl_notes_payable.save()
# VAT Payable Account
liability_ltl_vat_payable = entity.create_account(
coa_model=coa,
code="2106",
role=roles.LIABILITY_CL_OTHER,
name=_("VAT Payable"),
balance_type="credit",
active=True,
)
# taxes Payable Account
liability_ltl_taxes_payable = entity.create_account(
coa_model=coa,
code="2107",
role=roles.LIABILITY_CL_OTHER,
name=_("Taxes Payable"),
balance_type="credit",
active=True,
)
# social insurance Payable Account
liability_ltl_social_insurance_payable = entity.create_account(
coa_model=coa,
code="2108",
role=roles.LIABILITY_LTL_NOTES_PAYABLE,
name=_("Social Insurance Payable"),
balance_type="credit",
active=True,
)
# End of Service Benefits
entity.create_account(coa_model=coa, code="2202", role=roles.LIABILITY_LTL_NOTES_PAYABLE, name=_("End of Service Benefits"), balance_type="credit", active=True)
# Mortgage Payable Account
liability_ltl_mortgage_payable = entity.create_account(
coa_model=coa,
code="2203",
role=roles.LIABILITY_LTL_MORTGAGE_PAYABLE,
name=_("Mortgage Payable"),
balance_type="credit",
active=True,
)
liability_ltl_mortgage_payable.role_default = True
liability_ltl_mortgage_payable.save()
# Capital
equity_capital = entity.create_account(coa_model=coa, code="3101", role=roles.EQUITY_CAPITAL, name=_("Registered Capital"), balance_type="credit", active=True)
equity_capital.role_default = True
equity_capital.save()
entity.create_account(coa_model=coa, code="3102", role=roles.EQUITY_CAPITAL, name=_("Additional Paid-In Capital"), balance_type="credit", active=True)
# Other Equity
other_equity = entity.create_account(coa_model=coa, code="3201", role=roles.EQUITY_COMMON_STOCK, name=_("Opening Balances"), balance_type="credit", active=True)
other_equity.role_default = True
other_equity.save()
# Reserves
reserve = entity.create_account(coa_model=coa, code="3301", role=roles.EQUITY_ADJUSTMENT, name=_("Statutory Reserve"), balance_type="credit", active=True)
reserve.role_default = True
reserve.save()
entity.create_account(coa_model=coa, code="3302", role=roles.EQUITY_ADJUSTMENT, name=_("Foreign Currency Translation Reserve"), balance_type="credit", active=True)
# Retained Earnings Account
equity_retained_earnings = entity.create_account(
coa_model=coa,
code="3401",
role=roles.EQUITY_PREFERRED_STOCK,
name=_("Operating Profits and Losses"),
balance_type="credit",
active=True,
)
equity_retained_earnings.role_default = True
equity_retained_earnings.save()
equity_retained_earnings_losses = entity.create_account(
coa_model=coa,
code="3402",
role=roles.EQUITY_PREFERRED_STOCK,
name=_("Retained Earnings (or Losses)"),
balance_type="credit",
active=True,
)
# Sales Revenue Account
income_operational = entity.create_account(
coa_model=coa,
code="4101",
role=roles.INCOME_OPERATIONAL,
name=_("Sales Revenue"),
balance_type="credit",
active=True,
)
income_operational.role_default = True
income_operational.save()
# Interest Income Account
income_interest = entity.create_account(
coa_model=coa,
code="4102",
role=roles.INCOME_INTEREST,
name=_("Interest Income"),
balance_type="credit",
active=True,
)
income_interest.role_default = True
income_interest.save()
# Uneared Income Account
income_unearned = entity.create_account(
coa_model=coa,
code="4103",
role=roles.INCOME_OTHER,
name=_("Unearned Income"),
balance_type="credit",
active=True,
)
# Operating Revenues
entity.create_account(coa_model=coa, code="4104", role=roles.INCOME_OPERATIONAL, name=_("Sales/Service Revenue"), balance_type="credit", active=True)
#Non-Operating Revenues
entity.create_account(coa_model=coa, code="4201", role=roles.INCOME_OTHER, name=_("Non-Operating Revenues"), balance_type="credit", active=True)
# Cost of Goods Sold (COGS) Account
expense_cogs = entity.create_account(
coa_model=coa,
code="5101",
role=roles.COGS,
name=_("Cost of Goods Sold"),
balance_type="debit",
active=True,
)
expense_cogs.role_default = True
expense_cogs.save()
# accrued Expenses Account
expense_cogs = entity.create_account(
coa_model=coa,
code="6117",
role=roles.EXPENSE_OPERATIONAL,
name=_("Accrued Expenses"),
balance_type="debit",
active=True,
)
# accrued salaries Account
expense_cogs = entity.create_account(
coa_model=coa,
code="6118",
role=roles.EXPENSE_OPERATIONAL,
name=_("Accrued Salaries"),
balance_type="debit",
active=True,
)
# Rent Expense Account
expense_rent = entity.create_account(
coa_model=coa,
code="6102",
role=roles.EXPENSE_OPERATIONAL,
name=_("Rent Expense"),
balance_type="debit",
active=True,
)
# expense_rent.role_default = True
# expense_rent.save()
# Salaries and Administrative Fees
expense_salaries = entity.create_account(
coa_model=coa,
code="6103",
role=roles.EXPENSE_OPERATIONAL,
name=_("Salaries and Administrative Fees"),
balance_type="debit",
active=True,
)
# Medical Insurance
expense_medical_insurance = entity.create_account(
coa_model=coa,
code="6104",
role=roles.EXPENSE_OPERATIONAL,
name=_("Medical Insurance"),
balance_type="debit",
active=True,
)
# Marketing and Advertising Expenses
expense_marketing = entity.create_account(
coa_model=coa,
code="6105",
role=roles.EXPENSE_OPERATIONAL,
name=_("Marketing and Advertising Expenses"),
balance_type="debit",
active=True,
)
# Commissions and Incentives
expense_commissions = entity.create_account(
coa_model=coa,
code="6106",
role=roles.EXPENSE_OPERATIONAL,
name=_("Commissions and Incentives"),
balance_type="debit",
active=True,
)
# Travel Tickets
expense_travel = entity.create_account(
coa_model=coa,
code="6107",
role=roles.EXPENSE_OPERATIONAL,
name=_("Travel Tickets"),
balance_type="debit",
active=True,
)
# Social Insurance
expense_other = entity.create_account(
coa_model=coa,
code="6108",
role=roles.EXPENSE_OPERATIONAL,
name=_("Social Insurance"),
balance_type="debit",
active=True,
)
# Government Fees
expense_other = entity.create_account(
coa_model=coa,
code="6109",
role=roles.EXPENSE_OPERATIONAL,
name=_("Government Fees"),
balance_type="debit",
active=True,
)
# Fees and Subscriptions
expense_other = entity.create_account(
coa_model=coa,
code="6110",
role=roles.EXPENSE_OPERATIONAL,
name=_("Fees and Subscriptions"),
balance_type="debit",
active=True,
)
# Office Services Expenses
expense_other = entity.create_account(
coa_model=coa,
code="6111",
role=roles.EXPENSE_OPERATIONAL,
name=_("Office Services Expenses"),
balance_type="debit",
active=True,
)
# Office Supplies and Printing
expense_other = entity.create_account(
coa_model=coa,
code="6112",
role=roles.EXPENSE_OPERATIONAL,
name=_("Office Supplies and Printing"),
balance_type="debit",
active=True,
)
# Hospitality Expenses
expense_other = entity.create_account(
coa_model=coa,
code="6113",
role=roles.EXPENSE_OPERATIONAL,
name=_("Hospitality Expenses"),
balance_type="debit",
active=True,
)
# Bank Commissions
expense_other = entity.create_account(
coa_model=coa,
code="6114",
role=roles.EXPENSE_OPERATIONAL,
name=_("Bank Commissions"),
balance_type="debit",
active=True,
)
# Other Expenses
expense_other = entity.create_account(
coa_model=coa,
code="6115",
role=roles.EXPENSE_OPERATIONAL,
name=_("Other Expenses"),
balance_type="debit",
active=True,
)
# Transportation Expenses
expense_other = entity.create_account(
coa_model=coa,
code="6116",
role=roles.EXPENSE_OPERATIONAL,
name=_("Transportation Expenses"),
balance_type="debit",
active=True,
)
# 5.1 Direct Costs
entity.create_account(coa_model=coa, code="6201", role=roles.EXPENSE_OPERATIONAL, name=_("Cost of Goods Sold"), balance_type="debit", active=True)
entity.create_account(coa_model=coa, code="6202", role=roles.EXPENSE_OPERATIONAL, name=_("Salaries and Wages"), balance_type="debit", active=True)
entity.create_account(coa_model=coa, code="6203", role=roles.EXPENSE_OPERATIONAL, name=_("Sales Commissions"), balance_type="debit", active=True)
entity.create_account(coa_model=coa, code="6204", role=roles.EXPENSE_OPERATIONAL, name=_("Shipping and Customs Clearance"), balance_type="debit", active=True)
# 5.3 Non-Operating Expenses
entity.create_account(coa_model=coa, code="6301", role=roles.EXPENSE_OTHER, name=_("Zakat"), balance_type="debit", active=True)
entity.create_account(coa_model=coa, code="6302", role=roles.EXPENSE_OTHER, name=_("Taxes"), balance_type="debit", active=True)
entity.create_account(coa_model=coa, code="6303", role=roles.EXPENSE_OTHER, name=_("Foreign Currency Translation"), balance_type="debit", active=True)
entity.create_account(coa_model=coa, code="6304", role=roles.EXPENSE_OTHER, name=_("Interest Expenses"), balance_type="debit", active=True)
@receiver(post_save, sender=models.Dealer) @receiver(post_save, sender=models.Dealer)
def create_dealer_groups(sender, instance, created, **kwargs): def create_dealer_groups(sender, instance, created, **kwargs):
@ -679,7 +171,6 @@ def create_dealer_groups(sender, instance, created, **kwargs):
group_manager,created = models.CustomGroup.objects.get_or_create(name=group_name, dealer=instance, group=group) group_manager,created = models.CustomGroup.objects.get_or_create(name=group_name, dealer=instance, group=group)
group_manager.set_default_permissions() group_manager.set_default_permissions()
instance.user.groups.add(group) instance.user.groups.add(group)
transaction.on_commit(create_groups) transaction.on_commit(create_groups)
# Create Vendor # Create Vendor
@receiver(post_save, sender=models.Vendor) @receiver(post_save, sender=models.Vendor)
@ -1137,8 +628,6 @@ def create_dealer_settings(sender, instance, created, **kwargs):
# current_staff_count = instance.dealer.staff.count() # current_staff_count = instance.dealer.staff.count()
# if current_staff_count > allowed_users: # if current_staff_count > allowed_users:
# raise ValidationError(_("You have reached the maximum number of staff users allowed for your plan.")) # raise ValidationError(_("You have reached the maximum number of staff users allowed for your plan."))
@receiver(post_save, sender=models.Dealer) @receiver(post_save, sender=models.Dealer)
def create_vat(sender, instance, created, **kwargs): def create_vat(sender, instance, created, **kwargs):
""" """
@ -1176,21 +665,21 @@ def create_make_ledger_accounts(sender, instance, created, **kwargs):
entity = instance.entity entity = instance.entity
coa = entity.get_default_coa() coa = entity.get_default_coa()
last_account = entity.get_all_accounts().filter(role=roles.ASSET_CA_RECEIVABLES).order_by('-created').first() # for make in models.CarMake.objects.all():
if len(last_account.code) == 4: # last_account = entity.get_all_accounts().filter(role=roles.ASSET_CA_RECEIVABLES).order_by('-created').first()
code = f"{int(last_account.code)}{1:03d}" # if len(last_account.code) == 4:
elif len(last_account.code) > 4: # code = f"{int(last_account.code)}{1:03d}"
code = f"{int(last_account.code)+1}" # elif len(last_account.code) > 4:
# code = f"{int(last_account.code)+1}"
# entity.create_account(
# name=make.name,
# code=code,
# role=roles.ASSET_CA_RECEIVABLES,
# coa_model=coa,
# balance_type="credit",
# active=True
# )
for make in models.CarMake.objects.all():
entity.create_account(
name=make.name,
code=code,
role=roles.ASSET_CA_RECEIVABLES,
coa_model=coa,
balance_type="credit",
active=True
)
# @receiver(post_save, sender=VendorModel) # @receiver(post_save, sender=VendorModel)
@ -1333,4 +822,4 @@ def update_finance_cost(sender, instance, created, **kwargs):
# else: # else:
# save_journal(instance,ledger,vendor) # save_journal(instance,ledger,vendor)
# else: # else:
# save_journal(instance,ledger,vendor) # save_journal(instance,ledger,vendor)

580
inventory/tasks.py Normal file
View File

@ -0,0 +1,580 @@
from django_ledger.io import roles
from django.core.mail import send_mail
from background_task import background
from django.utils.translation import gettext_lazy as _
from inventory.models import DealerSettings,CarMake,Dealer
@background
def create_coa_accounts(pk):
instance = Dealer.objects.get(pk=pk)
entity = instance.entity
coa = entity.get_default_coa()
# Cash Account
asset_ca_cash = entity.create_account(
coa_model=coa,
code="1101",
role=roles.ASSET_CA_CASH,
name=_("Cash"),
balance_type="debit",
active=True,
)
asset_ca_cash.role_default = True
asset_ca_cash.save()
# 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()
# 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()
# Prepaid Expenses Account
asset_ca_prepaid = entity.create_account(
coa_model=coa,
code="1104",
role=roles.ASSET_CA_PREPAID,
name=_("Prepaid Expenses"),
balance_type="debit",
active=True,
)
asset_ca_prepaid.role_default = True
asset_ca_prepaid.save()
# Employee Expenses Account
asset_ca_prepaid_employee = entity.create_account(
coa_model=coa,
code="1105",
role=roles.ASSET_CA_PREPAID,
name=_("Employee Advance"),
balance_type="debit",
active=True,
)
# VAT Payable Account
liability_ltl_vat_receivable = entity.create_account(
coa_model=coa,
code="1106",
role=roles.ASSET_CA_RECEIVABLES,
name=_("VAT Receivable"),
balance_type="debit",
active=True,
)
# Buildings Accumulated Depreciation Account
asset_ppe_buildings_accum_depreciation = entity.create_account(
coa_model=coa,
code="1201",
role=roles.ASSET_PPE_BUILDINGS_ACCUM_DEPRECIATION,
name=_("Buildings - Accum. Depreciation"),
balance_type="credit",
active=True,
)
asset_ppe_buildings_accum_depreciation.role_default = True
asset_ppe_buildings_accum_depreciation.save()
# intangible Account
asset_lti_land_intangable = entity.create_account(
coa_model=coa,
code="1202",
role=roles.ASSET_INTANGIBLE_ASSETS,
name=_("Intangible Assets"),
balance_type="debit",
active=True,
)
asset_lti_land_intangable.role_default = True
asset_lti_land_intangable.save()
# investment property Account
asset_lti_land_investment = entity.create_account(
coa_model=coa,
code="1204",
role=roles.ASSET_LTI_SECURITIES,
name=_("Investments"),
balance_type="debit",
active=True,
)
asset_lti_land_investment.role_default = True
asset_lti_land_investment.save()
# # Notes Receivable Account
# asset_lti_notes_receivable = entity.create_account(
# coa_model=coa,
# code="1201",
# role=roles.ASSET_LTI_NOTES_RECEIVABLE,
# name=_("Notes Receivable"),
# balance_type="debit",
# active=True,
# )
# asset_lti_notes_receivable.role_default = True
# asset_lti_notes_receivable.save()
# # Land Account
# asset_lti_land = entity.create_account(
# coa_model=coa,
# code="1202",
# role=roles.ASSET_LTI_LAND,
# name=_("Land"),
# balance_type="debit",
# active=True,
# )
# asset_lti_land.role_default = True
# asset_lti_land.save()
# Buildings Account
asset_ppe_buildings = entity.create_account(
coa_model=coa,
code="1301",
role=roles.ASSET_PPE_BUILDINGS,
name=_("Buildings"),
balance_type="debit",
active=True,
)
asset_ppe_buildings.role_default = True
asset_ppe_buildings.save()
# Accounts Payable Account
liability_cl_acc_payable = entity.create_account(
coa_model=coa,
code="2101",
role=roles.LIABILITY_CL_ACC_PAYABLE,
name=_("Accounts Payable"),
balance_type="credit",
active=True,
)
liability_cl_acc_payable.role_default = True
liability_cl_acc_payable.save()
# Deferred Revenue Account
liability_cl_def_rev = entity.create_account(
coa_model=coa,
code="2103",
role=roles.LIABILITY_CL_DEFERRED_REVENUE,
name=_("Deferred Revenue"),
balance_type="credit",
active=True,
)
liability_cl_def_rev.role_default = True
liability_cl_def_rev.save()
# Wages Payable Account
liability_cl_wages_payable = entity.create_account(
coa_model=coa,
code="2102",
role=roles.LIABILITY_CL_WAGES_PAYABLE,
name=_("Wages Payable"),
balance_type="credit",
active=True,
)
liability_cl_wages_payable.role_default = True
liability_cl_wages_payable.save()
# Long-Term Notes Payable Account
liability_ltl_notes_payable = entity.create_account(
coa_model=coa,
code="2201",
role=roles.LIABILITY_LTL_NOTES_PAYABLE,
name=_("Long-Term Notes Payable"),
balance_type="credit",
active=True,
)
liability_ltl_notes_payable.role_default = True
liability_ltl_notes_payable.save()
# VAT Payable Account
liability_ltl_vat_payable = entity.create_account(
coa_model=coa,
code="2106",
role=roles.LIABILITY_CL_OTHER,
name=_("VAT Payable"),
balance_type="credit",
active=True,
)
# taxes Payable Account
liability_ltl_taxes_payable = entity.create_account(
coa_model=coa,
code="2107",
role=roles.LIABILITY_CL_OTHER,
name=_("Taxes Payable"),
balance_type="credit",
active=True,
)
# social insurance Payable Account
liability_ltl_social_insurance_payable = entity.create_account(
coa_model=coa,
code="2108",
role=roles.LIABILITY_LTL_NOTES_PAYABLE,
name=_("Social Insurance Payable"),
balance_type="credit",
active=True,
)
# End of Service Benefits
entity.create_account(coa_model=coa, code="2202", role=roles.LIABILITY_LTL_NOTES_PAYABLE, name=_("End of Service Benefits"), balance_type="credit", active=True)
# Mortgage Payable Account
liability_ltl_mortgage_payable = entity.create_account(
coa_model=coa,
code="2203",
role=roles.LIABILITY_LTL_MORTGAGE_PAYABLE,
name=_("Mortgage Payable"),
balance_type="credit",
active=True,
)
liability_ltl_mortgage_payable.role_default = True
liability_ltl_mortgage_payable.save()
# Capital
equity_capital = entity.create_account(coa_model=coa, code="3101", role=roles.EQUITY_CAPITAL, name=_("Registered Capital"), balance_type="credit", active=True)
equity_capital.role_default = True
equity_capital.save()
entity.create_account(coa_model=coa, code="3102", role=roles.EQUITY_CAPITAL, name=_("Additional Paid-In Capital"), balance_type="credit", active=True)
# Other Equity
other_equity = entity.create_account(coa_model=coa, code="3201", role=roles.EQUITY_COMMON_STOCK, name=_("Opening Balances"), balance_type="credit", active=True)
other_equity.role_default = True
other_equity.save()
# Reserves
reserve = entity.create_account(coa_model=coa, code="3301", role=roles.EQUITY_ADJUSTMENT, name=_("Statutory Reserve"), balance_type="credit", active=True)
reserve.role_default = True
reserve.save()
entity.create_account(coa_model=coa, code="3302", role=roles.EQUITY_ADJUSTMENT, name=_("Foreign Currency Translation Reserve"), balance_type="credit", active=True)
# Retained Earnings Account
equity_retained_earnings = entity.create_account(
coa_model=coa,
code="3401",
role=roles.EQUITY_PREFERRED_STOCK,
name=_("Operating Profits and Losses"),
balance_type="credit",
active=True,
)
equity_retained_earnings.role_default = True
equity_retained_earnings.save()
equity_retained_earnings_losses = entity.create_account(
coa_model=coa,
code="3402",
role=roles.EQUITY_PREFERRED_STOCK,
name=_("Retained Earnings (or Losses)"),
balance_type="credit",
active=True,
)
# Sales Revenue Account
income_operational = entity.create_account(
coa_model=coa,
code="4101",
role=roles.INCOME_OPERATIONAL,
name=_("Sales Revenue"),
balance_type="credit",
active=True,
)
income_operational.role_default = True
income_operational.save()
# Interest Income Account
income_interest = entity.create_account(
coa_model=coa,
code="4102",
role=roles.INCOME_INTEREST,
name=_("Interest Income"),
balance_type="credit",
active=True,
)
income_interest.role_default = True
income_interest.save()
# Uneared Income Account
income_unearned = entity.create_account(
coa_model=coa,
code="4103",
role=roles.INCOME_OTHER,
name=_("Unearned Income"),
balance_type="credit",
active=True,
)
# Operating Revenues
entity.create_account(coa_model=coa, code="4104", role=roles.INCOME_OPERATIONAL, name=_("Sales/Service Revenue"), balance_type="credit", active=True)
#Non-Operating Revenues
entity.create_account(coa_model=coa, code="4201", role=roles.INCOME_OTHER, name=_("Non-Operating Revenues"), balance_type="credit", active=True)
# Cost of Goods Sold (COGS) Account
expense_cogs = entity.create_account(
coa_model=coa,
code="5101",
role=roles.COGS,
name=_("Cost of Goods Sold"),
balance_type="debit",
active=True,
)
expense_cogs.role_default = True
expense_cogs.save()
# accrued Expenses Account
expense_cogs = entity.create_account(
coa_model=coa,
code="6117",
role=roles.EXPENSE_OPERATIONAL,
name=_("Accrued Expenses"),
balance_type="debit",
active=True,
)
# accrued salaries Account
expense_cogs = entity.create_account(
coa_model=coa,
code="6118",
role=roles.EXPENSE_OPERATIONAL,
name=_("Accrued Salaries"),
balance_type="debit",
active=True,
)
# Rent Expense Account
expense_rent = entity.create_account(
coa_model=coa,
code="6102",
role=roles.EXPENSE_OPERATIONAL,
name=_("Rent Expense"),
balance_type="debit",
active=True,
)
# expense_rent.role_default = True
# expense_rent.save()
# Salaries and Administrative Fees
expense_salaries = entity.create_account(
coa_model=coa,
code="6103",
role=roles.EXPENSE_OPERATIONAL,
name=_("Salaries and Administrative Fees"),
balance_type="debit",
active=True,
)
# Medical Insurance
expense_medical_insurance = entity.create_account(
coa_model=coa,
code="6104",
role=roles.EXPENSE_OPERATIONAL,
name=_("Medical Insurance"),
balance_type="debit",
active=True,
)
# Marketing and Advertising Expenses
expense_marketing = entity.create_account(
coa_model=coa,
code="6105",
role=roles.EXPENSE_OPERATIONAL,
name=_("Marketing and Advertising Expenses"),
balance_type="debit",
active=True,
)
# Commissions and Incentives
expense_commissions = entity.create_account(
coa_model=coa,
code="6106",
role=roles.EXPENSE_OPERATIONAL,
name=_("Commissions and Incentives"),
balance_type="debit",
active=True,
)
# Travel Tickets
expense_travel = entity.create_account(
coa_model=coa,
code="6107",
role=roles.EXPENSE_OPERATIONAL,
name=_("Travel Tickets"),
balance_type="debit",
active=True,
)
# Social Insurance
expense_other = entity.create_account(
coa_model=coa,
code="6108",
role=roles.EXPENSE_OPERATIONAL,
name=_("Social Insurance"),
balance_type="debit",
active=True,
)
# Government Fees
expense_other = entity.create_account(
coa_model=coa,
code="6109",
role=roles.EXPENSE_OPERATIONAL,
name=_("Government Fees"),
balance_type="debit",
active=True,
)
# Fees and Subscriptions
expense_other = entity.create_account(
coa_model=coa,
code="6110",
role=roles.EXPENSE_OPERATIONAL,
name=_("Fees and Subscriptions"),
balance_type="debit",
active=True,
)
# Office Services Expenses
expense_other = entity.create_account(
coa_model=coa,
code="6111",
role=roles.EXPENSE_OPERATIONAL,
name=_("Office Services Expenses"),
balance_type="debit",
active=True,
)
# Office Supplies and Printing
expense_other = entity.create_account(
coa_model=coa,
code="6112",
role=roles.EXPENSE_OPERATIONAL,
name=_("Office Supplies and Printing"),
balance_type="debit",
active=True,
)
# Hospitality Expenses
expense_other = entity.create_account(
coa_model=coa,
code="6113",
role=roles.EXPENSE_OPERATIONAL,
name=_("Hospitality Expenses"),
balance_type="debit",
active=True,
)
# Bank Commissions
expense_other = entity.create_account(
coa_model=coa,
code="6114",
role=roles.EXPENSE_OPERATIONAL,
name=_("Bank Commissions"),
balance_type="debit",
active=True,
)
# Other Expenses
expense_other = entity.create_account(
coa_model=coa,
code="6115",
role=roles.EXPENSE_OPERATIONAL,
name=_("Other Expenses"),
balance_type="debit",
active=True,
)
# Transportation Expenses
expense_other = entity.create_account(
coa_model=coa,
code="6116",
role=roles.EXPENSE_OPERATIONAL,
name=_("Transportation Expenses"),
balance_type="debit",
active=True,
)
# 5.1 Direct Costs
entity.create_account(coa_model=coa, code="6201", role=roles.EXPENSE_OPERATIONAL, name=_("Cost of Goods Sold"), balance_type="debit", active=True)
entity.create_account(coa_model=coa, code="6202", role=roles.EXPENSE_OPERATIONAL, name=_("Salaries and Wages"), balance_type="debit", active=True)
entity.create_account(coa_model=coa, code="6203", role=roles.EXPENSE_OPERATIONAL, name=_("Sales Commissions"), balance_type="debit", active=True)
entity.create_account(coa_model=coa, code="6204", role=roles.EXPENSE_OPERATIONAL, name=_("Shipping and Customs Clearance"), balance_type="debit", active=True)
# 5.3 Non-Operating Expenses
entity.create_account(coa_model=coa, code="6301", role=roles.EXPENSE_OTHER, name=_("Zakat"), balance_type="debit", active=True)
entity.create_account(coa_model=coa, code="6302", role=roles.EXPENSE_OTHER, name=_("Taxes"), balance_type="debit", active=True)
entity.create_account(coa_model=coa, code="6303", role=roles.EXPENSE_OTHER, name=_("Foreign Currency Translation"), balance_type="debit", active=True)
entity.create_account(coa_model=coa, code="6304", role=roles.EXPENSE_OTHER, name=_("Interest Expenses"), balance_type="debit", active=True)
# @background
# def create_groups(instance):
# group_names = ["Inventory", "Accountant", "Sales"]
# for group_name in group_names:
# group, _ = Group.objects.get_or_create(name=f"{instance.pk}_{group_name}")
# group_manager,_ = CustomGroup.objects.get_or_create(name=group_name, dealer=instance, group=group)
# group_manager.set_default_permissions()
# instance.user.groups.add(group)
@background
def create_settings(pk):
instance = Dealer.objects.get(pk=pk)
DealerSettings.objects.create(
dealer=instance,
invoice_cash_account=instance.entity.get_all_accounts().filter(role=roles.ASSET_CA_CASH).first(),
invoice_prepaid_account=instance.entity.get_all_accounts().filter(role=roles.ASSET_CA_RECEIVABLES).first(),
invoice_unearned_account=instance.entity.get_all_accounts().filter(role=roles.LIABILITY_CL_DEFERRED_REVENUE).first(),
bill_cash_account=instance.entity.get_all_accounts().filter(role=roles.ASSET_CA_CASH).first(),
bill_prepaid_account=instance.entity.get_all_accounts().filter(role=roles.ASSET_CA_PREPAID).first(),
bill_unearned_account=instance.entity.get_all_accounts().filter(role=roles.LIABILITY_CL_ACC_PAYABLE).first()
)
@background
def create_accounts_for_make(pk):
instance = Dealer.objects.get(pk=pk)
entity = instance.entity
coa = entity.get_default_coa()
for make in CarMake.objects.all():
last_account = entity.get_all_accounts().filter(role=roles.ASSET_CA_RECEIVABLES).order_by('-created').first()
if len(last_account.code) == 4:
code = f"{int(last_account.code)}{1:03d}"
elif len(last_account.code) > 4:
code = f"{int(last_account.code)+1}"
entity.create_account(
name=make.name,
code=code,
role=roles.ASSET_CA_RECEIVABLES,
coa_model=coa,
balance_type="credit",
active=True
)
@background
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)

View File

@ -4,13 +4,15 @@ import json
import logging import logging
import datetime import datetime
import numpy as np import numpy as np
from rich import print # from rich import print
from random import randint from random import randint
from decimal import Decimal from decimal import Decimal
from calendar import month_name from calendar import month_name
from pyzbar.pyzbar import decode from pyzbar.pyzbar import decode
from urllib.parse import urlparse, urlunparse from urllib.parse import urlparse, urlunparse
#####################################################################
from django.db.models.deletion import RestrictedError from django.db.models.deletion import RestrictedError
# Django # Django
@ -66,12 +68,27 @@ from django_ledger.views import (
LedgerModelDeleteView as LedgerModelDeleteViewBase, LedgerModelDeleteView as LedgerModelDeleteViewBase,
LedgerModelCreateView as LedgerModelCreateViewBase LedgerModelCreateView as LedgerModelCreateViewBase
) )
from django_ledger.views.invoice import (
InvoiceModelDetailView as InvoiceModelDetailViewBase,
)
from django_ledger.views import (
LedgerModelListView as LedgerModelListViewBase,
JournalEntryModelTXSDetailView as JournalEntryModelTXSDetailViewBase,
LedgerModelModelActionView as LedgerModelModelActionViewBase,
LedgerModelDeleteView as LedgerModelDeleteViewBase,
LedgerModelCreateView as LedgerModelCreateViewBase
)
from django_ledger.forms.account import AccountModelCreateForm, AccountModelUpdateForm from django_ledger.forms.account import AccountModelCreateForm, AccountModelUpdateForm
from django_ledger.views.entity import ( from django_ledger.views.entity import (
EntityModelDetailBaseView, EntityModelDetailBaseView,
EntityModelDetailHandlerView, EntityModelDetailHandlerView,
) )
from django_ledger.forms.ledger import LedgerModelCreateForm from django_ledger.forms.ledger import LedgerModelCreateForm
from django_ledger.views.entity import (
EntityModelDetailBaseView,
EntityModelDetailHandlerView,
)
from django_ledger.forms.ledger import LedgerModelCreateForm
from django_ledger.forms.item import ( from django_ledger.forms.item import (
ExpenseItemCreateForm, ExpenseItemCreateForm,
ExpenseItemUpdateForm, ExpenseItemUpdateForm,
@ -142,18 +159,20 @@ from .utils import (
get_financial_values, get_financial_values,
get_item_transactions, get_item_transactions,
reserve_car, reserve_car,
send_email, # send_email,
get_user_type, get_user_type,
set_bill_payment, set_bill_payment,
set_invoice_payment, set_invoice_payment,
CarTransfer, CarTransfer,
) )
from .tasks import send_email
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
class Hash(Func): class Hash(Func):
""" """
Represents a function used to compute a hash value. Represents a function used to compute a hash value.
@ -570,7 +589,6 @@ class CarCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
template_name = "inventory/car_form.html" template_name = "inventory/car_form.html"
permission_required = ["inventory.add_car"] permission_required = ["inventory.add_car"]
def get_form(self, form_class=None): def get_form(self, form_class=None):
form = super().get_form(form_class) form = super().get_form(form_class)
dealer = get_user_type(self.request) dealer = get_user_type(self.request)
@ -1012,6 +1030,7 @@ class CarListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
) )
return context return context
def get_queryset(self): def get_queryset(self):
dealer = get_user_type(self.request) dealer = get_user_type(self.request)
qs = super().get_queryset() qs = super().get_queryset()
@ -1048,6 +1067,7 @@ class CarListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
return qs return qs
@login_required @login_required
def inventory_stats_view(request): def inventory_stats_view(request):
""" """
@ -1463,6 +1483,7 @@ class CarTransferCreateView(LoginRequiredMixin, CreateView):
return reverse_lazy("car_detail", kwargs={"pk": self.object.car.pk}) return reverse_lazy("car_detail", kwargs={"pk": self.object.car.pk})
class CarTransferDetailView(LoginRequiredMixin, SuccessMessageMixin, DetailView): class CarTransferDetailView(LoginRequiredMixin, SuccessMessageMixin, DetailView):
""" """
Provides a detailed view of a specific car transfer record. Provides a detailed view of a specific car transfer record.
@ -1493,6 +1514,7 @@ class CarTransferDetailView(LoginRequiredMixin, SuccessMessageMixin, DetailView)
return context return context
@login_required @login_required
def car_transfer_approve(request, car_pk, transfer_pk): def car_transfer_approve(request, car_pk, transfer_pk):
""" """
@ -1786,7 +1808,7 @@ class DealerDetailView(LoginRequiredMixin, DetailView):
return models.Dealer.objects.annotate( return models.Dealer.objects.annotate(
staff_count=Coalesce( staff_count=Coalesce(
Count("staff"), Value(0) Count("staff"), Value(0)
) ) # Get the number of staff members
) )
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):

25
load_initial_data.sh Executable file
View File

@ -0,0 +1,25 @@
#!/bin/bash
echo "Loading initial data"
echo "Loading carmake"
python3 manage.py loaddata --app carmake carmake_backup.json
echo "Loading carmodel"
python3 manage.py loaddata --app carmodel carmodel_backup.json
echo "Loading carserie"
python3 manage.py loaddata --app carserie carserie_backup.json
echo "Loading cartrim"
python3 manage.py loaddata --app cartrim cartrim_backup.json
echo "Loading caroption"
python3 manage.py loaddata --app caroption caroption_backup.json
echo "Loading carequipment"
python3 manage.py loaddata --app carequipment carequipment_backup.json
echo "Populating colors"
python3 manage.py populate_colors
echo "Done"

View File

@ -4,7 +4,6 @@ aiohttp-retry
aiosignal aiosignal
alabaster alabaster
albucore albucore
albumentations
annotated-types annotated-types
anyio anyio
arabic-reshaper arabic-reshaper
@ -32,7 +31,6 @@ cryptography
cycler cycler
Cython Cython
decorator decorator
defusedxml
desert desert
diff-match-patch diff-match-patch
dill dill
@ -83,7 +81,6 @@ docopt
docutils docutils
easy-thumbnails easy-thumbnails
emoji emoji
et_xmlfile
Faker Faker
filelock filelock
fire fire
@ -117,8 +114,6 @@ kiwisolver
lazy_loader lazy_loader
ledger ledger
libretranslatepy libretranslatepy
lmdb
lxml
Markdown Markdown
markdown-it-py markdown-it-py
MarkupSafe MarkupSafe
@ -195,9 +190,6 @@ rfc3986
rich rich
rubicon-objc rubicon-objc
sacremoses sacremoses
scikit-image
scikit-learn
scipy
selenium selenium
sentencepiece sentencepiece
shapely shapely
@ -211,7 +203,6 @@ sqlparse
stanza stanza
stringzilla stringzilla
suds suds
sympy
tablib tablib
termcolor termcolor
threadpoolctl threadpoolctl

68
requirements_dev.txt Normal file
View File

@ -0,0 +1,68 @@
annotated-types==0.7.0
anyio==4.9.0
asgiref==3.8.1
Babel==2.15.0
certifi==2025.1.31
cffi==1.17.1
charset-normalizer==3.4.1
colorama==0.4.6
crispy-bootstrap5==2024.10
cryptography==44.0.2
diff-match-patch==20241021
distro==1.9.0
Django==5.1.7
django-allauth==65.6.0
django-appointment==3.8.0
django-background-tasks==1.2.8
django-bootstrap5==25.1
django-countries==7.6.1
django-crispy-forms==2.3
django-extensions==3.2.3
django-filter==25.1
django-import-export==4.3.7
django-ledger==0.7.6.1
django-next-url-mixin==0.4.0
django-ordered-model==3.7.4
django-phonenumber-field==8.0.0
django-plans==2.0.0
django-sequences==3.0
django-tables2==2.7.5
django-treebeard==4.7.1
djangorestframework==3.15.2
docopt==0.6.2
Faker==37.1.0
fpdf==1.7.2
h11==0.14.0
httpcore==1.0.7
httpx==0.28.1
icalendar==6.1.2
idna==3.10
jiter==0.9.0
jwt==1.3.1
Markdown==3.7
num2words==0.5.14
numpy==2.2.4
ofxtools==0.9.5
openai==1.68.2
opencv-python==4.11.0.86
phonenumbers==8.13.42
pillow==10.4.0
pycparser==2.22
pydantic==2.10.6
pydantic_core==2.27.2
python-dateutil==2.9.0.post0
python-stdnum==1.20
pytz==2025.2
pyvin==0.0.2
pyzbar==0.1.9
requests==2.32.3
six==1.17.0
sniffio==1.3.1
sqlparse==0.5.3
suds==1.2.0
swapper==1.3.0
tablib==3.8.0
tqdm==4.67.1
typing_extensions==4.13.0
tzdata==2025.2
urllib3==2.3.0

View File

@ -1,6 +1,6 @@
from inventory.models import * from inventory.models import *
from django_ledger.models import VendorModel from django_ledger.models import VendorModel
from rich import print # from rich import print
import random import random
import datetime import datetime

View File

@ -16,7 +16,7 @@ from django_ledger.models import (
CustomerModel, CustomerModel,
EntityManagementModel, EntityManagementModel,
) )
from rich import print # from rich import print
from datetime import date from datetime import date
from inventory.models import ( from inventory.models import (
Car, Car,
@ -30,6 +30,7 @@ from inventory.models import (
) )
from inventory.utils import CarFinanceCalculator from inventory.utils import CarFinanceCalculator
from appointment.models import Appointment, AppointmentRequest, Service, StaffMember from appointment.models import Appointment, AppointmentRequest, Service, StaffMember
from appointment.models import Appointment, AppointmentRequest, Service, StaffMember
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django_ledger.io.io_core import get_localdate from django_ledger.io.io_core import get_localdate
from datetime import datetime, timedelta from datetime import datetime, timedelta
@ -42,6 +43,8 @@ User = get_user_model()
load_dotenv(".env") load_dotenv(".env")
def run(): def run():
# print(Service.objects.first().pk) # print(Service.objects.first().pk)
# print(Appointment.objects.first().client) # print(Appointment.objects.first().client)
@ -142,6 +145,9 @@ def run():
# info = item.additional_info["car_info"] # info = item.additional_info["car_info"]
# finance = item.additional_info["car_finance"] # finance = item.additional_info["car_finance"]
# print({"vin":info["make"],"mode":info["model"],"year":info["year"],"trim":info["trim"],"mileage":info["mileage"],"cost_price":finance["cost_price"],"selling_price":finance["selling_price"]}) # print({"vin":info["make"],"mode":info["model"],"year":info["year"],"trim":info["trim"],"mileage":info["mileage"],"cost_price":finance["cost_price"],"selling_price":finance["selling_price"]})
# info = item.additional_info["car_info"]
# finance = item.additional_info["car_finance"]
# print({"vin":info["make"],"mode":info["model"],"year":info["year"],"trim":info["trim"],"mileage":info["mileage"],"cost_price":finance["cost_price"],"selling_price":finance["selling_price"]})
# for account in AccountModel.objects.all(): # for account in AccountModel.objects.all():
# print(account.path) # print(account.path)
@ -175,6 +181,7 @@ def run():
# print(Permission.objects.filter(codename__icontains='customermodel').first().codename) # print(Permission.objects.filter(codename__icontains='customermodel').first().codename)
# print(os.getenv("DJANGO_ALLOWED_HOSTS")) # print(os.getenv("DJANGO_ALLOWED_HOSTS"))
car_makes = CarMake.objects.all()[:10] car_makes = CarMake.objects.all()[:10]
# Fetch the entity and COGS account # Fetch the entity and COGS account
@ -186,6 +193,8 @@ def run():
for make in range(len(car_makes)): # Start from 0 to include all items for make in range(len(car_makes)): # Start from 0 to include all items
# Generate a unique code # Generate a unique code
# Generate a unique code
# Create the account # Create the account
# account = AccountModel.objects.create( # account = AccountModel.objects.create(
# name=car_makes[make].name, # name=car_makes[make].name,
@ -211,10 +220,17 @@ def run():
.order_by("-created") .order_by("-created")
.first() .first()
) )
last_account = (
entity.get_all_accounts()
.filter(role=roles.COGS)
.order_by("-created")
.first()
)
if len(last_account.code) == 4: if len(last_account.code) == 4:
code = f"{int(last_account.code)}{1:03d}" code = f"{int(last_account.code)}{1:03d}"
elif len(last_account.code) > 4: elif len(last_account.code) > 4:
code = f"{int(last_account.code) + 1}" code = f"{int(last_account.code) + 1}"
code = f"{int(last_account.code) + 1}"
# account = entity.create_account( # account = entity.create_account(
# name=car_makes[make].name, # name=car_makes[make].name,
@ -240,12 +256,24 @@ def run():
.order_by("-created") .order_by("-created")
.first() .first()
) )
path = ""
depth=3,
)
# 00060004001S
last_account = (
entity.get_all_accounts()
.filter(role=roles.COGS)
.order_by("-created")
.first()
)
path = "" path = ""
if len(last_account.code) == 12: if len(last_account.code) == 12:
path = f"{int(last_account.path)}{1:03d}" path = f"{int(last_account.path)}{1:03d}"
elif len(last_account.code) > 12: elif len(last_account.code) > 12:
path = f"{int(last_account.path) + 1}" path = f"{int(last_account.path) + 1}"
path = f"{int(last_account.path) + 1}"
# account.path = path # account.path = path
try:
try: try:
account = cogs.add_child(instance=account) account = cogs.add_child(instance=account)
account.move(cogs, pos="sorted-sibling") account.move(cogs, pos="sorted-sibling")
@ -254,6 +282,7 @@ def run():
except Exception as e: except Exception as e:
print(e) print(e)
# form_data = { # form_data = {
# 'name': car_makes[make].name, # 'name': car_makes[make].name,
# 'code': code, # 'code': code,
@ -263,6 +292,7 @@ def run():
# 'coa_model': coa # Ensure the COA model is included # 'coa_model': coa # Ensure the COA model is included
# } # }
# Create the form instance with the data # Create the form instance with the data
# create_form = AccountModelCreateForm(data=form_data, coa_model=coa) # create_form = AccountModelCreateForm(data=form_data, coa_model=coa)
# # Validate and save the form # # Validate and save the form
@ -286,3 +316,26 @@ def run():
# print(f"Account {account.name} created successfully.") # print(f"Account {account.name} created successfully.")
# else: # else:
# print(f"Failed to create account {account.name}. Errors: {form.errors}") # print(f"Failed to create account {account.name}. Errors: {form.errors}")
# create_form = AccountModelCreateForm(data=form_data, coa_model=coa)
# # Validate and save the form
# if create_form.is_valid():
# account = create_form.save(commit=False)
# account.coa_model = coa # Set the entity for the account
# Add the account as a child of the COGS account
# cogs.add_child(instance=account)
# print(f"Account '{account.name}' created successfully.")
# else:
# print(f"Failed to create account. Errors: {create_form.errors}")
# form = AccountModelUpdateForm(instance=account)
# if form.is_valid():
# instance = form.save(commit=False)
# instance._position = "sorted-sibling"
# instance._ref_node_id = cogs.pk
# instance.save()
# print(f"Account {account.name} created successfully.")
# else:
# print(f"Failed to create account {account.name}. Errors: {form.errors}")

View File

@ -8,7 +8,7 @@ from django_ledger.models.invoice import InvoiceModel
from django_ledger.utils import accruable_net_summary from django_ledger.utils import accruable_net_summary
from decimal import Decimal from decimal import Decimal
from django_ledger.models import EstimateModel,EntityModel,ItemModel,ItemTransactionModel,AccountModel,CustomerModel,EntityManagementModel from django_ledger.models import EstimateModel,EntityModel,ItemModel,ItemTransactionModel,AccountModel,CustomerModel,EntityManagementModel
from rich import print # from rich import print
from datetime import date from datetime import date
from inventory.models import Car, Dealer, VatRate,Lead,CarMake,CarModel,Schedule,CustomGroup from inventory.models import Car, Dealer, VatRate,Lead,CarMake,CarModel,Schedule,CustomGroup
from inventory.utils import CarFinanceCalculator from inventory.utils import CarFinanceCalculator
@ -30,19 +30,19 @@ def run():
entity = EntityModel.objects.get(admin__email="ismail.mosa.ibrahim@gmail.com") entity = EntityModel.objects.get(admin__email="ismail.mosa.ibrahim@gmail.com")
coa = entity.get_default_coa() coa = entity.get_default_coa()
cogs = entity.get_default_coa_accounts().filter(role=roles.COGS).first() cogs = entity.get_default_coa_accounts().filter(role=roles.COGS).first()
last_account = entity.get_all_accounts().filter(role=roles.LIABILITY_CL_ACC_PAYABLE).order_by('-created').first() last_account = entity.get_all_accounts().filter(role=roles.LIABILITY_CL_ACC_PAYABLE).order_by('-created').first()
if len(last_account.code) == 4: if len(last_account.code) == 4:
code = f"{int(last_account.code)}{1:03d}" code = f"{int(last_account.code)}{1:03d}"
elif len(last_account.code) > 4: elif len(last_account.code) > 4:
code = f"{int(last_account.code)+1}" code = f"{int(last_account.code)+1}"
print(code) print(code)
# # Loop through car makes and create accounts # # Loop through car makes and create accounts
# for make in range(len(car_makes)): # Start from 0 to include all items # for make in range(len(car_makes)): # Start from 0 to include all items
# # Generate a unique code # # Generate a unique code
# code = f"{cogs.code}{make + 1:03d}" # Example: "COGS-001", "COGS-002", etc. # code = f"{cogs.code}{make + 1:03d}" # Example: "COGS-001", "COGS-002", etc.
# account = entity.create_account( # account = entity.create_account(
# name=car_makes[make].name, # name=car_makes[make].name,
# code=code, # code=code,
@ -50,11 +50,11 @@ def run():
# coa_model=coa, # coa_model=coa,
# balance_type="debit", # balance_type="debit",
# active=True # active=True
# ) # )
# try: # try:
# account = cogs.add_child(instance=account) # account = cogs.add_child(instance=account)
# account.move(cogs, pos="sorted-sibling") # account.move(cogs, pos="sorted-sibling")
# account.refresh_from_db() # account.refresh_from_db()
# account.save() # account.save()
# except Exception as e: # except Exception as e:
@ -67,5 +67,4 @@ def run():
# 'active': True, # 'active': True,
# 'coa_model': coa # Ensure the COA model is included # 'coa_model': coa # Ensure the COA model is included
# } # }

View File

@ -0,0 +1,20 @@
(function () {
const allauth = window.allauth = window.allauth || {}
function manageEmailForm (o) {
const actions = document.getElementsByName('action_remove')
if (actions.length) {
actions[0].addEventListener('click', function (e) {
if (!window.confirm(o.i18n.confirmDelete)) {
e.preventDefault()
}
})
}
}
allauth.account = {
forms: {
manageEmailForm
}
}
})()

View File

@ -0,0 +1,12 @@
(function () {
document.addEventListener('DOMContentLoaded', function () {
Array.from(document.querySelectorAll('script[data-allauth-onload]')).forEach(scriptElt => {
const funcRef = scriptElt.dataset.allauthOnload
if (typeof funcRef === 'string' && funcRef.startsWith('allauth.')) {
const funcArg = JSON.parse(scriptElt.textContent)
const func = funcRef.split('.').reduce((acc, part) => acc && acc[part], window)
func(funcArg)
}
})
})
})()

View File

@ -0,0 +1,43 @@
/*global gettext*/
'use strict';
{
window.addEventListener('load', function() {
// Add anchor tag for Show/Hide link
const fieldsets = document.querySelectorAll('fieldset.collapse');
for (const [i, elem] of fieldsets.entries()) {
// Don't hide if fields in this fieldset have errors
if (elem.querySelectorAll('div.errors, ul.errorlist').length === 0) {
elem.classList.add('collapsed');
const h2 = elem.querySelector('h2');
const link = document.createElement('a');
link.id = 'fieldsetcollapser' + i;
link.className = 'collapse-toggle';
link.href = '#';
link.textContent = gettext('Show');
h2.appendChild(document.createTextNode(' ('));
h2.appendChild(link);
h2.appendChild(document.createTextNode(')'));
}
}
// Add toggle to hide/show anchor tag
const toggleFunc = function(ev) {
if (ev.target.matches('.collapse-toggle')) {
ev.preventDefault();
ev.stopPropagation();
const fieldset = ev.target.closest('fieldset');
if (fieldset.classList.contains('collapsed')) {
// Show
ev.target.textContent = gettext('Hide');
fieldset.classList.remove('collapsed');
} else {
// Hide
ev.target.textContent = gettext('Show');
fieldset.classList.add('collapsed');
}
}
};
document.querySelectorAll('fieldset.module').forEach(function(el) {
el.addEventListener('click', toggleFunc);
});
});
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -39,7 +39,7 @@
<div class="card-body pt-4 pb-0"> <div class="card-body pt-4 pb-0">
<div class="tab-content"> <div class="tab-content">
<div class="tab-pane active" role="tabpanel" aria-labelledby="bootstrap-wizard-validation-tab1" id="bootstrap-wizard-validation-tab1"> <div class="tab-pane active" role="tabpanel" aria-labelledby="bootstrap-wizard-validation-tab1" id="bootstrap-wizard-validation-tab1">
<form class="needs-validation" id="wizardValidationForm1" novalidate="novalidate" data-wizard-form="1"> <form class="needs-validation" id="wizardValidationForm1" novalidate="novalidate" data-wizard-form="1">
{{form1|crispy}} {{form1|crispy}}
</form> </form>
</div> </div>
@ -47,12 +47,12 @@
<form class="needs-validation" id="wizardValidationForm2" novalidate="novalidate" data-wizard-form="2"> <form class="needs-validation" id="wizardValidationForm2" novalidate="novalidate" data-wizard-form="2">
{{form2|crispy}} {{form2|crispy}}
</form> </form>
</div> </div>
<div class="tab-pane" role="tabpanel" aria-labelledby="bootstrap-wizard-validation-tab3" id="bootstrap-wizard-validation-tab3"> <div class="tab-pane" role="tabpanel" aria-labelledby="bootstrap-wizard-validation-tab3" id="bootstrap-wizard-validation-tab3">
<form class="needs-validation" id="wizardValidationForm3" novalidate="novalidate" data-wizard-form="3"> <form class="needs-validation" id="wizardValidationForm3" novalidate="novalidate" data-wizard-form="3">
{{form3|crispy}} {{form3|crispy}}
</form> </form>
</div> </div>
<div class="tab-pane" role="tabpanel" aria-labelledby="bootstrap-wizard-validation-tab4" id="bootstrap-wizard-validation-tab4"> <div class="tab-pane" role="tabpanel" aria-labelledby="bootstrap-wizard-validation-tab4" id="bootstrap-wizard-validation-tab4">
<div class="row flex-center pb-8 pt-4 gx-3 gy-4"> <div class="row flex-center pb-8 pt-4 gx-3 gy-4">
<div class="col-12 col-sm-auto"> <div class="col-12 col-sm-auto">
@ -96,7 +96,7 @@
const validator1 = new JustValidate('#wizardValidationForm2', { const validator1 = new JustValidate('#wizardValidationForm2', {
validateBeforeSubmitting: true, validateBeforeSubmitting: true,
}); });
validator1.addField('#wizardValidationForm2 [name="phone_number"]', [ validator1.addField('#wizardValidationForm2 [name="phone_number"]', [
{ {
rule: 'required', rule: 'required',
@ -131,7 +131,7 @@
rule: 'minLength', rule: 'minLength',
value: 6, value: 6,
}, },
]); ]);
validator.addField('#wizardValidationForm1 [name="confirm_password"]', [ validator.addField('#wizardValidationForm1 [name="confirm_password"]', [
{ {
@ -154,13 +154,13 @@
validator.addField('#wizardValidationForm1 [name="terms"]', [ validator.addField('#wizardValidationForm1 [name="terms"]', [
{ {
rule: 'required', rule: 'required',
}, },
]) ])
/* /*
validator = new JustValidate('#wizardValidationForm1', { validator = new JustValidate('#wizardValidationForm1', {
rules: { rules: {
email: { email: {
required: true, required: true,
email: true, email: true,
@ -198,10 +198,10 @@
const url = "{% url 'account_signup' %}"; const url = "{% url 'account_signup' %}";
let submit_btn = document.getElementById('submit_btn'); let submit_btn = document.getElementById('submit_btn');
const csrftoken = getCookie('csrftoken'); const csrftoken = getCookie('csrftoken');
submit_btn.addEventListener('click', async () => { submit_btn.addEventListener('click', async () => {
const allFormData = getAllFormData(); const allFormData = getAllFormData();
try { try {
showLoading(); showLoading();
const response = await fetch(url, { const response = await fetch(url, {
@ -225,17 +225,17 @@
} catch (error) { } catch (error) {
notify("error",error); notify("error",error);
} }
}); });
function getAllFormData() { function getAllFormData() {
const forms = document.querySelectorAll('form'); const forms = document.querySelectorAll('form');
const formData = {}; const formData = {};
forms.forEach((form, index) => { forms.forEach((form, index) => {
const formId = form.id || `form${index + 1}`; const formId = form.id || `form${index + 1}`;
formData[formId] = {}; formData[formId] = {};
const formElements = form.elements; const formElements = form.elements;
for (let element of formElements) { for (let element of formElements) {
if (element.name) { if (element.name) {
@ -245,7 +245,7 @@
}); });
return formData; return formData;
} }
function showLoading() { function showLoading() {
Swal.fire({ Swal.fire({
title: "{% trans 'Please Wait' %}", title: "{% trans 'Please Wait' %}",
@ -256,17 +256,31 @@
} }
}); });
} }
function hideLoading() { function hideLoading() {
Swal.close(); Swal.close();
} }
function notify(tag,msg){ function notify(tag,msg){
Swal.fire({ Swal.fire({
icon: tag, icon: tag,
titleText: msg titleText: msg
}); });
} }
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== "") {
const cookies = document.cookie.split(";");
for (let cookie of cookies) {
cookie = cookie.trim();
if (cookie.substring(0, name.length + 1) === name + "=") {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
</script> </script>
{% endblock customJS %} {% endblock customJS %}

View File

@ -82,14 +82,10 @@
<div class="my-3"></div> <div class="my-3"></div>
{% include 'footer.html' %} {% include 'footer.html' %}
</div> </div>
</main> </main>
{% block customJS %}
<script src="{% static 'js/djetler.bundle.js' %}"></script> <script src="{% static 'js/djetler.bundle.js' %}"></script>
<script src="{% static 'js/js-utils.js' %}"></script>
<script src="{% static 'js/js-utils.js' %}"></script> <script src="{% static 'js/modal/show_modal.js' %}"></script>
<script src="{% static 'js/modal/show_modal.js' %}"></script>
{% endblock %}
<!-- ===============================================--> <!-- ===============================================-->
<!-- JavaScripts--> <!-- JavaScripts-->
@ -133,5 +129,7 @@
datePickers.forEach(dp => djLedger.getCalendar(dp.attributes.id.value, dateNavigationUrl)) datePickers.forEach(dp => djLedger.getCalendar(dp.attributes.id.value, dateNavigationUrl))
{% endif %} {% endif %}
</script> </script>
{% block customJS %}
{% endblock %}
</body> </body>
</html> </html>

View File

@ -70,6 +70,8 @@
<script src="{% static 'vendors/swiper/swiper-bundle.min.js' %}"></script> <script src="{% static 'vendors/swiper/swiper-bundle.min.js' %}"></script>
<script src="{% static 'vendors/typed.js/typed.umd.js' %}"></script> <script src="{% static 'vendors/typed.js/typed.umd.js' %}"></script>
{% block customJS %}
{% endblock customJS %}
</body> </body>
</html> </html>