update
This commit is contained in:
commit
ab657348e6
@ -25,6 +25,7 @@ admin.site.register(models.Organization)
|
|||||||
admin.site.register(models.Representative)
|
admin.site.register(models.Representative)
|
||||||
admin.site.register(models.CarTrim)
|
admin.site.register(models.CarTrim)
|
||||||
admin.site.register(models.AdditionalServices)
|
admin.site.register(models.AdditionalServices)
|
||||||
|
admin.site.register(models.Payment)
|
||||||
|
|
||||||
@admin.register(models.CarMake)
|
@admin.register(models.CarMake)
|
||||||
class CarMakeAdmin(admin.ModelAdmin):
|
class CarMakeAdmin(admin.ModelAdmin):
|
||||||
|
|||||||
@ -17,8 +17,9 @@ from .models import (
|
|||||||
CarLocation,
|
CarLocation,
|
||||||
Organization,
|
Organization,
|
||||||
Representative,
|
Representative,
|
||||||
SaleQuotationCar,
|
Payment,
|
||||||
AdditionalServices
|
SaleQuotationCar,
|
||||||
|
AdditionalServices
|
||||||
|
|
||||||
)
|
)
|
||||||
from django.forms import ModelMultipleChoiceField
|
from django.forms import ModelMultipleChoiceField
|
||||||
@ -28,6 +29,10 @@ from django.forms import formset_factory
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class PaymentForm(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = Payment
|
||||||
|
fields = ['amount','payment_method', 'reference_number']
|
||||||
|
|
||||||
class UserForm(forms.ModelForm):
|
class UserForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|||||||
18
inventory/migrations/0015_alter_salequotation_payment_id.py
Normal file
18
inventory/migrations/0015_alter_salequotation_payment_id.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 4.2.17 on 2024-12-24 14:26
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('inventory', '0014_payment_refund'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='salequotation',
|
||||||
|
name='payment_id',
|
||||||
|
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='Payment ID'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -675,7 +675,7 @@ class SaleQuotation(models.Model):
|
|||||||
updated_at = models.DateTimeField(auto_now=True, verbose_name=_("Updated At"))
|
updated_at = models.DateTimeField(auto_now=True, verbose_name=_("Updated At"))
|
||||||
|
|
||||||
posted = models.BooleanField(default=False)
|
posted = models.BooleanField(default=False)
|
||||||
payment_id = models.CharField(max_length=10, null=True, blank=True, verbose_name=_("Payment ID"))
|
payment_id = models.CharField(max_length=255, null=True, blank=True, verbose_name=_("Payment ID"))
|
||||||
is_paid = models.BooleanField(default=False)
|
is_paid = models.BooleanField(default=False)
|
||||||
date_draft = models.DateTimeField(null=True, blank=True, verbose_name=_('Draft Date'))
|
date_draft = models.DateTimeField(null=True, blank=True, verbose_name=_('Draft Date'))
|
||||||
date_in_review = models.DateTimeField(null=True, blank=True, verbose_name=_('In Review Date'))
|
date_in_review = models.DateTimeField(null=True, blank=True, verbose_name=_('In Review Date'))
|
||||||
@ -838,7 +838,7 @@ class Payment(models.Model):
|
|||||||
verbose_name_plural = _("payments")
|
verbose_name_plural = _("payments")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"Payment of {self.amount} on {self.date} for {self.order}"
|
return f"Payment of {self.amount} on {self.payment_date} for {self.quotation}"
|
||||||
|
|
||||||
|
|
||||||
class Refund(models.Model):
|
class Refund(models.Model):
|
||||||
|
|||||||
@ -82,6 +82,10 @@ urlpatterns = [
|
|||||||
path('sales/quotations/<int:pk>/post_quotation/', views.post_quotation, name='post_quotation'),
|
path('sales/quotations/<int:pk>/post_quotation/', views.post_quotation, name='post_quotation'),
|
||||||
path('sales/quotations/<int:pk>/invoice_detail/', views.invoice_detail, name='invoice_detail'),
|
path('sales/quotations/<int:pk>/invoice_detail/', views.invoice_detail, name='invoice_detail'),
|
||||||
|
|
||||||
|
#Payment URLs
|
||||||
|
# path('sales/quotations/<int:pk>/payment/', views.PaymentCreateView.as_view(), name='payment_create'),
|
||||||
|
path('sales/quotations/<int:pk>/payment/', views.payment_create, name='payment_create'),
|
||||||
|
|
||||||
# Users URLs
|
# Users URLs
|
||||||
path('user/create/', views.UserCreateView.as_view(), name='user_create'),
|
path('user/create/', views.UserCreateView.as_view(), name='user_create'),
|
||||||
path('user/<int:pk>/update/', views.UserUpdateView.as_view(), name='user_update'),
|
path('user/<int:pk>/update/', views.UserUpdateView.as_view(), name='user_update'),
|
||||||
|
|||||||
@ -867,18 +867,18 @@ def generate_invoice(request, pk):
|
|||||||
invoice_model.save()
|
invoice_model.save()
|
||||||
quotation.save()
|
quotation.save()
|
||||||
|
|
||||||
# invoice_model = invoice_model.filter(date_draft=quotation.date_draft).first()
|
|
||||||
# if not invoice_model.can_review():
|
|
||||||
# messages.error(request, "Quotation is not ready for review")
|
|
||||||
# return redirect("quotation_detail", pk=pk)
|
|
||||||
|
|
||||||
# invoice_model.mark_as_review()
|
if not invoice_model.can_review():
|
||||||
# invoice_model.date_in_review = date
|
messages.error(request, "Quotation is not ready for review")
|
||||||
# qoutation.date_in_review = date
|
return redirect("quotation_detail", pk=pk)
|
||||||
# qoutation.status = "In Review"
|
|
||||||
# invoice_model.save()
|
invoice_model.mark_as_review()
|
||||||
# qoutation.save()
|
invoice_model.date_in_review = date
|
||||||
# messages.success(request, _("Quotation Reviewed"))
|
quotation.date_in_review = date
|
||||||
|
quotation.status = "In Review"
|
||||||
|
invoice_model.save()
|
||||||
|
quotation.save()
|
||||||
|
|
||||||
# elif status == "approved":
|
# elif status == "approved":
|
||||||
# if qoutation.status == "Approved":
|
# if qoutation.status == "Approved":
|
||||||
# messages.error(request, "Quotation is already approved")
|
# messages.error(request, "Quotation is already approved")
|
||||||
@ -973,11 +973,11 @@ def post_quotation(request, pk):
|
|||||||
# if not ledger:
|
# if not ledger:
|
||||||
# ledger = entity.create_ledger(name=f"Payment Ledger for Invoice {invoice_model}",posted=True)
|
# ledger = entity.create_ledger(name=f"Payment Ledger for Invoice {invoice_model}",posted=True)
|
||||||
|
|
||||||
entity_unit,created = EntityUnitModel.objects.get_or_create(
|
# entity_unit,created = EntityUnitModel.objects.get_or_create(
|
||||||
name="Sales Department",
|
# name="Sales Department",
|
||||||
entity=entity,
|
# entity=entity,
|
||||||
document_prefix="SD"
|
# document_prefix="SD"
|
||||||
)
|
# )
|
||||||
|
|
||||||
journal_entry = JournalEntryModel.objects.create(
|
journal_entry = JournalEntryModel.objects.create(
|
||||||
entity_unit=entity_unit,
|
entity_unit=entity_unit,
|
||||||
@ -1018,57 +1018,43 @@ def mark_quotation(request, pk):
|
|||||||
date = datetime.datetime.now()
|
date = datetime.datetime.now()
|
||||||
customer = entity.get_customers().filter(customer_name=qoutation.customer.get_full_name).first()
|
customer = entity.get_customers().filter(customer_name=qoutation.customer.get_full_name).first()
|
||||||
invoice_model = entity.get_invoices().filter(customer=customer)
|
invoice_model = entity.get_invoices().filter(customer=customer)
|
||||||
# if status == "in_review":
|
if status == "approved":
|
||||||
# if qoutation.status == "In Review":
|
if qoutation.status == "Approved":
|
||||||
# messages.error(request, "Quotation is already in review")
|
messages.error(request, "Quotation is already approved")
|
||||||
# return redirect("quotation_detail", pk=pk)
|
return redirect("quotation_detail", pk=pk)
|
||||||
|
|
||||||
# invoice_model = invoice_model.filter(date_draft=qoutation.date_draft).first()
|
invoice_model = invoice_model.filter(date_in_review=qoutation.date_in_review).first()
|
||||||
# if not invoice_model.can_review():
|
if not invoice_model.can_approve():
|
||||||
# messages.error(request, "Quotation is not ready for review")
|
messages.error(request, "Quotation is not ready for approval")
|
||||||
# return redirect("quotation_detail", pk=pk)
|
return redirect("quotation_detail", pk=pk)
|
||||||
|
|
||||||
# invoice_model.mark_as_review()
|
invoice_model.mark_as_approved(entity_slug=entity.slug, user_model=request.user.dealer.get_root_dealer.user)
|
||||||
# invoice_model.date_in_review = date
|
invoice_model.date_approved = date
|
||||||
# qoutation.date_in_review = date
|
qoutation.date_approved = date
|
||||||
# qoutation.status = "In Review"
|
invoice_model.save()
|
||||||
# invoice_model.save()
|
qoutation.status = "Approved"
|
||||||
# qoutation.save()
|
qoutation.save()
|
||||||
# messages.success(request, _("Quotation Reviewed"))
|
for car in qoutation.quotation_cars.all():
|
||||||
# elif status == "approved":
|
car.car.status = "reserved"
|
||||||
# if qoutation.status == "Approved":
|
car.car.save()
|
||||||
# messages.error(request, "Quotation is already approved")
|
messages.success(request, _("Quotation Approved"))
|
||||||
# return redirect("quotation_detail", pk=pk)
|
elif status == "paid":
|
||||||
|
if qoutation.status == "Paid":
|
||||||
|
messages.error(request, "Quotation is already paid")
|
||||||
|
return redirect("quotation_detail", pk=pk)
|
||||||
|
|
||||||
# invoice_model = invoice_model.filter(date_in_review=qoutation.date_in_review).first()
|
invoice_model = invoice_model.filter(date_approved=qoutation.date_approved).first()
|
||||||
# if not invoice_model.can_approve():
|
if not invoice_model.can_pay():
|
||||||
# messages.error(request, "Quotation is not ready for approval")
|
messages.error(request, "Quotation is not ready for payment")
|
||||||
# return redirect("quotation_detail", pk=pk)
|
return redirect("quotation_detail", pk=pk)
|
||||||
|
|
||||||
# invoice_model.mark_as_approved(entity_slug=entity.slug, user_model=request.user.dealer.get_root_dealer.user)
|
invoice_model.mark_as_paid(entity_slug=entity.slug, user_model=request.user.dealer.get_root_dealer.user)
|
||||||
# invoice_model.date_approved = date
|
invoice_model.date_paid = date
|
||||||
# qoutation.date_approved = date
|
qoutation.date_paid = date
|
||||||
# invoice_model.save()
|
invoice_model.save()
|
||||||
# qoutation.status = "Approved"
|
qoutation.status = "Paid"
|
||||||
# qoutation.save()
|
qoutation.save()
|
||||||
# messages.success(request, _("Quotation Approved"))
|
messages.success(request, _("Quotation Paid"))
|
||||||
# elif status == "paid":
|
|
||||||
# if qoutation.status == "Paid":
|
|
||||||
# messages.error(request, "Quotation is already paid")
|
|
||||||
# return redirect("quotation_detail", pk=pk)
|
|
||||||
|
|
||||||
# invoice_model = invoice_model.filter(date_approved=qoutation.date_approved).first()
|
|
||||||
# if not invoice_model.can_pay():
|
|
||||||
# messages.error(request, "Quotation is not ready for payment")
|
|
||||||
# return redirect("quotation_detail", pk=pk)
|
|
||||||
|
|
||||||
# invoice_model.mark_as_paid(entity_slug=entity.slug, user_model=request.user.dealer.get_root_dealer.user)
|
|
||||||
# invoice_model.date_paid = date
|
|
||||||
# qoutation.date_paid = date
|
|
||||||
# invoice_model.save()
|
|
||||||
# qoutation.status = "Paid"
|
|
||||||
# qoutation.save()
|
|
||||||
# messages.success(request, _("Quotation Paid"))
|
|
||||||
return redirect("quotation_detail", pk=pk)
|
return redirect("quotation_detail", pk=pk)
|
||||||
|
|
||||||
|
|
||||||
@ -1390,3 +1376,72 @@ def payment_invoice(request,pk):
|
|||||||
|
|
||||||
|
|
||||||
return redirect('quotation_detail', pk=pk)
|
return redirect('quotation_detail', pk=pk)
|
||||||
|
|
||||||
|
|
||||||
|
# class PaymentCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView):
|
||||||
|
# model = models.Payment
|
||||||
|
# form_class = forms.PaymentForm
|
||||||
|
# template_name = "sales/payments/payment_form.html"
|
||||||
|
# success_url = reverse_lazy("quotation_list")
|
||||||
|
# success_message = "Payment created successfully."
|
||||||
|
|
||||||
|
# def form_valid(self, form):
|
||||||
|
# quotation = get_object_or_404(models.SaleQuotation, pk=self.kwargs["pk"])
|
||||||
|
# form.instance.quotation = quotation
|
||||||
|
# form.save()
|
||||||
|
# return super().form_valid(form)
|
||||||
|
# def get_context_data(self, **kwargs):
|
||||||
|
# context = super().get_context_data(**kwargs)
|
||||||
|
# context["quotation"] = get_object_or_404(models.SaleQuotation, pk=self.kwargs["pk"])
|
||||||
|
# return context
|
||||||
|
|
||||||
|
|
||||||
|
def payment_create(request, pk):
|
||||||
|
quotation = get_object_or_404(models.SaleQuotation, pk=pk)
|
||||||
|
if request.method == "POST":
|
||||||
|
form = forms.PaymentForm(request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
form.instance.quotation = quotation
|
||||||
|
insatnce = form.save()
|
||||||
|
|
||||||
|
entity = quotation.entity
|
||||||
|
customer = entity.get_customers().filter(customer_name=quotation.customer.get_full_name).first()
|
||||||
|
coa_qs, coa_map = entity.get_all_coa_accounts()
|
||||||
|
cash_account = coa_qs.first().get_coa_accounts().filter(name="Cash")
|
||||||
|
recivable_account = coa_qs.first().get_coa_accounts().filter(name="Accounts Receivable")
|
||||||
|
journal_entry = JournalEntryModel.objects.filter(pk=quotation.payment_id).first()
|
||||||
|
TransactionModel.objects.create(
|
||||||
|
journal_entry=journal_entry,
|
||||||
|
account=cash_account.first(), # Debit Cash
|
||||||
|
amount=insatnce.amount, # Payment amount
|
||||||
|
tx_type='debit',
|
||||||
|
description="Payment Received",
|
||||||
|
)
|
||||||
|
|
||||||
|
TransactionModel.objects.create(
|
||||||
|
journal_entry=journal_entry,
|
||||||
|
account=recivable_account.first(), # Credit Accounts Receivable
|
||||||
|
amount=insatnce.amount, # Payment amount
|
||||||
|
tx_type='credit',
|
||||||
|
description="Payment Received",
|
||||||
|
)
|
||||||
|
journal_entry.posted = True
|
||||||
|
quotation.posted = True
|
||||||
|
quotation.save()
|
||||||
|
journal_entry.save()
|
||||||
|
|
||||||
|
invoice_model = entity.get_invoices().filter(date_approved=quotation.date_approved).first()
|
||||||
|
|
||||||
|
invoice_model.mark_as_paid(entity_slug=entity.slug, user_model=request.user.dealer.get_root_dealer.user)
|
||||||
|
date = timezone.now()
|
||||||
|
invoice_model.date_paid = date
|
||||||
|
quotation.date_paid = date
|
||||||
|
invoice_model.save()
|
||||||
|
quotation.status = "Paid"
|
||||||
|
quotation.save()
|
||||||
|
|
||||||
|
messages.success(request, "Payment created successfully.")
|
||||||
|
return redirect("quotation_detail", pk=pk)
|
||||||
|
else:
|
||||||
|
form = forms.PaymentForm()
|
||||||
|
return render(request, "sales/payments/payment_create.html", {"quotation": quotation,"form": form})
|
||||||
|
|||||||
0
templates/sales/payments/confirm.html
Normal file
0
templates/sales/payments/confirm.html
Normal file
24
templates/sales/payments/payment_create.html
Normal file
24
templates/sales/payments/payment_create.html
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load static %}
|
||||||
|
{% load crispy_forms_tags %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% block title %}{{ _("Payyment Create") }}{% endblock title %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="container">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">{{ _("Payment Create") }}</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form method="post" action="{% url 'payment_create' pk=quotation.pk %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form|crispy }}
|
||||||
|
<button type="submit" class="btn btn-primary">{% trans 'Save' %}</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
||||||
|
|
||||||
@ -148,13 +148,9 @@
|
|||||||
{% elif quotation.status == 'Draft' and quotation.is_approved %}
|
{% elif quotation.status == 'Draft' and quotation.is_approved %}
|
||||||
<a href="{% url 'mark_quotation' quotation.pk %}?status=in_review" class="btn btn-secondary">Mark As Review</a>
|
<a href="{% url 'mark_quotation' quotation.pk %}?status=in_review" class="btn btn-secondary">Mark As Review</a>
|
||||||
{% elif quotation.status == 'In Review' %}
|
{% elif quotation.status == 'In Review' %}
|
||||||
<a href="{% url 'mark_quotation' quotation.pk %}?status=approved" class="btn btn-info">Approve</a>
|
<a href="{% url 'mark_quotation' quotation.pk %}?status=approved" class="btn btn-info">Approve Quotation</a>
|
||||||
{% elif quotation.status == 'Approved' %}
|
{% elif quotation.status == 'Approved' %}
|
||||||
<a href="{% url 'mark_quotation' quotation.pk %}?status=paid" class="btn btn-success">Mark As Paid</a>
|
<a href="{% url 'payment_create' quotation.pk %}" class="btn btn-success">Pay</a>
|
||||||
{% else %}
|
|
||||||
{% if not quotation.posted %}
|
|
||||||
<a href="{% url 'post_quotation' quotation.pk %}" class="btn btn-success">Post</a>
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user