263 lines
10 KiB
HTML
263 lines
10 KiB
HTML
{% extends "base.html" %}
|
|
{% load i18n static %}
|
|
{% load crispy_forms_filters %}
|
|
{% block title %}
|
|
{% trans 'Sale Order' %}
|
|
{% endblock %}
|
|
|
|
{% block customCSS %}
|
|
<style>
|
|
/* Custom styling */
|
|
.form-section {
|
|
background-color: #f8f9fa;
|
|
border-radius: 0.5rem;
|
|
padding: 1.5rem;
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
|
|
.form-section-header {
|
|
border-bottom: 1px solid #dee2e6;
|
|
padding-bottom: 0.75rem;
|
|
margin-bottom: 1.5rem;
|
|
color: #0d6efd;
|
|
}
|
|
|
|
.required-field::after {
|
|
content: " *";
|
|
color: #dc3545;
|
|
}
|
|
|
|
.search-select {
|
|
position: relative;
|
|
}
|
|
|
|
.search-select input {
|
|
padding-right: 2.5rem;
|
|
}
|
|
|
|
.search-select .search-icon {
|
|
position: absolute;
|
|
right: 1rem;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
color: #6c757d;
|
|
}
|
|
|
|
.currency-input {
|
|
position: relative;
|
|
}
|
|
|
|
.currency-input .currency-symbol {
|
|
position: absolute;
|
|
left: 1rem;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
color: #6c757d;
|
|
}
|
|
|
|
.currency-input input {
|
|
padding-left: 2rem;
|
|
}
|
|
|
|
.form-actions {
|
|
background-color: #f8f9fa;
|
|
padding: 1rem;
|
|
border-radius: 0.5rem;
|
|
position: sticky;
|
|
bottom: 1rem;
|
|
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.1);
|
|
}
|
|
</style>
|
|
{% endblock customCSS %}
|
|
|
|
{% block content %}
|
|
|
|
<div class="row justify-content-center mb-4">
|
|
<div class="col-lg-10">
|
|
<div class="card shadow">
|
|
<div class="card-header bg-primary text-white">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<h2 class="h4 mb-0">
|
|
<i class="fas fa-file-invoice me-2"></i> New Sale Order
|
|
</h2>
|
|
<div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
<form id="saleOrderForm" method="post">
|
|
{% csrf_token %}
|
|
<!-- Basic Information Section -->
|
|
<div class="form-section">
|
|
<h4 class="form-section-header">
|
|
<i class="fas fa-info-circle me-2"></i> Basic Information
|
|
</h4>
|
|
|
|
<div class="row g-3">
|
|
<!-- Estimate -->
|
|
<div class="col-md-6">
|
|
{{form.estimate|as_crispy_field}}
|
|
</div>
|
|
|
|
<!-- Opportunity -->
|
|
<div class="col-md-6">
|
|
{{form.opportunity|as_crispy_field}}
|
|
</div>
|
|
|
|
<!-- Customer -->
|
|
<div class="col-md-6">
|
|
{% if form.customer %}
|
|
{{form.customer|as_crispy_field}}
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Vehicle -->
|
|
<div class="col-md-6">
|
|
<label for="car" class="form-label required-field">Vehicles</label>
|
|
<ul class="list-group">
|
|
{% for car in data.cars %}
|
|
<li class="list-group-item d-flex justify-content-around align-items-center">
|
|
<span class="badge bg-info rounded-pill">{{ car.make }}</span>
|
|
<span class="badge bg-info rounded-pill">{{ car.model }}</span>
|
|
<span class="badge bg-info rounded-pill">{{ car.year }}</span>
|
|
<span class="badge bg-info rounded-pill">{{ car.vin }}</span>
|
|
</li>
|
|
{% endfor %}
|
|
</ul>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<!-- Status -->
|
|
<div class="col-md-6">
|
|
{{form.status|as_crispy_field}}
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Financial Details Section -->
|
|
<div class="form-section">
|
|
<h4 class="form-section-header">
|
|
<i class="fas fa-money-bill-wave me-2"></i> Financial Details
|
|
</h4>
|
|
</div>
|
|
|
|
<!-- Delivery Information Section -->
|
|
<div class="form-section">
|
|
<h4 class="form-section-header">
|
|
<i class="fas fa-truck me-2"></i> Delivery Information
|
|
</h4>
|
|
|
|
<div class="row g-3">
|
|
<!-- Expected Delivery Date -->
|
|
<div class="col-md-6">
|
|
{{form.order_date|as_crispy_field}}
|
|
</div>
|
|
<div class="col-md-6">
|
|
{{form.expected_delivery_date|as_crispy_field}}
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<!-- Comments -->
|
|
<div class="col-12">
|
|
<label for="comments" class="form-label">Comments</label>
|
|
<textarea class="form-control" id="comments" rows="3" placeholder="Enter any additional comments..."></textarea>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Form Actions -->
|
|
<div class="form-actions mt-4">
|
|
<div class="d-flex justify-content-between">
|
|
<a href="{% url 'estimate_detail' request.dealer.slug estimate.pk %}" type="button" class="btn btn-phoenix-secondary">
|
|
<i class="fas fa-times me-2"></i> Cancel
|
|
</a>
|
|
<div>
|
|
|
|
<button type="submit" class="btn btn-phoenix-primary">
|
|
<i class="fas fa-check-circle me-2"></i> Submit Order
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{% endblock %}
|
|
{% block customJS %}
|
|
<!-- Custom JavaScript -->
|
|
<script>
|
|
/*
|
|
// Calculate financial totals
|
|
function calculateTotals() {
|
|
const agreedPrice = parseFloat(document.getElementById('agreed_price').value) || 0;
|
|
const downPayment = parseFloat(document.getElementById('down_payment_amount').value) || 0;
|
|
const tradeInValue = parseFloat(document.getElementById('trade_in_value').value) || 0;
|
|
const loanAmount = parseFloat(document.getElementById('loan_amount').value) || 0;
|
|
|
|
// Calculate total paid amount
|
|
const totalPaid = downPayment + tradeInValue + loanAmount;
|
|
document.getElementById('total_paid_amount').value = totalPaid.toFixed(2);
|
|
|
|
// Calculate remaining balance
|
|
const remainingBalance = agreedPrice - totalPaid;
|
|
document.getElementById('remaining_balance').value = remainingBalance > 0 ? remainingBalance.toFixed(2) : '0.00';
|
|
}
|
|
|
|
// Show/hide cancellation fields based on status
|
|
function toggleCancellationFields() {
|
|
const status = document.getElementById('status').value;
|
|
const cancellationFields = document.getElementById('cancellationFields');
|
|
const cancellationReasonFields = document.getElementById('cancellationReasonFields');
|
|
|
|
if (status === 'CANCELLED') {
|
|
cancellationFields.style.display = 'block';
|
|
cancellationReasonFields.style.display = 'block';
|
|
} else {
|
|
cancellationFields.style.display = 'none';
|
|
cancellationReasonFields.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
// Set current datetime for order date
|
|
function setCurrentDateTime() {
|
|
const now = new Date();
|
|
const year = now.getFullYear();
|
|
const month = String(now.getMonth() + 1).padStart(2, '0');
|
|
const day = String(now.getDate()).padStart(2, '0');
|
|
const hours = String(now.getHours()).padStart(2, '0');
|
|
const minutes = String(now.getMinutes()).padStart(2, '0');
|
|
|
|
document.getElementById('order_date').value = `${year}-${month}-${day}T${hours}:${minutes}`;
|
|
}
|
|
|
|
// Initialize form
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Set current datetime
|
|
setCurrentDateTime();
|
|
|
|
// Add event listeners for financial calculations
|
|
document.getElementById('agreed_price').addEventListener('change', calculateTotals);
|
|
document.getElementById('down_payment_amount').addEventListener('change', calculateTotals);
|
|
document.getElementById('trade_in_value').addEventListener('change', calculateTotals);
|
|
document.getElementById('loan_amount').addEventListener('change', calculateTotals);
|
|
|
|
// Add event listener for status change
|
|
document.getElementById('status').addEventListener('change', toggleCancellationFields);
|
|
|
|
// Form submission
|
|
document.getElementById('saleOrderForm').addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
// In a real application, this would submit the form data to the server
|
|
alert('Sale order would be submitted here');
|
|
// window.location.href = '/sale-orders/';
|
|
});
|
|
});*/
|
|
</script>
|
|
{% endblock customJS %} |