This commit is contained in:
ismail 2025-05-07 14:33:59 +03:00
parent b44fb270fa
commit 5dee96ec09
9 changed files with 233 additions and 282 deletions

View File

@ -49,6 +49,7 @@ from .models import (
SaleOrder,
CarMake,
Customer,
Organization,
DealerSettings
)
from django_ledger import models as ledger_models
@ -242,7 +243,7 @@ class CustomerForm(forms.ModelForm):
# image = forms.ImageField(required=False)
class OrganizationForm(CustomerForm):
class OrganizationForm(forms.ModelForm):
"""
Represents a form for collecting and handling organization-specific details.
@ -257,8 +258,10 @@ class OrganizationForm(CustomerForm):
:ivar logo: Optional field to upload the logo of the organization.
:type logo: forms.ImageField
"""
contact_person = forms.CharField(required=False)
logo = forms.ImageField(required=False)
phone_number = SaudiPhoneNumberField(label=_('Phone Number'),required=True)
class Meta:
model = Organization
fields = ["name","arabic_name","email","phone_number","crn","vrn","address","logo"]
class CarForm(

View File

@ -0,0 +1,32 @@
# Generated by Django 5.1.7 on 2025-05-07 09:33
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('django_ledger', '0021_alter_bankaccountmodel_account_model_and_more'),
('inventory', '0007_customer_customer_type'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.RemoveField(
model_name='customer',
name='customer_type',
),
migrations.AddField(
model_name='organization',
name='customer_model',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='django_ledger.customermodel'),
),
migrations.AddField(
model_name='organization',
name='user',
field=models.OneToOneField(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='organization_profile', to=settings.AUTH_USER_MODEL),
preserve_default=False,
),
]

View File

