Po upload update signals #84

Merged
ismail merged 21 commits from frontend into main 2025-06-26 19:11:12 +03:00
18 changed files with 96 additions and 77 deletions

View File

@ -13,6 +13,7 @@ from django_ledger.models import (
TransactionModel,
LedgerModel,
AccountModel,
PurchaseOrderModel
)
from . import models
from django.utils.timezone import now
@ -892,3 +893,10 @@ def update_finance_cost(sender, instance, created, **kwargs):
# save_journal(instance,ledger,vendor)
# else:
# save_journal(instance,ledger,vendor)
@receiver(post_save, sender=PurchaseOrderModel)
def create_po_item_upload(sender,instance,created,**kwargs):
if instance.po_status == "fulfilled":
for item in instance.get_itemtxs_data()[0]:
dealer = models.Dealer.objects.get(entity=instance.entity)
models.PoItemsUploaded.objects.create(dealer=dealer,po=instance, item=item, status="fulfilled")

View File

@ -9,7 +9,7 @@ from django.conf.urls import handler403, handler400, handler404, handler500
urlpatterns = [
# main URLs
path("", views.HomeView.as_view(), name="home"),
# path("<slug:dealer_slug>/", views.HomeView.as_view(), name="home"),
path("<slug:dealer_slug>/", views.HomeView.as_view(), name="home"),
path("welcome/", views.WelcomeView.as_view(), name="welcome"),
# Accounts URLs
# path("login/", allauth_views.LoginView.as_view(template_name="account/login.html"), name="account_login"),

View File

@ -1573,12 +1573,25 @@ class CarDeleteView(
model = models.Car
template_name = "inventory/car_confirm_delete.html"
success_url = reverse_lazy("inventory_stats")
permission_required = ["inventory.delete_car"]
def delete(self, request, *args, **kwargs):
messages.success(request, _("Car deleted successfully"))
return super().delete(request, *args, **kwargs)
def get_success_url(self):
"""
Returns the URL to redirect to after a successful car deletion.
It dynamically includes the dealer_slug from the URL.
"""
dealer_slug = self.kwargs.get('dealer_slug')
if dealer_slug:
return reverse_lazy("car_list", kwargs={'dealer_slug': dealer_slug})
else:
messages.error(self.request, _("Could not determine dealer for redirection."))
return reverse_lazy("home")
class CarLocationCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
@ -9522,13 +9535,7 @@ class PurchaseOrderMarkAsApprovedView(BasePurchaseOrderActionActionView):
class PurchaseOrderMarkAsFulfilledView(BasePurchaseOrderActionActionView):
action_name = "mark_as_fulfilled"
def get(self, request, dealer_slug, entity_slug, po_pk, *args, **kwargs):
po = get_object_or_404(PurchaseOrderModel, pk=po_pk)
for item in po.get_itemtxs_data()[0]:
models.PoItemsUploaded.objects.create(po=po, item=item, status="fulfilled")
return super().get(request, dealer_slug, entity_slug, po_pk, *args, **kwargs)
class PurchaseOrderMarkAsCanceledView(BasePurchaseOrderActionActionView):
action_name = "mark_as_canceled"

View File

@ -25,7 +25,7 @@
{% block content %}
<div class="container-fluid">
<h1>{% if object %}{{ _("Update") }}{% else %}{{ _("Create") }}{% endif %}</h1>
<h1>{% if object %}{{ _("Update Lead") }}{% else %}{{ _("Create New Lead") }}{% endif %}</h1>
<div class="row mb-3">
<div class="col-sm-6 col-md-8">

View File

@ -77,7 +77,7 @@
<div class="kanban-column bg-body">
<div class="kanban-header opacity-75"><span class="text-body">{{ _("New Leads")}} ({{new|length}})</span></div>
{% for lead in new %}
<a href="{% url 'lead_detail' lead.slug %}">
<a href="{% url 'lead_detail' request.dealer.slug lead.slug %}">
<div class="lead-card">
<strong>{{lead.full_name|capfirst}}</strong><br>
<small>{{lead.email}}</small><br>

View File

@ -13,7 +13,7 @@
<ul class="dropdown-menu dropdown-menu-end p-0" style="z-index: 9999;">
<li>
{% if opportunity.estimate %}
<a class="dropdown-item" href="{% url 'estimate_detail' opportunity.estimate.pk %}">{{ _("View Quotation")}}</a>
<a class="dropdown-item" href="{% url 'estimate_detail' request.dealer.slug opportunity.estimate.pk %}">{{ _("View Quotation")}}</a>
{% else %}
<a class="dropdown-item" href="{% url 'estimate_create_from_opportunity' request.dealer.slug opportunity.slug %}">{{ _("Create Quotation")}}</a>
{% endif %}
@ -104,7 +104,7 @@
<h5 class="mb-0 text-body-highlight me-2">{{ _("Estimate") }}</h5>
</div>
{% if opportunity.estimate %}
<a class="dropdown-item" href="{% url 'estimate_detail' opportunity.estimate.pk %}">{{ _("View Quotation")}}</a>
<a class="dropdown-item" href="{% url 'estimate_detail' request.dealer.slug opportunity.estimate.pk %}">{{ _("View Quotation")}}</a>
{% else %}
<p>{{ _("No Estimate") }}</p>
{% endif %}

View File

@ -119,7 +119,7 @@
</div>
<div class="d-flex gap-2">
<a class="btn btn-sm btn-phoenix-primary" href="{% url 'opportunity_detail' request.dealer.slug opportunity.slug %}">
<a class="btn btn-sm btn-phoenix-primary" href="{% url 'opportunity_detail' request.dealer.slug opportunity.slug %}">
{{ _("View Details") }} <i class="fa-solid fa-eye ms-2"></i>
</a>
<a class="btn btn-sm btn-phoenix-success" href="{% url 'update_opportunity' request.dealer.slug opportunity.slug %}">

View File

@ -109,7 +109,11 @@
{{ _("Delete") }}
</a>
<a class="btn btn-sm btn-phoenix-secondary"
<<<<<<< HEAD
href="{% url 'group_list' request.dealer.slug%}">
=======
href="{% url 'group_list' request.dealer.slug %}">
>>>>>>> c9fad7b79c346875a636122fdc7514814180dbc7
<i class="fa-solid fa-arrow-left"></i>
{% trans "Back to List" %}
</a>

View File

@ -71,7 +71,7 @@
<li class="nav-item">
<a class="nav-link" href="{% url 'estimate_create' request.dealer.slug %}">
<div class="d-flex align-items-center">
<span class="nav-link-icon"><span class="fas fa-list-ul"></span></span><span class="nav-link-text">{% trans "create quotation"|capfirst %}</span>
<span class="nav-link-icon"><span class="fas fa-handshake"></span></span><span class="nav-link-text">{% trans "create quotation"|capfirst %}</span>
</div>
</a>
</li>
@ -80,12 +80,20 @@
<li class="nav-item">
<a class="nav-link" href="{% url 'estimate_list' request.dealer.slug %}">
<div class="d-flex align-items-center">
<span class="nav-link-icon"><span class="fas fa-clipboard-list"></span></span><span class="nav-link-text">{% trans "quotations"|capfirst %}</span>
<span class="nav-link-icon"><span class="fas fa-handshake"></span></span><span class="nav-link-text">{% trans "quotations"|capfirst %}</span>
</div>
</a>
</li>
{% endif %}
<li class="nav-item">
<a class="nav-link" href="{% url 'sales_list' request.dealer.slug %}">
<div class="d-flex align-items-center">
<span class="nav-link-icon"><span class="fas fa-money-check"></span></span><span class="nav-link-text">{% trans "Sales Orders"|capfirst %}</span>
</div>
</a>
</li>
{% if perms.django_ledger.view_invoicemodel %}
<li class="nav-item">
<a class="nav-link" href="{% url 'invoice_list' request.dealer.slug %}">
@ -104,13 +112,7 @@
</a>
</li>
{% endif %}
<li class="nav-item">
<a class="nav-link" href="{% url 'sales_list' request.dealer.slug %}">
<div class="d-flex align-items-center">
<span class="nav-link-icon"><span class="fas fa-money-check"></span></span><span class="nav-link-text">{% trans "Sales Orders"|capfirst %}</span>
</div>
</a>
</li>
</ul>
</div>
</div>
@ -470,7 +472,7 @@
<div class="my-2 text-center fw-bold fs-10 text-body-quaternary">
<a class="text-body-quaternary me-1" href="">Privacy policy</a>&bull;<a class="text-body-quaternary mx-1" href="">Terms</a>&bull;<a class="text-body-quaternary ms-1" href="">Cookies</a>
</div>
{% else %}
{% else %}
<div class="px-3">
<a class="btn btn-phoenix-success d-flex flex-center w-100" href="{% url 'account_login' %}"> <span class="me-2" data-feather="log-in"> </span>{% trans 'Sign In' %}</a>
</div>

View File

@ -3,11 +3,13 @@
{% load i18n %}
{% block title %}Delete Car{% endblock %}
{% block content %}
<div class="mt-4 ms-4">
<h1>Delete Car</h1>
<p>Are you sure you want to delete the car "{{ car }}"?</p>
<p class="text-danger">Are you sure you want to delete the car "{{ car }}"?</p>
<form method="post">
{% csrf_token %}
<button type="submit" class="btn btn-phoenix-danger">Confirm Delete</button>
<a href="{% url 'car_list' request.dealer.slug %}" class="btn btn-phoenix-secondary">{% trans 'Cancel' %}</a>
</form>
</div>
{% endblock %}

View File

@ -305,7 +305,7 @@
</div>
</div>
</div>
</div>
{% endblock %}
{% block customJS %}

View File

@ -99,7 +99,7 @@
<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 class="dropdown-item" href="{% url 'payment_details' request.dealer.slug tx.journal_entry.pk %}">{% trans 'view'|capfirst %}</a>
<a class="dropdown-item text-success-dark" href="{% url 'payment_details' request.dealer.slug tx.journal_entry.pk %}">{% trans 'view Transactions'|capfirst %}</a>
</div>
</div>
</td>

View File

@ -39,7 +39,7 @@
<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 'account_detail' request.dealer.slug account.uuid %}" class="dropdown-item text-success-dark">
{% trans "View" %}
{% trans "View Journal Entries" %}
</a>
<div class="dropdown-divider"></div>
<button class="dropdown-item text-danger" data-bs-toggle="modal" data-bs-target="#deleteModal">{% trans "Delete" %}</button>

View File

@ -12,7 +12,16 @@
{% block content %}
<div class="container-fluid">
<h3>{% trans "Add Organization" %}</h3>
<!--Heading-->
<h3>
{% if object %}
{% trans 'Update Organization'%}
{% else %}
{% trans 'Add New Organization'%}
{% endif %}
</h3>
<!--form body-->
<div class="row mb-3">
<div class="col-sm-6 col-md-8">
<form class="form" method="post" enctype="multipart/form-data">

View File

@ -75,7 +75,7 @@
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="deleteModalLabel">
{% trans 'Delete Vendor' %}
{% trans 'Delete Organization' %}
<span data-feather="alert-circle"></span>
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>

View File

@ -10,14 +10,12 @@
<div class="col-lg-12">
<div class="d-flex flex-column gap-3">
<!-- PO Card -->
<div class="card">
<div class="card-body">
{% include 'purchase_orders/includes/card_po.html' with dealer_slug=request.dealer.slug po_model=po_model entity_slug=entity_slug style='po-detail' %}
</div>
</div>
<!-- PO List Button -->
<a class="btn btn-phoenix-primary w-100 py-2"
href="{% url 'purchase_order_list' request.dealer.slug %}">
<i class="fas fa-list me-2"></i>{% trans 'PO List' %}
@ -25,9 +23,7 @@
</div>
</div>
<!-- Main Content -->
<div class="col-lg-8">
<!-- Stats Cards -->
<div class="col-lg-12">
<div class="card mb-4">
<div class="card-body">
<div class="row text-center">
@ -50,30 +46,20 @@
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-12">
<!-- PO Details -->
<div class="card">
<div class="card-body">
<h3 class="h4 fw-light mb-2">{{ po_model.po_title }}</h3>
<!-- PO Items Table -->
<div class="table-responsive">
{% po_item_table1 po_items %}
</div>
<div class="col-lg-12">
<div class="table-responsive">
{% po_item_table1 po_items %}
</div>
</div>
<!--POS list-->
<a class="btn btn-phoenix-primary w-100 py-2 mt-2"
href="{% url 'purchase_order_list' request.dealer.slug %}">
<i class="fas fa-list me-2"></i>{% trans 'PO List' %}
</a>
</div>
</div>
</div>
{% include "purchase_orders/includes/mark_as.html" %}
</div>
{% endblock %}
@ -91,15 +77,15 @@
document.getElementById('POModalTitle').textContent = title;
document.getElementById('POModalBody').innerHTML = `
<div class="d-flex justify-content-center gap-3">
<a class="btn btn-phoenix-primary px-4" href="${actionUrl}">
<i class="fas fa-check-circle me-2"></i>${buttonText}
</a>
<button class="btn btn-phoenix-secondary" data-bs-dismiss="modal">
<i class="fas fa-times me-2"></i>Cancel
</button>
</div>
`;
<div class="d-flex justify-content-center gap-3">
<a class="btn btn-phoenix-primary px-4" href="${actionUrl}">
<i class="fas fa-check-circle me-2"></i>${buttonText}
</a>
<button class="btn btn-phoenix-secondary" data-bs-dismiss="modal">
<i class="fas fa-times me-2"></i>Cancel
</button>
</div>
`;
modal.show();
};

View File

@ -74,12 +74,6 @@
</div>
</div>
<div class="d-flex align-items-center gap-2">
{% if estimate.invoicemodel_set.first %}
<a href="{% url 'invoice_detail' request.dealer.slug estimate.invoicemodel_set.first.pk %}" class="btn btn-phoenix-primary btn-sm" type="button"><i class="fa-solid fa-receipt"></i>
{{ _("View Invoice")}}</a>
<button class="btn btn-phoenix-primary" data-bs-toggle="modal" data-bs-target="#POModal"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-receipt"></i> {% trans 'View Purchase Order' %}</span></button>
{% endif %}
{% if estimate.status == 'draft' %}
<a href="{% url 'send_email' request.dealer.slug estimate.pk %}" class="btn btn-phoenix-primary me-2"><span class="fa-regular fa-paper-plane me-sm-2"></span><span class="d-none d-sm-inline-block">{% trans 'Send Quotation' %}</span></a>
<button id="mark_as_sent_estimate" class="btn btn-phoenix-secondary" onclick="setFormAction('review')" data-bs-toggle="modal" data-bs-target="#confirmModal"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-check-double"></i> {% trans 'Mark As Sent' %}</span></button>
@ -87,16 +81,23 @@
<button id="accept_estimate" onclick="setFormAction('approved')" class="btn btn-phoenix-secondary" data-bs-toggle="modal" data-bs-target="#confirmModal"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-check-double"></i> {% trans 'Mark As Accept' %}</span></button>
{% elif estimate.status == 'approved' %}
{% if estimate.sale_orders.first %}
{% if estimate.sale_orders.first %}
<!--if sale order exist-->
<a href="{% url 'invoice_create' request.dealer.slug estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-receipt"></i> {% trans 'Create Invoice' %}</span></a>
<a href="{% url 'preview_sale_order' request.dealer.slug estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block">{{ _("Preview Sale Order") }}</span></a>
{% else %}
<a href="{% url 'order_detail' request.dealer.slug estimate.sale_orders.first.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block">{{ _("Preview Sale Order") }}</span></a>
{% else %}
<a href="{% url 'create_sale_order' request.dealer.slug estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block"><i class="fa-solid fa-file-import"></i> {% trans 'Create Sale Order' %}</span></a>
{% comment %} {% endcomment %}
{% endif %}
{% elif estimate.status == 'in_review' %}
<a href="{% url 'estimate_preview' request.dealer.slug estimate.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block"><i class="fa-regular fa-eye"></i> {% trans 'Preview' %}</span></a>
{% endif %}
{% elif estimate.status == 'completed' %}
<a href="{% url 'order_detail' request.dealer.slug estimate.sale_orders.first.pk %}" class="btn btn-phoenix-primary"><span class="d-none d-sm-inline-block">{{ _("Preview Sale Order") }}</span></a>
<a href="{% url 'invoice_detail' request.dealer.slug estimate.invoicemodel_set.first.pk %}" class="btn btn-phoenix-primary btn-sm" type="button"><i class="fa-solid fa-receipt"></i>
{{ _("View Invoice")}}</a>
{% endif %}
{% if estimate.can_cancel %}
{% if perms.django_ledger.change_estimatemodel %}
<button class="btn btn-phoenix-danger" data-bs-toggle="modal" data-bs-target="#CancelModal"><i class="fa-solid fa-ban"></i> {% trans "Cancel" %}</button>

View File

@ -23,7 +23,7 @@
</div>
</div>
<div class="table-responsive scrollbar mx-n1 px-1">
<div class="card-header ">
<div class="card-header ">
</div>
<h4 class="my-4">Groups</h4>