Merge branch 'main' of http://10.10.1.136:3000/ismail/haikal into frontend
This commit is contained in:
commit
5e602f563f
@ -1355,11 +1355,27 @@ class SaleOrderForm(forms.ModelForm):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = SaleOrder
|
model = SaleOrder
|
||||||
fields = [
|
fields = [
|
||||||
"customer","expected_delivery_date","estimate","opportunity","comments","order_date","status"]
|
"customer",
|
||||||
|
"expected_delivery_date",
|
||||||
|
"estimate",
|
||||||
|
"opportunity",
|
||||||
|
"comments",
|
||||||
|
"order_date",
|
||||||
|
"status",
|
||||||
|
]
|
||||||
widgets = {
|
widgets = {
|
||||||
"expected_delivery_date": forms.DateInput(attrs={"type": "date", "label": _("Expected Delivery Date")}),
|
"expected_delivery_date": forms.DateInput(
|
||||||
"order_date": forms.DateInput(attrs={"type": "date", "label": _("Order Date")}),
|
attrs={"type": "date", "label": _("Expected Delivery Date")}
|
||||||
"customer": forms.Select(attrs={"class": "form-control","label": _("Customer"),}),
|
),
|
||||||
|
"order_date": forms.DateInput(
|
||||||
|
attrs={"type": "date", "label": _("Order Date")}
|
||||||
|
),
|
||||||
|
"customer": forms.Select(
|
||||||
|
attrs={
|
||||||
|
"class": "form-control",
|
||||||
|
"label": _("Customer"),
|
||||||
|
}
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -2479,7 +2479,6 @@ class SaleOrder(models.Model):
|
|||||||
return self.invoice.get_itemtxs_data()[0]
|
return self.invoice.get_itemtxs_data()[0]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def cars(self):
|
def cars(self):
|
||||||
if self.items:
|
if self.items:
|
||||||
@ -2497,6 +2496,7 @@ class CustomGroup(models.Model):
|
|||||||
@property
|
@property
|
||||||
def entity(self):
|
def entity(self):
|
||||||
return self.invoice.entity
|
return self.invoice.entity
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def users(self):
|
def users(self):
|
||||||
return self.group.user_set.all()
|
return self.group.user_set.all()
|
||||||
|
|||||||
@ -309,7 +309,9 @@ def update_item_model_cost(sender, instance, created, **kwargs):
|
|||||||
# entity.get_all_accounts()
|
# entity.get_all_accounts()
|
||||||
# .filter(name="Cash", role=roles.ASSET_CA_CASH)
|
# .filter(name="Cash", role=roles.ASSET_CA_CASH)
|
||||||
# .first()
|
# .first()
|
||||||
entity.get_all_accounts().filter(role=roles.ASSET_CA_CASH,role_default=True).first()
|
entity.get_all_accounts()
|
||||||
|
.filter(role=roles.ASSET_CA_CASH, role_default=True)
|
||||||
|
.first()
|
||||||
)
|
)
|
||||||
|
|
||||||
ledger = LedgerModel.objects.create(
|
ledger = LedgerModel.objects.create(
|
||||||
|
|||||||
@ -452,6 +452,12 @@ def po_item_table1(context, queryset):
|
|||||||
"purchase_orders/includes/po_item_formset.html", takes_context=True
|
"purchase_orders/includes/po_item_formset.html", takes_context=True
|
||||||
)
|
)
|
||||||
def po_item_formset_table(context, po_model, itemtxs_formset):
|
def po_item_formset_table(context, po_model, itemtxs_formset):
|
||||||
|
# print(len(itemtxs_formset.forms))
|
||||||
|
|
||||||
|
for form in itemtxs_formset.forms:
|
||||||
|
form.fields["item_model"].queryset = form.fields["item_model"].queryset.filter(
|
||||||
|
item_role="inventory"
|
||||||
|
)
|
||||||
return {
|
return {
|
||||||
"entity_slug": context["view"].kwargs["entity_slug"],
|
"entity_slug": context["view"].kwargs["entity_slug"],
|
||||||
"po_model": po_model,
|
"po_model": po_model,
|
||||||
@ -614,27 +620,26 @@ def get_vehicle_type_name(car_serie):
|
|||||||
return "sedan"
|
return "sedan"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def status_badge_color(status):
|
def status_badge_color(status):
|
||||||
color_map = {
|
color_map = {
|
||||||
'PENDING_APPROVAL': 'warning',
|
"PENDING_APPROVAL": "warning",
|
||||||
'APPROVED': 'info',
|
"APPROVED": "info",
|
||||||
'IN_FINANCING': 'primary',
|
"IN_FINANCING": "primary",
|
||||||
'PARTIALLY_PAID': 'success',
|
"PARTIALLY_PAID": "success",
|
||||||
'FULLY_PAID': 'success',
|
"FULLY_PAID": "success",
|
||||||
'PENDING_DELIVERY': 'warning',
|
"PENDING_DELIVERY": "warning",
|
||||||
'DELIVERED': 'success',
|
"DELIVERED": "success",
|
||||||
'CANCELLED': 'danger',
|
"CANCELLED": "danger",
|
||||||
}
|
}
|
||||||
return color_map.get(status, 'secondary')
|
return color_map.get(status, "secondary")
|
||||||
|
|
||||||
|
|
||||||
@register.inclusion_tag('inventory/tags/inventory_table.html', takes_context=True)
|
@register.inclusion_tag("inventory/tags/inventory_table.html", takes_context=True)
|
||||||
def inventory_table(context, queryset):
|
def inventory_table(context, queryset):
|
||||||
ctx = {
|
ctx = {
|
||||||
'entity_slug': context['view'].kwargs['entity_slug'],
|
"entity_slug": context["view"].kwargs["entity_slug"],
|
||||||
'inventory_list': queryset
|
"inventory_list": queryset,
|
||||||
}
|
}
|
||||||
ctx.update(queryset.aggregate(inventory_total_value=Sum('total_value')))
|
ctx.update(queryset.aggregate(inventory_total_value=Sum("total_value")))
|
||||||
return ctx
|
return ctx
|
||||||
@ -375,9 +375,16 @@ urlpatterns = [
|
|||||||
views.sales_list_view,
|
views.sales_list_view,
|
||||||
name="sales_list",
|
name="sales_list",
|
||||||
),
|
),
|
||||||
path('sale_orders/<int:pk>/', views.SaleOrderDetailView.as_view(), name='order_detail'),
|
path(
|
||||||
path('inventory/<slug:entity_slug>/list/', views.InventoryListView.as_view(), name='inventort_list'),
|
"sale_orders/<int:pk>/",
|
||||||
|
views.SaleOrderDetailView.as_view(),
|
||||||
|
name="order_detail",
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"inventory/<slug:entity_slug>/list/",
|
||||||
|
views.InventoryListView.as_view(),
|
||||||
|
name="inventort_list",
|
||||||
|
),
|
||||||
# Sales URLs quotation_create
|
# Sales URLs quotation_create
|
||||||
# path(
|
# path(
|
||||||
# "sales/quotations/create/",
|
# "sales/quotations/create/",
|
||||||
|
|||||||
@ -3627,26 +3627,28 @@ def sales_list_view(request):
|
|||||||
context = {"txs": page_obj, "page_obj": page_obj}
|
context = {"txs": page_obj, "page_obj": page_obj}
|
||||||
return render(request, "sales/sales_list.html", context)
|
return render(request, "sales/sales_list.html", context)
|
||||||
|
|
||||||
|
|
||||||
class SaleOrderDetailView(LoginRequiredMixin, DetailView):
|
class SaleOrderDetailView(LoginRequiredMixin, DetailView):
|
||||||
model = models.SaleOrder
|
model = models.SaleOrder
|
||||||
template_name = 'sales/saleorder_detail.html'
|
template_name = "sales/saleorder_detail.html"
|
||||||
context_object_name = 'sale_order'
|
context_object_name = "sale_order"
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
sale_order = self.get_object()
|
sale_order = self.get_object()
|
||||||
|
|
||||||
# Add additional context data
|
# Add additional context data
|
||||||
context['status_choices'] = dict(models.SaleOrder.STATUS_CHOICES)
|
context["status_choices"] = dict(models.SaleOrder.STATUS_CHOICES)
|
||||||
context['page_title'] = _('Sales Order Details')
|
context["page_title"] = _("Sales Order Details")
|
||||||
|
|
||||||
# Calculate any additional properties you want to display
|
# Calculate any additional properties you want to display
|
||||||
context['is_delivered'] = sale_order.status == 'DELIVERED'
|
context["is_delivered"] = sale_order.status == "DELIVERED"
|
||||||
context['is_cancelled'] = sale_order.status == 'CANCELLED'
|
context["is_cancelled"] = sale_order.status == "CANCELLED"
|
||||||
context['is_pending_approval'] = sale_order.status == 'PENDING_APPROVAL'
|
context["is_pending_approval"] = sale_order.status == "PENDING_APPROVAL"
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
# Estimates
|
# Estimates
|
||||||
class EstimateListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
|
class EstimateListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
|
||||||
"""
|
"""
|
||||||
@ -4043,8 +4045,7 @@ def create_sale_order(request, pk):
|
|||||||
customer = estimate.customer.customer_set.first()
|
customer = estimate.customer.customer_set.first()
|
||||||
form.fields["estimate"].queryset = EstimateModel.objects.filter(pk=pk)
|
form.fields["estimate"].queryset = EstimateModel.objects.filter(pk=pk)
|
||||||
form.initial["estimate"] = estimate
|
form.initial["estimate"] = estimate
|
||||||
form.fields["customer"].queryset = models.Customer.objects.filter(
|
form.fields["customer"].queryset = models.Customer.objects.filter(pk=customer.pk)
|
||||||
pk=customer.pk)
|
|
||||||
form.initial["customer"] = customer
|
form.initial["customer"] = customer
|
||||||
if hasattr(estimate, "opportunity"):
|
if hasattr(estimate, "opportunity"):
|
||||||
form.initial["opportunity"] = estimate.opportunity
|
form.initial["opportunity"] = estimate.opportunity
|
||||||
@ -4570,7 +4571,6 @@ def invoice_create(request, pk):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
"form": form,
|
"form": form,
|
||||||
"estimate": estimate,
|
"estimate": estimate,
|
||||||
@ -8974,7 +8974,11 @@ def InventoryItemCreateView(request):
|
|||||||
trim_name = models.CarTrim.objects.get(pk=trim)
|
trim_name = models.CarTrim.objects.get(pk=trim)
|
||||||
|
|
||||||
inventory_name = f"{make_name.name} || {model_name.name} || {serie_name.name} || {trim_name.name} || {year} || {exterior.name} || {interior.name}"
|
inventory_name = f"{make_name.name} || {model_name.name} || {serie_name.name} || {trim_name.name} || {year} || {exterior.name} || {interior.name}"
|
||||||
if inventory := entity.get_items_inventory().filter(name=inventory_name).first():
|
if (
|
||||||
|
inventory := entity.get_items_inventory()
|
||||||
|
.filter(name=inventory_name)
|
||||||
|
.first()
|
||||||
|
):
|
||||||
messages.error(request, _("Inventory item already exists"))
|
messages.error(request, _("Inventory item already exists"))
|
||||||
return redirect(f"{reverse('inventory_item_create')}?for_po={for_po}")
|
return redirect(f"{reverse('inventory_item_create')}?for_po={for_po}")
|
||||||
uom = entity.get_uom_all().get(name="Unit")
|
uom = entity.get_uom_all().get(name="Unit")
|
||||||
@ -9108,14 +9112,31 @@ class PurchaseOrderUpdateView(PurchaseOrderModelUpdateViewBase):
|
|||||||
template_name = "purchase_orders/po_update.html"
|
template_name = "purchase_orders/po_update.html"
|
||||||
context_object_name = "po_model"
|
context_object_name = "po_model"
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, itemtxs_formset=None, **kwargs):
|
||||||
dealer = get_user_type(self.request)
|
dealer = get_user_type(self.request)
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
context["entity_slug"] = dealer.entity.slug
|
context["entity_slug"] = dealer.entity.slug
|
||||||
context["make_data"] = models.CarMake.objects.all()
|
po_model: PurchaseOrderModel = self.object
|
||||||
context["model_data"] = models.CarModel.objects.none()
|
# context["make_data"] = models.CarMake.objects.all()
|
||||||
context["serie_data"] = models.CarSerie.objects.none()
|
# context["model_data"] = models.CarModel.objects.none()
|
||||||
context["trim_data"] = models.CarTrim.objects.none()
|
# context["serie_data"] = models.CarSerie.objects.none()
|
||||||
|
# context["trim_data"] = models.CarTrim.objects.none()
|
||||||
|
# itemtxs_qs = dealer.entity.get_items_inventory().filter(item_role="inventory")
|
||||||
|
if not itemtxs_formset:
|
||||||
|
itemtxs_qs = self.get_po_itemtxs_qs(po_model)
|
||||||
|
itemtxs_qs, itemtxs_agg = po_model.get_itemtxs_data(queryset=itemtxs_qs)
|
||||||
|
po_itemtxs_formset_class = get_po_itemtxs_formset_class(po_model)
|
||||||
|
itemtxs_formset = po_itemtxs_formset_class(
|
||||||
|
entity_slug=dealer.entity.slug,
|
||||||
|
user_model=dealer.entity.admin,
|
||||||
|
po_model=po_model,
|
||||||
|
queryset=itemtxs_qs,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
itemtxs_qs, itemtxs_agg = po_model.get_itemtxs_data()
|
||||||
|
|
||||||
|
context["itemtxs_qs"] = itemtxs_qs
|
||||||
|
context["itemtxs_formset"] = itemtxs_formset
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
@ -9135,7 +9156,7 @@ class PurchaseOrderUpdateView(PurchaseOrderModelUpdateViewBase):
|
|||||||
kwargs={"entity_slug": entity_slug, "po_pk": po_pk},
|
kwargs={"entity_slug": entity_slug, "po_pk": po_pk},
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return super(PurchaseOrderModelUpdateViewBase, self).get(
|
return super(PurchaseOrderUpdateView, self).get(
|
||||||
request, entity_slug, po_pk, *args, **kwargs
|
request, entity_slug, po_pk, *args, **kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -9235,7 +9256,9 @@ class BasePurchaseOrderActionActionView(BasePurchaseOrderActionActionViewBase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
kwargs["user_model"] = self.request.user
|
# kwargs["user_model"] = self.request.user
|
||||||
|
dealer = get_user_type(request)
|
||||||
|
kwargs["user_model"] = dealer.entity.admin
|
||||||
if not self.action_name:
|
if not self.action_name:
|
||||||
raise ImproperlyConfigured("View attribute action_name is required.")
|
raise ImproperlyConfigured("View attribute action_name is required.")
|
||||||
response = super(BasePurchaseOrderActionActionView, self).get(
|
response = super(BasePurchaseOrderActionActionView, self).get(
|
||||||
@ -9245,12 +9268,18 @@ class BasePurchaseOrderActionActionView(BasePurchaseOrderActionActionViewBase):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
getattr(po_model, self.action_name)(commit=self.commit, **kwargs)
|
getattr(po_model, self.action_name)(commit=self.commit, **kwargs)
|
||||||
except ValidationError as e:
|
|
||||||
messages.add_message(
|
messages.add_message(
|
||||||
request,
|
request,
|
||||||
message=e.message,
|
message="PO updated successfully.",
|
||||||
level=messages.ERROR,
|
level=messages.SUCCESS,
|
||||||
)
|
)
|
||||||
|
except ValidationError as e:
|
||||||
|
print(e)
|
||||||
|
# messages.add_message(
|
||||||
|
# request,
|
||||||
|
# message=e.message,
|
||||||
|
# level=messages.ERROR,
|
||||||
|
# )
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
@ -9493,7 +9522,6 @@ def bulk_update_car_price(request):
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class InventoryListView(InventoryListViewBase):
|
class InventoryListView(InventoryListViewBase):
|
||||||
template_name = "inventory/list.html"
|
template_name = "inventory/list.html"
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
{%block title%} {%trans 'Stocks'%} {%endblock%}
|
{%block title%} {%trans 'Stocks'%} {%endblock%}
|
||||||
|
|
||||||
{% block customCSS %}
|
{% block customCSS %}
|
||||||
<style>
|
<style>
|
||||||
.htmx-indicator {
|
.htmx-indicator {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity 500ms ease-in;
|
transition: opacity 500ms ease-in;
|
||||||
@ -21,10 +21,10 @@
|
|||||||
.transition {
|
.transition {
|
||||||
transition: all ease-in 1s;
|
transition: all ease-in 1s;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
{% endblock customCSS %}
|
{% endblock customCSS %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="mb-9">
|
<div class="mb-9">
|
||||||
<div id="projectSummary">
|
<div id="projectSummary">
|
||||||
<div class="row g-3 justify-content-between align-items-end mb-4">
|
<div class="row g-3 justify-content-between align-items-end mb-4">
|
||||||
<div class="col-12 col-sm-auto">
|
<div class="col-12 col-sm-auto">
|
||||||
@ -293,7 +293,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %} {% block customJS %}
|
{% endblock %} {% block customJS %}
|
||||||
<script>
|
<script>
|
||||||
links = document.querySelectorAll(".nav-link");
|
links = document.querySelectorAll(".nav-link");
|
||||||
links.forEach((link) => {
|
links.forEach((link) => {
|
||||||
@ -357,5 +357,5 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
{% endblock customJS %}
|
{% endblock customJS %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
{% load custom_filters %}
|
{% load custom_filters %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container-fluid px-4 py-4">
|
<div class="container-fluid px-4 py-4">
|
||||||
<div class="row g-4">
|
<div class="row g-4">
|
||||||
<!-- Inventory Ordered Card -->
|
<!-- Inventory Ordered Card -->
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
@ -16,10 +16,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="card-body p-0">
|
<div class="card-body p-0">
|
||||||
{% if inventory_ordered %}
|
{% if inventory_ordered %}
|
||||||
|
|
||||||
|
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
|
|
||||||
{% inventory_table inventory_ordered %}
|
{% inventory_table inventory_ordered %}
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
@ -82,5 +79,5 @@
|
|||||||
<div class="col-12 text-end mt-3">
|
<div class="col-12 text-end mt-3">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -1,5 +1,7 @@
|
|||||||
{% load trans from i18n %}
|
{% load trans from i18n %}
|
||||||
{% load django_ledger %}
|
{% load currency_symbol from django_ledger %}
|
||||||
|
{% load icon from django_ledger %}
|
||||||
|
{% load custom_filters %}
|
||||||
{% load widget_tweaks %}
|
{% load widget_tweaks %}
|
||||||
|
|
||||||
<form action="{% url 'purchase_order_update_items' entity_slug=entity_slug po_pk=po_model.uuid %}"
|
<form action="{% url 'purchase_order_update_items' entity_slug=entity_slug po_pk=po_model.uuid %}"
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
{% load django_ledger %}
|
{% load currency_symbol from django_ledger %}
|
||||||
{% load custom_filters %}
|
{% load custom_filters %}
|
||||||
{% load widget_tweaks %}
|
{% load widget_tweaks %}
|
||||||
{% load crispy_forms_tags %}
|
{% load crispy_forms_tags %}
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
{% block title %}{{ page_title }} - {{ sale_order.formatted_order_id }}{% endblock %}
|
{% block title %}{{ page_title }} - {{ sale_order.formatted_order_id }}{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container mt-4">
|
<div class="container mt-4">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h2 class="mb-0">
|
<h2 class="mb-0">
|
||||||
@ -265,5 +265,5 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
Loading…
x
Reference in New Issue
Block a user