@ -0,0 +1,19 @@
# Generated by Django 5.1.7 on 2025-05-07 09:44
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0008_remove_customer_customer_type_and_more'),
]
operations = [
migrations.AddField(
model_name='organization',
name='email',
field=models.EmailField(default='t@tenhal.sa', max_length=254, verbose_name='Email'),
preserve_default=False,
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 5.1.7 on 2025-05-07 09:46
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0009_organization_email'),
]
operations = [
migrations.AddField(
model_name='organization',
name='active',
field=models.BooleanField(default=True, verbose_name='Active'),
),
]

View File

@ -1069,10 +1069,6 @@ class Customer(models.Model):
image = models.ImageField(
upload_to="customers/", blank=True, null=True, verbose_name=_("Image")
)
customer_type = models.CharField(
choices=[("customer", _("Customer")),("organization", _("Organization"))], default="customer", max_length=15, verbose_name=_("Customer Type"),
null=True,blank=True
)
created = models.DateTimeField(auto_now_add=True, verbose_name=_("Created"))
updated = models.DateTimeField(auto_now=True, verbose_name=_("Updated"))
@ -1101,7 +1097,6 @@ class Customer(models.Model):
)
try:
customer.additional_info.update({"customer_info": customer_dict})
customer.additional_info.update({"type": "customer"})
except Exception:
pass
customer.save()
@ -1123,7 +1118,6 @@ class Customer(models.Model):
customer.email = self.email
try:
customer.additional_info.update({"customer_info": customer_dict})
customer.additional_info.update({"type": "customer"})
except Exception:
pass
customer.save()
@ -1139,17 +1133,29 @@ class Customer(models.Model):
user.set_password("Tenhal@123")
user.save()
return user
def deactivate_account(self):
self.active = False
self.customer_model.active = False
self.user.is_active = False
self.customer_model.save()
self.user.save()
self.save()
class Organization(models.Model, LocalizedNameMixin):
dealer = models.ForeignKey(
Dealer, on_delete=models.CASCADE, related_name="organizations"
)
customer_model = models.ForeignKey(
CustomerModel, on_delete=models.SET_NULL, null=True
)
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='organization_profile')
name = models.CharField(max_length=255, verbose_name=_("Name"))
arabic_name = models.CharField(max_length=255, verbose_name=_("Arabic Name"))
crn = models.CharField(
max_length=15, verbose_name=_("Commercial Registration Number")
)
vrn = models.CharField(max_length=15, verbose_name=_("VAT Registration Number"))
email = models.EmailField(verbose_name=_("Email"))
phone_number = PhoneNumberField(region="SA", verbose_name=_("Phone Number"))
address = models.CharField(
max_length=200, blank=True, null=True, verbose_name=_("Address")
@ -1157,6 +1163,7 @@ class Organization(models.Model, LocalizedNameMixin):
logo = models.ImageField(
upload_to="logos", blank=True, null=True, verbose_name=_("Logo")
)
active = models.BooleanField(default=True, verbose_name=_("Active"))
created = models.DateTimeField(auto_now_add=True, verbose_name=_("Created"))
updated = models.DateTimeField(auto_now=True, verbose_name=_("Updated"))
@ -1166,7 +1173,61 @@ class Organization(models.Model, LocalizedNameMixin):
def __str__(self):
return self.name
def create_customer_model(self):
customer_dict = to_dict(self)
customer = self.dealer.entity.create_customer(
commit=False,
customer_model_kwargs={
"customer_name": self.name,
"address_1": self.address,
"phone": self.phone_number,
"email": self.email,
},
)
try:
customer.additional_info.update({"customer_info": customer_dict})
except Exception:
pass
customer.save()
return customer
def update_user_model(self):
user = self.user
user.first_name = self.name
user.email = self.email
user.save()
return user
def update_customer_model(self):
customer_dict = to_dict(self)
customer = self.customer_model
customer.customer_name = self.name
customer.address_1 = self.address
customer.phone = self.phone_number
customer.email = self.email
try:
customer.additional_info.update({"customer_info": customer_dict})
except Exception:
pass
customer.save()
return customer
def create_user_model(self):
user = User.objects.create_user(
username=self.email,
email=self.email,
first_name=self.name,
)
user.set_password("Tenhal@123")
user.save()
return user
def deactivate_account(self):
self.active = False
self.user.is_active = False
self.customer_model.active = False
self.user.save()
self.customer_model.save()
self.save()
class Representative(models.Model, LocalizedNameMixin):
dealer = models.ForeignKey(

View File

@ -374,7 +374,7 @@ path(
"organizations/", views.OrganizationListView.as_view(), name="organization_list"
),
path(
"organizations/<uuid:pk>/",
"organizations/<int:pk>/",
views.OrganizationDetailView.as_view(),
name="organization_detail",
),
@ -384,12 +384,12 @@ path(
name="organization_create",
),
path(
"organizations/<uuid:pk>/update/",
views.OrganizationUpdateView,
"organizations/<int:pk>/update/",
views.OrganizationUpdateView.as_view(),
name="organization_update",
),
path(
"organizations/<uuid:pk>/delete/",
"organizations/<int:pk>/delete/",
views.OrganizationDeleteView,
name="organization_delete",
),

View File

@ -1895,7 +1895,7 @@ class CustomerListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
def get_queryset(self):
query = self.request.GET.get("q")
dealer = get_user_type(self.request)
customers = dealer.customers.all()
customers = dealer.customers.filter(active=True)
return apply_search_filters(customers, query)
def get_context_data(self, **kwargs):
@ -2017,6 +2017,18 @@ def add_activity_to_customer(request, pk):
class CustomerCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
"""
# Handles the creation of a new customer within the system. This view ensures that proper permissions
# and request methods are utilized. It provides feedback to the user about the success or failure of
# the customer creation process. When the form is submitted and valid, it checks for duplicate
# customers based on the email provided before proceeding with the customer creation.
# :param request: The HTTP request object containing metadata about the request initiated by the user.
# :type request: HttpRequest
# :return: The rendered form page or a redirect to the customer list page upon successful creation.
# :rtype: HttpResponse
# :raises PermissionDenied: If the user does not have the required permissions to access the view.
# """
model = models.Customer
form_class = forms.CustomerForm
permission_required = ["django_ledger.add_customermodel"]
@ -2035,85 +2047,8 @@ class CustomerCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView
return super().form_valid(form)
# @login_required
# @permission_required("django_ledger.add_customermodel", raise_exception=True)
# def CustomerCreateView(request):
# """
# Handles the creation of a new customer within the system. This view ensures that proper permissions
# and request methods are utilized. It provides feedback to the user about the success or failure of
# the customer creation process. When the form is submitted and valid, it checks for duplicate
# customers based on the email provided before proceeding with the customer creation.
# :param request: The HTTP request object containing metadata about the request initiated by the user.
# :type request: HttpRequest
# :return: The rendered form page or a redirect to the customer list page upon successful creation.
# :rtype: HttpResponse
# :raises PermissionDenied: If the user does not have the required permissions to access the view.
# """
# form = forms.CustomerForm()
# if request.method == "POST":
# form = forms.CustomerForm(request.POST)
# dealer = get_user_type(request)
# if form.is_valid():
# if (
# dealer.entity.get_customers()
# .filter(email=form.cleaned_data["email"])
# .exists()
# ):
# messages.error(request, _("Customer with this email already exists"))
# else:
# customer_name = (
# f"{form.cleaned_data['first_name']} "
# f"{form.cleaned_data['last_name']}"
# )
# customer_dict = {
# x: request.POST[x]
# for x in request.POST
# if x != "csrfmiddlewaretoken"
# }
# try:
# customer = dealer.entity.create_customer(
# commit=False,
# customer_model_kwargs={
# "customer_name": customer_name,
# "address_1": form.cleaned_data["address"],
# "phone": form.cleaned_data["phone_number"],
# "email": form.cleaned_data["email"],
# },
# )
# customer.additional_info.update({"customer_info": customer_dict})
# customer.additional_info.update({"type": "customer"})
# customer.save()
# messages.success(request, _("Customer created successfully"))
# return redirect("customer_list")
# except Exception as e:
# messages.error(request, _(f"An error occurred: {str(e)}"))
# else:
# messages.error(request, _("Please correct the errors below"))
# return render(request, "customers/customer_form.html", {"form": form})
class CustomerUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
model = models.Customer
form_class = forms.CustomerForm
permission_required = ["django_ledger.change_customermodel"]
template_name = "customers/customer_form.html"
success_url = reverse_lazy("customer_list")
success_message = "Customer updated successfully"
def form_valid(self, form):
form.instance.update_user_model()
form.instance.update_customer_model()
return super().form_valid(form)
# @login_required
# @permission_required("django_ledger.change_customermodel", raise_exception=True)
# def CustomerUpdateView(request, pk):
# """
"""
# Updates the details of an existing customer in the database. This view is
# accessible only to logged-in users with the appropriate permissions. It
# handles both GET (form rendering with pre-filled customer data) and POST
@ -2135,44 +2070,17 @@ class CustomerUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView
# returns the rendered form template with the validation errors.
# :rtype: HttpResponse
# """
# customer = get_object_or_404(CustomerModel, pk=pk)
# if request.method == "POST":
# # form = forms.CustomerForm(request.POST, instance=customer)
# customer_dict = {
# x: request.POST[x] for x in request.POST if x != "csrfmiddlewaretoken"
# }
# dealer = get_user_type(request)
# customer_name = customer_dict["first_name"] + " " + customer_dict["last_name"]
model = models.Customer
form_class = forms.CustomerForm
permission_required = ["django_ledger.change_customermodel"]
template_name = "customers/customer_form.html"
success_url = reverse_lazy("customer_list")
success_message = "Customer updated successfully"
# instance = dealer.entity.get_customers().get(pk=pk)
# instance.customer_name = customer_name
# instance.address_1 = customer_dict["address"]
# instance.phone = customer_dict["phone_number"]
# instance.email = customer_dict["email"]
# customer_dict["pk"] = str(instance.pk)
# instance.additional_info.update({"customer_info": customer_dict})
# try:
# user = User.objects.filter(
# pk=int(instance.additional_info["user_info"]["id"])
# ).first()
# if user:
# user.username = customer_dict["email"]
# user.email = customer_dict["email"]
# user.save()
# except Exception as e:
# raise Exception(e)
# instance.save()
# messages.success(request, _("Customer updated successfully"))
# return redirect("customer_list")
# else:
# form = forms.CustomerForm(
# initial=customer.additional_info["customer_info"]
# if "customer_info" in customer.additional_info
# else {}
# )
# return render(request, "customers/customer_form.html", {"form": form})
def form_valid(self, form):
form.instance.update_user_model()
form.instance.update_customer_model()
return super().form_valid(form)
@login_required
@ -2193,15 +2101,8 @@ def delete_customer(request, pk):
:rtype: HttpResponseRedirect
"""
customer = get_object_or_404(models.Customer, pk=pk)
customer_model = customer.customer_model
user = customer.user
customer.active = False
customer_model.active = False
user.is_active = False
customer.save()
user.save()
messages.success(request, _("Customer deleted successfully"))
customer.deactivate_account()
messages.success(request, _("Customer deactivated successfully"))
return redirect("customer_list")
@ -2371,8 +2272,9 @@ def delete_vendor(request, pk):
:rtype: HttpResponseRedirect
"""
vendor = get_object_or_404(models.Vendor, pk=pk)
# vendor.active = False
vendor.delete()
vendor.active = False
vendor.vendor_model.active = False
vendor.save()
messages.success(request, _("Vendor deleted successfully"))
return redirect("vendor_list")
@ -2832,7 +2734,7 @@ class OrganizationListView(LoginRequiredMixin, ListView):
:ivar paginate_by: The number of organizations displayed per page.
:type paginate_by: int
"""
model = CustomerModel
model = models.Organization
template_name = "organizations/organization_list.html"
context_object_name = "organizations"
paginate_by = 10
@ -2840,9 +2742,7 @@ class OrganizationListView(LoginRequiredMixin, ListView):
def get_queryset(self):
query = self.request.GET.get("q")
dealer = get_user_type(self.request)
organization = dealer.entity.get_customers().filter(
additional_info__type="organization", active=True
)
organization = dealer.organizations.filter(active=True)
return apply_search_filters(organization, query)
@ -2865,32 +2765,13 @@ class OrganizationDetailView(LoginRequiredMixin, DetailView):
template for accessing the organization's data.
:type context_object_name: str
"""
model = CustomerModel
model = models.Organization
template_name = "organizations/organization_detail.html"
context_object_name = "organization"
class OrganizationCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
model = models.Organization
form_class = forms.OrganizationForm
permission_required = ["django_ledger.add_customermodel"]
template_name = "customers/organization_form.html"
success_url = reverse_lazy("organization_list")
success_message = "Customer created successfully"
def form_valid(self, form):
dealer = get_user_type(self.request)
form.instance.dealer = dealer
user = form.instance.create_user_model()
customer = form.instance.create_customer_model()
form.instance.customer_type = 'organization'
form.instance.user = user
form.instance.customer_model = customer
return super().form_valid(form)
# @login_required
# def OrganizationCreateView(request):
# """
"""
# Handles the creation of a new organization via a web form. This view allows the
# authenticated user to submit data for creating an organization. If a POST request
# is received, it validates the data, checks for duplicate organizations, and
@ -2904,110 +2785,52 @@ class OrganizationCreateView(LoginRequiredMixin, PermissionRequiredMixin, Create
# redirecting the user after a successful creation.
# :rtype: HttpResponse
# """
# if request.method == "POST":
# form = forms.OrganizationForm(request.POST)
# if CustomerModel.objects.filter(email=request.POST["email"]).exists():
# messages.error(
# request, _("An organization with this email already exists.")
# )
# return redirect("organization_create")
model = models.Organization
form_class = forms.OrganizationForm
permission_required = ["django_ledger.add_customermodel"]
template_name = "organizations/organization_form.html"
success_url = reverse_lazy("organization_list")
success_message = "Organization created successfully"
# organization_dict = {
# x: request.POST[x] for x in request.POST if x != "csrfmiddlewaretoken"
# }
# dealer = get_user_type(request)
# name = organization_dict["first_name"] + " " + organization_dict["last_name"]
# customer = dealer.entity.create_customer(
# commit=False,
# customer_model_kwargs={
# "customer_name": name,
# "address_1": organization_dict["address"],
# "phone": organization_dict["phone_number"],
# "email": organization_dict["email"],
# },
# )
# image = request.FILES.get("logo")
# if image:
# file_name = default_storage.save("images/{}".format(image.name), image)
# file_url = default_storage.url(file_name)
def form_valid(self, form):
dealer = get_user_type(self.request)
form.instance.dealer = dealer
user = form.instance.create_user_model()
customer = form.instance.create_customer_model()
form.instance.user = user
form.instance.customer_model = customer
# organization_dict["logo"] = file_url
# organization_dict["pk"] = str(customer.pk)
# customer.additional_info.update({"customer_info": organization_dict})
# customer.additional_info.update({"type": "organization"})
# customer.save()
# messages.success(request, _("Organization created successfully"))
# return redirect("organization_list")
# else:
# form = forms.OrganizationForm()
# return render(request, "organizations/organization_form.html", {"form": form})
return super().form_valid(form)
@login_required
def OrganizationUpdateView(request, pk):
class OrganizationUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
"""
Handles the update of an organization instance. This view fetches the organization
based on the provided primary key (pk) and renders a form for editing the
organization attributes. When a POST request is made, this view validates and
processes the form data, updates the organization instance, and saves the changes.
If the request method is not POST, it initializes the form with existing organization
data for rendering.
# Handles the update of an organization instance. This view fetches the organization
# based on the provided primary key (pk) and renders a form for editing the
# organization attributes. When a POST request is made, this view validates and
# processes the form data, updates the organization instance, and saves the changes.
# If the request method is not POST, it initializes the form with existing organization
# data for rendering.
:param request: The HTTP request object. Must be authenticated via login.
:type request: HttpRequest
:param pk: The primary key of the organization to be updated.
:type pk: int
:return: An HTTP response object. Either renders the organization form or redirects
to the organization list upon successful update.
:rtype: HttpResponse
"""
organization = get_object_or_404(CustomerModel, pk=pk)
if request.method == "POST":
form = forms.OrganizationForm(request.POST)
# :param request: The HTTP request object. Must be authenticated via login.
# :type request: HttpRequest
# :param pk: The primary key of the organization to be updated.
# :type pk: int
# :return: An HTTP response object. Either renders the organization form or redirects
# to the organization list upon successful update.
# :rtype: HttpResponse
# """
model = models.Organization
form_class = forms.OrganizationForm
permission_required = ["django_ledger.change_customermodel"]
template_name = "organizations/organization_form.html"
success_url = reverse_lazy("organization_list")
success_message = "Organization updated successfully"
organization_dict = {
x: request.POST[x] for x in request.POST if x != "csrfmiddlewaretoken"
}
dealer = get_user_type(request)
def form_valid(self, form):
form.instance.update_user_model()
form.instance.update_customer_model()
return super().form_valid(form)
instance = dealer.entity.get_customers().get(
pk=organization.additional_info["customer_info"]["pk"]
)
name = organization_dict["first_name"] + " " + organization_dict["last_name"]
instance.customer_name = name
instance.address_1 = organization_dict["address"]
instance.phone = organization_dict["phone_number"]
instance.email = organization_dict["email"]
image = request.FILES.get("logo")
if image:
file_name = default_storage.save("images/{}".format(image.name), image)
file_url = default_storage.url(file_name)
organization_dict["logo"] = file_url
else:
organization_dict["logo"] = organization.additional_info["customer_info"][
"logo"
]
organization_dict["pk"] = str(instance.pk)
instance.additional_info["customer_info"] = organization_dict
instance.additional_info["type"] = "organization"
instance.save()
messages.success(request, _("Organization created successfully"))
return redirect("organization_list")
else:
form = forms.OrganizationForm(
initial=organization.additional_info["customer_info"] or {}
)
# form.fields.pop("logo", None)
return render(request, "organizations/organization_form.html", {"form": form})
# class OrganizationDeleteView(LoginRequiredMixin, SuccessMessageMixin, DeleteView):
# model = models.Organization
# template_name = "organizations/organization_confirm_delete.html"
# success_url = reverse_lazy("organization_list")
# success_message = "Organization deleted successfully."
@login_required
def OrganizationDeleteView(request, pk):
"""
@ -3023,14 +2846,9 @@ def OrganizationDeleteView(request, pk):
:return: An HTTP response redirecting to the organization list view.
:rtype: HttpResponseRedirect
"""
organization = get_object_or_404(CustomerModel, pk=pk)
try:
User.objects.get(email=organization.email).delete()
organization.delete()
messages.success(request, _("Organization deleted successfully"))
except Exception as e:
print("unable to delete user", e)
messages.error(request, _("Unable to delete organization"))
organization = get_object_or_404(models.Organization, pk=pk)
organization.deactivate_account()
messages.success(request, _("Organization Deactivated successfully"))
return redirect("organization_list")

View File

@ -5,10 +5,10 @@
<div class="row my-4">
<h2>{{ organization.get_local_name }}</h2>
<ul class="list-group mb-4">
<li class="list-group-item"><strong>{% trans "CRN" %}:</strong> {{ organization.additional_info.customer_info.crn }}</li>
<li class="list-group-item"><strong>{% trans "VRN" %}:</strong> {{ organization.additional_info.customer_info.vrn }}</li>
<li class="list-group-item"><strong>{% trans "Phone" %}:</strong> {{ organization.additional_info.customer_info.phone_number }}</li>
<li class="list-group-item"><strong>{% trans "Address" %}:</strong> {{ organization.additional_info.customer_info.address }}</li>
<li class="list-group-item"><strong>{% trans "CRN" %}:</strong> {{ organization.crn }}</li>
<li class="list-group-item"><strong>{% trans "VRN" %}:</strong> {{ organization.vrn }}</li>
<li class="list-group-item"><strong>{% trans "Phone" %}:</strong> {{ organization.phone_number }}</li>
<li class="list-group-item"><strong>{% trans "Address" %}:</strong> {{ organization.address }}</li>
</ul>
<div class="d-flex">
<a href="{% url 'organization_update' organization.pk %}" class="btn btn-sm btn-warning me-2">{% trans "Edit" %}</a>

View File

@ -102,26 +102,26 @@
<td class="name align-middle white-space-nowrap ps-0">
<div class="d-flex align-items-center">
<div>
<a class="fs-8 fw-bold" href="{% url 'organization_detail' org.pk %}">{{ org.customer_name }}</a>
<a class="fs-8 fw-bold" href="{% url 'organization_detail' org.pk %}">{{ org.name }}</a>
<div class="d-flex align-items-center">
<p class="mb-0 text-body-highlight fw-semibold fs-9 me-2"></p><span class="badge badge-phoenix badge-phoenix-primary">{{ org.customer_name }}</span>
<p class="mb-0 text-body-highlight fw-semibold fs-9 me-2"></p><span class="badge badge-phoenix badge-phoenix-primary">{{ org.name }}</span>
</div>
</div>
</div>
</td>
<td class="email align-middle white-space-nowrap fw-semibold ps-4 border-end border-translucent">{{ org.additional_info.customer_info.crn }}</td>
<td class="phone align-middle white-space-nowrap fw-semibold ps-4 border-end border-translucent">{{ org.additional_info.customer_info.vrn }}</td>
<td class="email align-middle white-space-nowrap fw-semibold ps-4 border-end border-translucent">{{ org.crn }}</td>
<td class="phone align-middle white-space-nowrap fw-semibold ps-4 border-end border-translucent">{{ org.vrn }}</td>
<td class="phone align-middle white-space-nowrap ps-4 border-end border-translucent fw-semibold text-body-highlight">
<a class="text-body-highlight" href="tel:{{ org.phone }}">{{ org.phone }}</a>
<a class="text-body-highlight" href="tel:{{ org.phone }}">{{ org.phone_number }}</a>
</td>
<td class="company align-middle white-space-nowrap text-body-tertiary text-opacity-85 ps-4 border-end border-translucent fw-semibold text-body-highlight">{{ org.address_1 }}</td>
<td class="company align-middle white-space-nowrap text-body-tertiary text-opacity-85 ps-4 border-end border-translucent fw-semibold text-body-highlight">{{ org.address }}</td>
<td class="date align-middle white-space-nowrap text-body-tertiary text-opacity-85 ps-4 text-body-tertiary">{{ org.created|date }}</td>
<td class="align-middle white-space-nowrap text-end pe-0 ps-4">
{% if perms.django_ledger.change_customermodel %}
<div class="btn-reveal-trigger position-static">
<button class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10" type="button" data-bs-toggle="dropdown" data-boundary="window" aria-haspopup="true" aria-expanded="false" data-bs-reference="parent"><span class="fas fa-ellipsis-h fs-10"></span></button>
<div class="dropdown-menu dropdown-menu-end py-2">
<a href="{% url 'organization_update' org.pk %}" class="dropdown-item text-success-dark">{% trans 'Edit' %}</a>
<div class="dropdown-menu dropdown-menu-end py-2">
<a href="{% url 'organization_update' org.pk %}" class="dropdown-item text-success-dark">{% trans 'Edit' %}</a>
{% if perms.django_ledger.delete_customermodel %}
<div class="dropdown-divider"></div><button class="dropdown-item text-danger" data-bs-toggle="modal" data-bs-target="#deleteModal">{% trans 'Delete' %}</button>
{% endif %}