This commit is contained in:
Marwan Alwali 2024-12-24 18:35:30 +03:00
commit ab657348e6
9 changed files with 181 additions and 78 deletions

View File

@ -25,6 +25,7 @@ admin.site.register(models.Organization)
admin.site.register(models.Representative)
admin.site.register(models.CarTrim)
admin.site.register(models.AdditionalServices)
admin.site.register(models.Payment)
@admin.register(models.CarMake)
class CarMakeAdmin(admin.ModelAdmin):

View File

@ -17,8 +17,9 @@ from .models import (
CarLocation,
Organization,
Representative,
SaleQuotationCar,
AdditionalServices
Payment,
SaleQuotationCar,
AdditionalServices
)
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 Meta:

View 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'),
),
]

View File

@ -675,7 +675,7 @@ class SaleQuotation(models.Model):
updated_at = models.DateTimeField(auto_now=True, verbose_name=_("Updated At"))
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)
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'))
@ -838,7 +838,7 @@ class Payment(models.Model):
verbose_name_plural = _("payments")
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):

View File

@ -82,6 +82,10 @@ urlpatterns = [
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'),
#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
path('user/create/', views.UserCreateView.as_view(), name='user_create'),
path('user/<int:pk>/update/', views.UserUpdateView.as_view(), name='user_update'),

View File

@ -859,7 +859,7 @@ def generate_invoice(request, pk):
origin="Payment",
)
quotation.payment_id = journal_entry.pk
quotation.payment_id = journal_entry.pk
quotation.is_approved = True
date = datetime.datetime.now()
quotation.date_draft = date
@ -867,18 +867,18 @@ def generate_invoice(request, pk):
invoice_model.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)
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()
# invoice_model.date_in_review = date
# qoutation.date_in_review = date
# qoutation.status = "In Review"
# invoice_model.save()
# qoutation.save()
# messages.success(request, _("Quotation Reviewed"))
invoice_model.mark_as_review()
invoice_model.date_in_review = date
quotation.date_in_review = date
quotation.status = "In Review"
invoice_model.save()
quotation.save()
# elif status == "approved":
# if qoutation.status == "Approved":
# messages.error(request, "Quotation is already approved")
@ -968,16 +968,16 @@ def post_quotation(request, pk):
recivable_account = coa_qs.first().get_coa_accounts().filter(name="Accounts Receivable")
customer = entity.get_customers().filter(customer_name=qoutation.customer.get_full_name).first()
invoice_model = entity.get_invoices().filter(customer=customer,date_paid=qoutation.date_paid).first()
ledger = entity.get_ledgers().filter(name=f"Payment Ledger for Invoice {invoice_model}").first()
ledger = entity.get_ledgers().filter(name=f"Payment Ledger for Invoice {invoice_model}").first()
return
# if not ledger:
# ledger = entity.create_ledger(name=f"Payment Ledger for Invoice {invoice_model}",posted=True)
entity_unit,created = EntityUnitModel.objects.get_or_create(
name="Sales Department",
entity=entity,
document_prefix="SD"
)
# entity_unit,created = EntityUnitModel.objects.get_or_create(
# name="Sales Department",
# entity=entity,
# document_prefix="SD"
# )
journal_entry = JournalEntryModel.objects.create(
entity_unit=entity_unit,
@ -1017,58 +1017,44 @@ def mark_quotation(request, pk):
entity = qoutation.entity
date = datetime.datetime.now()
customer = entity.get_customers().filter(customer_name=qoutation.customer.get_full_name).first()
invoice_model = entity.get_invoices().filter(customer=customer)
# if status == "in_review":
# if qoutation.status == "In Review":
# messages.error(request, "Quotation is already in review")
# return redirect("quotation_detail", pk=pk)
invoice_model = entity.get_invoices().filter(customer=customer)
if status == "approved":
if qoutation.status == "Approved":
messages.error(request, "Quotation is already approved")
return redirect("quotation_detail", pk=pk)
# invoice_model = invoice_model.filter(date_draft=qoutation.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()
# invoice_model.date_in_review = date
# qoutation.date_in_review = date
# qoutation.status = "In Review"
# invoice_model.save()
# qoutation.save()
# messages.success(request, _("Quotation Reviewed"))
# elif status == "approved":
# if qoutation.status == "Approved":
# messages.error(request, "Quotation is already approved")
# return redirect("quotation_detail", pk=pk)
invoice_model = invoice_model.filter(date_in_review=qoutation.date_in_review).first()
if not invoice_model.can_approve():
messages.error(request, "Quotation is not ready for approval")
return redirect("quotation_detail", pk=pk)
# invoice_model = invoice_model.filter(date_in_review=qoutation.date_in_review).first()
# if not invoice_model.can_approve():
# messages.error(request, "Quotation is not ready for approval")
# 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.date_approved = date
qoutation.date_approved = date
invoice_model.save()
qoutation.status = "Approved"
qoutation.save()
for car in qoutation.quotation_cars.all():
car.car.status = "reserved"
car.car.save()
messages.success(request, _("Quotation Approved"))
elif status == "paid":
if qoutation.status == "Paid":
messages.error(request, "Quotation is already paid")
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.date_approved = date
# qoutation.date_approved = date
# invoice_model.save()
# qoutation.status = "Approved"
# qoutation.save()
# messages.success(request, _("Quotation Approved"))
# 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 = 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"))
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)
@ -1389,4 +1375,73 @@ def payment_invoice(request,pk):
invoice = invoice_model.filter(customer=customer,date_draft=quotation.date_draft).first()
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})

View File

View 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 %}

View File

@ -148,13 +148,9 @@
{% 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>
{% elif quotation.status == 'In Review' %}
<a href="{% url 'mark_quotation' quotation.pk %}?status=approved" class="btn btn-info">Approve</a>
{% elif quotation.status == 'Approved' %}
<a href="{% url 'mark_quotation' quotation.pk %}?status=paid" class="btn btn-success">Mark As Paid</a>
{% else %}
{% if not quotation.posted %}
<a href="{% url 'post_quotation' quotation.pk %}" class="btn btn-success">Post</a>
{% endif %}
<a href="{% url 'mark_quotation' quotation.pk %}?status=approved" class="btn btn-info">Approve Quotation</a>
{% elif quotation.status == 'Approved' %}
<a href="{% url 'payment_create' quotation.pk %}" class="btn btn-success">Pay</a>
{% endif %}