update
This commit is contained in:
parent
a4665842c9
commit
38d22db6f4
BIN
AGDAR_CENTRE_QUOTATION.docx
Normal file
BIN
AGDAR_CENTRE_QUOTATION.docx
Normal file
Binary file not shown.
422
AGDAR_CENTRE_QUOTATION.html
Normal file
422
AGDAR_CENTRE_QUOTATION.html
Normal file
@ -0,0 +1,422 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Quotation - Agdar Centre</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
background: #f5f5f5;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
background: white;
|
||||
padding: 40px;
|
||||
box-shadow: 0 0 20px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 40px;
|
||||
padding-bottom: 20px;
|
||||
border-bottom: 3px solid #007bff;
|
||||
}
|
||||
|
||||
.company-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.company-name {
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
color: #007bff;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.company-details {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.quotation-info {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.quotation-title {
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.quotation-number {
|
||||
font-size: 16px;
|
||||
color: #666;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.quotation-date {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.client-section {
|
||||
margin-bottom: 30px;
|
||||
padding: 20px;
|
||||
background: #f8f9fa;
|
||||
border-left: 4px solid #007bff;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #007bff;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.client-name {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.items-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.items-table thead {
|
||||
background: #007bff;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.items-table th {
|
||||
padding: 12px;
|
||||
text-align: left;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.items-table td {
|
||||
padding: 12px;
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
}
|
||||
|
||||
.items-table tbody tr:hover {
|
||||
background: #f8f9fa;
|
||||
}
|
||||
|
||||
.text-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.totals-section {
|
||||
margin-left: auto;
|
||||
width: 400px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.total-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 10px 0;
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
}
|
||||
|
||||
.total-row.subtotal {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.total-row.vat {
|
||||
font-size: 16px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.total-row.grand-total {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
border-top: 2px solid #007bff;
|
||||
border-bottom: 3px double #007bff;
|
||||
padding: 15px 0;
|
||||
color: #007bff;
|
||||
}
|
||||
|
||||
.payment-terms {
|
||||
margin-bottom: 30px;
|
||||
padding: 20px;
|
||||
background: #fff3cd;
|
||||
border-left: 4px solid #ffc107;
|
||||
}
|
||||
|
||||
.payment-schedule {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.payment-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 8px 0;
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
}
|
||||
|
||||
.payment-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.payment-label {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.payment-amount {
|
||||
font-weight: bold;
|
||||
color: #007bff;
|
||||
}
|
||||
|
||||
.terms-conditions {
|
||||
margin-bottom: 30px;
|
||||
padding: 20px;
|
||||
background: #f8f9fa;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.terms-conditions ul {
|
||||
margin-left: 20px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.terms-conditions li {
|
||||
margin-bottom: 8px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.validity {
|
||||
padding: 15px;
|
||||
background: #d1ecf1;
|
||||
border-left: 4px solid #17a2b8;
|
||||
margin-bottom: 30px;
|
||||
font-weight: 600;
|
||||
color: #0c5460;
|
||||
}
|
||||
|
||||
.footer {
|
||||
margin-top: 40px;
|
||||
padding-top: 20px;
|
||||
border-top: 2px solid #dee2e6;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.signature-section {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 60px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.signature-box {
|
||||
width: 45%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.signature-line {
|
||||
border-top: 2px solid #333;
|
||||
margin-top: 60px;
|
||||
padding-top: 10px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.contact-info {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
@media print {
|
||||
body {
|
||||
background: white;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.container {
|
||||
box-shadow: none;
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<!-- Header -->
|
||||
<div class="header">
|
||||
<div class="company-info">
|
||||
<div class="company-name">AGDAR CENTRE</div>
|
||||
<div class="company-details">
|
||||
Multidisciplinary Healthcare Services<br>
|
||||
Kingdom of Saudi Arabia<br>
|
||||
VAT No: 300000000000003
|
||||
</div>
|
||||
</div>
|
||||
<div class="quotation-info">
|
||||
<div class="quotation-title">QUOTATION</div>
|
||||
<div class="quotation-number">Quote #: QT-2025-001</div>
|
||||
<div class="quotation-date">Date: November 30, 2025</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Client Information -->
|
||||
<div class="client-section">
|
||||
<div class="section-title">QUOTATION FOR:</div>
|
||||
<div class="client-name">Agdar Centre - Solution Implementation</div>
|
||||
</div>
|
||||
|
||||
<!-- Validity Notice -->
|
||||
<div class="validity">
|
||||
⏰ This quotation is valid for 30 days from the date of issue
|
||||
</div>
|
||||
|
||||
<!-- Items Table -->
|
||||
<table class="items-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 10%">#</th>
|
||||
<th style="width: 50%">Description</th>
|
||||
<th style="width: 15%" class="text-center">Quantity</th>
|
||||
<th style="width: 25%" class="text-right">Amount (SAR)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td>
|
||||
<strong>Healthcare Management Solution</strong><br>
|
||||
<span style="color: #666; font-size: 14px;">
|
||||
Complete implementation of multidisciplinary healthcare management system including:
|
||||
<ul style="margin-top: 8px; margin-left: 20px; font-size: 13px;">
|
||||
<li>Patient Management System</li>
|
||||
<li>Appointment Scheduling & Management</li>
|
||||
<li>Clinical Documentation (ABA, OT, SLP, Psychology, Medical, Nursing)</li>
|
||||
<li>Financial & Billing System with ZATCA E-Invoice Integration</li>
|
||||
<li>Package Management & Scheduling</li>
|
||||
<li>Multi-Disciplinary Team (MDT) Collaboration</li>
|
||||
<li>Notifications & Communication System</li>
|
||||
<li>Reporting & Analytics</li>
|
||||
<li>User Management & Access Control</li>
|
||||
</ul>
|
||||
</span>
|
||||
</td>
|
||||
<td class="text-center">1</td>
|
||||
<td class="text-right">50,000.00</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Totals -->
|
||||
<div class="totals-section">
|
||||
<div class="total-row subtotal">
|
||||
<span>Subtotal:</span>
|
||||
<span>50,000.00 SAR</span>
|
||||
</div>
|
||||
<div class="total-row vat">
|
||||
<span>VAT (15%):</span>
|
||||
<span>7,500.00 SAR</span>
|
||||
</div>
|
||||
<div class="total-row grand-total">
|
||||
<span>TOTAL AMOUNT:</span>
|
||||
<span>57,500.00 SAR</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Payment Terms -->
|
||||
<div class="payment-terms">
|
||||
<div class="section-title">💳 PAYMENT TERMS</div>
|
||||
<div class="payment-schedule">
|
||||
<div class="payment-item">
|
||||
<span class="payment-label">Down Payment (30%):</span>
|
||||
<span class="payment-amount">17,250.00 SAR</span>
|
||||
</div>
|
||||
<div class="payment-item">
|
||||
<span class="payment-label">Month 1 Payment:</span>
|
||||
<span class="payment-amount">13,416.67 SAR</span>
|
||||
</div>
|
||||
<div class="payment-item">
|
||||
<span class="payment-label">Month 2 Payment:</span>
|
||||
<span class="payment-amount">13,416.67 SAR</span>
|
||||
</div>
|
||||
<div class="payment-item">
|
||||
<span class="payment-label">Month 3 Payment (Final):</span>
|
||||
<span class="payment-amount">13,416.66 SAR</span>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-top: 15px; padding-top: 15px; border-top: 1px solid #dee2e6; font-size: 14px; color: #666;">
|
||||
<strong>Payment Schedule:</strong><br>
|
||||
• 30% down payment due upon acceptance of quotation<br>
|
||||
• Remaining 70% (40,250.00 SAR) to be paid in 3 equal monthly installments<br>
|
||||
• Each installment approximately 13,416.67 SAR
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Terms & Conditions -->
|
||||
<div class="terms-conditions">
|
||||
<div class="section-title">📋 TERMS & CONDITIONS</div>
|
||||
<ul>
|
||||
<li>This quotation is valid for 30 days from the date of issue</li>
|
||||
<li>Prices are in Saudi Riyals (SAR) and include 15% VAT</li>
|
||||
<li>Down payment of 30% is required to commence work</li>
|
||||
<li>Monthly installments are due on the same date each month</li>
|
||||
<li>Late payment may incur additional charges as per agreement</li>
|
||||
<li>All payments should be made via bank transfer or approved payment methods</li>
|
||||
<li>Implementation timeline will be confirmed upon contract signing</li>
|
||||
<li>Training and support included as per service agreement</li>
|
||||
<li>Warranty and maintenance terms as per separate agreement</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Signature Section -->
|
||||
<div class="signature-section">
|
||||
<div class="signature-box">
|
||||
<div class="signature-line">
|
||||
Prepared By<br>
|
||||
Agdar Centre
|
||||
</div>
|
||||
</div>
|
||||
<div class="signature-box">
|
||||
<div class="signature-line">
|
||||
Accepted By<br>
|
||||
Client Signature & Date
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="footer">
|
||||
<div class="contact-info">
|
||||
<strong>AGDAR CENTRE</strong><br>
|
||||
Kingdom of Saudi Arabia<br>
|
||||
Email: info@agdarcentre.com | Phone: +966 XX XXX XXXX<br>
|
||||
VAT Registration Number: 300000000000003
|
||||
</div>
|
||||
<div style="margin-top: 20px; font-size: 12px; color: #999;">
|
||||
Thank you for your business!
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
@ -573,13 +573,28 @@ def handle_appointment_no_show(appointment: Appointment):
|
||||
- Update patient statistics
|
||||
- Consider automatic rescheduling policy
|
||||
"""
|
||||
from datetime import datetime, time
|
||||
from core.tasks import send_email_task
|
||||
|
||||
# Convert scheduled_time to time object if it's a string
|
||||
if isinstance(appointment.scheduled_time, str):
|
||||
time_obj = datetime.strptime(appointment.scheduled_time, '%H:%M').time()
|
||||
else:
|
||||
time_obj = appointment.scheduled_time
|
||||
|
||||
# Get scheduled datetime
|
||||
scheduled_datetime = datetime.combine(
|
||||
appointment.scheduled_date,
|
||||
time_obj
|
||||
)
|
||||
|
||||
# Notify provider
|
||||
if appointment.provider:
|
||||
create_notification_task.delay(
|
||||
user_id=str(appointment.provider.id),
|
||||
user_id=str(appointment.provider.user.id),
|
||||
title="Patient No-Show",
|
||||
message=f"Patient {appointment.patient.full_name_en} did not show up for "
|
||||
f"appointment on {appointment.start_at.strftime('%B %d, %Y at %I:%M %p')}",
|
||||
f"appointment on {scheduled_datetime.strftime('%B %d, %Y at %I:%M %p')}",
|
||||
notification_type='WARNING',
|
||||
related_object_type='appointment',
|
||||
related_object_id=str(appointment.id),
|
||||
@ -587,13 +602,11 @@ def handle_appointment_no_show(appointment: Appointment):
|
||||
|
||||
# Send notification to patient
|
||||
if appointment.patient.email:
|
||||
from core.tasks import send_email_task
|
||||
|
||||
send_email_task.delay(
|
||||
subject="Missed Appointment",
|
||||
message=f"Dear {appointment.patient.full_name_en},\n\n"
|
||||
f"We noticed you missed your appointment on "
|
||||
f"{appointment.start_at.strftime('%B %d, %Y at %I:%M %p')}.\n\n"
|
||||
f"{scheduled_datetime.strftime('%B %d, %Y at %I:%M %p')}.\n\n"
|
||||
f"Please contact us to reschedule.\n\n"
|
||||
f"Best regards,\nTenhal Healthcare Team",
|
||||
recipient_list=[appointment.patient.email],
|
||||
|
||||
293
create_quotation_docx.py
Normal file
293
create_quotation_docx.py
Normal file
@ -0,0 +1,293 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Script to generate Agdar Centre Quotation in Word format
|
||||
"""
|
||||
|
||||
from docx import Document
|
||||
from docx.shared import Inches, Pt, RGBColor
|
||||
from docx.enum.text import WD_ALIGN_PARAGRAPH
|
||||
from docx.oxml.ns import qn
|
||||
from docx.oxml import OxmlElement
|
||||
|
||||
def add_horizontal_line(paragraph):
|
||||
"""Add a horizontal line to a paragraph"""
|
||||
p = paragraph._p
|
||||
pPr = p.get_or_add_pPr()
|
||||
pBdr = OxmlElement('w:pBdr')
|
||||
bottom = OxmlElement('w:bottom')
|
||||
bottom.set(qn('w:val'), 'single')
|
||||
bottom.set(qn('w:sz'), '12')
|
||||
bottom.set(qn('w:space'), '1')
|
||||
bottom.set(qn('w:color'), '0070C0')
|
||||
pBdr.append(bottom)
|
||||
pPr.append(pBdr)
|
||||
|
||||
def create_quotation():
|
||||
"""Create the quotation document"""
|
||||
doc = Document()
|
||||
|
||||
# Set document margins
|
||||
sections = doc.sections
|
||||
for section in sections:
|
||||
section.top_margin = Inches(0.75)
|
||||
section.bottom_margin = Inches(0.75)
|
||||
section.left_margin = Inches(1)
|
||||
section.right_margin = Inches(1)
|
||||
|
||||
# Header Section
|
||||
header_table = doc.add_table(rows=1, cols=2)
|
||||
header_table.autofit = False
|
||||
header_table.allow_autofit = False
|
||||
|
||||
# Left column - Company Info
|
||||
left_cell = header_table.rows[0].cells[0]
|
||||
company_name = left_cell.paragraphs[0]
|
||||
company_name.text = "AGDAR CENTRE"
|
||||
company_name.runs[0].font.size = Pt(24)
|
||||
company_name.runs[0].font.bold = True
|
||||
company_name.runs[0].font.color.rgb = RGBColor(0, 112, 192)
|
||||
|
||||
company_details = left_cell.add_paragraph("Multidisciplinary Healthcare Services")
|
||||
company_details.runs[0].font.size = Pt(10)
|
||||
company_details.runs[0].font.color.rgb = RGBColor(102, 102, 102)
|
||||
|
||||
company_details2 = left_cell.add_paragraph("Kingdom of Saudi Arabia")
|
||||
company_details2.runs[0].font.size = Pt(10)
|
||||
company_details2.runs[0].font.color.rgb = RGBColor(102, 102, 102)
|
||||
|
||||
company_details3 = left_cell.add_paragraph("VAT No: 300000000000003")
|
||||
company_details3.runs[0].font.size = Pt(10)
|
||||
company_details3.runs[0].font.color.rgb = RGBColor(102, 102, 102)
|
||||
|
||||
# Right column - Quotation Info
|
||||
right_cell = header_table.rows[0].cells[1]
|
||||
quote_title = right_cell.paragraphs[0]
|
||||
quote_title.text = "QUOTATION"
|
||||
quote_title.alignment = WD_ALIGN_PARAGRAPH.RIGHT
|
||||
quote_title.runs[0].font.size = Pt(28)
|
||||
quote_title.runs[0].font.bold = True
|
||||
|
||||
quote_number = right_cell.add_paragraph("Quote #: QT-2025-001")
|
||||
quote_number.alignment = WD_ALIGN_PARAGRAPH.RIGHT
|
||||
quote_number.runs[0].font.size = Pt(11)
|
||||
quote_number.runs[0].font.color.rgb = RGBColor(102, 102, 102)
|
||||
|
||||
quote_date = right_cell.add_paragraph("Date: November 30, 2025")
|
||||
quote_date.alignment = WD_ALIGN_PARAGRAPH.RIGHT
|
||||
quote_date.runs[0].font.size = Pt(10)
|
||||
quote_date.runs[0].font.color.rgb = RGBColor(102, 102, 102)
|
||||
|
||||
# Add horizontal line
|
||||
line_para = doc.add_paragraph()
|
||||
add_horizontal_line(line_para)
|
||||
|
||||
doc.add_paragraph() # Spacing
|
||||
|
||||
# Client Section
|
||||
client_heading = doc.add_paragraph("QUOTATION FOR:")
|
||||
client_heading.runs[0].font.size = Pt(12)
|
||||
client_heading.runs[0].font.bold = True
|
||||
client_heading.runs[0].font.color.rgb = RGBColor(0, 112, 192)
|
||||
|
||||
client_name = doc.add_paragraph("Agdar Centre - Solution Implementation")
|
||||
client_name.runs[0].font.size = Pt(14)
|
||||
client_name.runs[0].font.bold = True
|
||||
|
||||
doc.add_paragraph() # Spacing
|
||||
|
||||
# Validity Notice
|
||||
validity = doc.add_paragraph("⏰ This quotation is valid for 30 days from the date of issue")
|
||||
validity.runs[0].font.size = Pt(11)
|
||||
validity.runs[0].font.bold = True
|
||||
validity.runs[0].font.color.rgb = RGBColor(12, 84, 96)
|
||||
|
||||
doc.add_paragraph() # Spacing
|
||||
|
||||
# Items Table
|
||||
items_table = doc.add_table(rows=1, cols=4)
|
||||
items_table.style = 'Light Grid Accent 1'
|
||||
|
||||
# Header row
|
||||
header_cells = items_table.rows[0].cells
|
||||
header_cells[0].text = "#"
|
||||
header_cells[1].text = "Description"
|
||||
header_cells[2].text = "Quantity"
|
||||
header_cells[3].text = "Amount (SAR)"
|
||||
|
||||
# Format header
|
||||
for cell in header_cells:
|
||||
cell.paragraphs[0].runs[0].font.bold = True
|
||||
cell.paragraphs[0].runs[0].font.color.rgb = RGBColor(255, 255, 255)
|
||||
shading_elm = OxmlElement('w:shd')
|
||||
shading_elm.set(qn('w:fill'), '0070C0')
|
||||
cell._element.get_or_add_tcPr().append(shading_elm)
|
||||
|
||||
header_cells[2].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||
header_cells[3].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.RIGHT
|
||||
|
||||
# Data row
|
||||
row_cells = items_table.add_row().cells
|
||||
row_cells[0].text = "1"
|
||||
|
||||
# Description with bullet points
|
||||
desc_para = row_cells[1].paragraphs[0]
|
||||
desc_para.add_run("Healthcare Management Solution\n").bold = True
|
||||
desc_para.add_run("\nComplete implementation of multidisciplinary healthcare management system including:\n").font.size = Pt(10)
|
||||
|
||||
features = [
|
||||
"Patient Management System",
|
||||
"Appointment Scheduling & Management",
|
||||
"Clinical Documentation (ABA, OT, SLP, Psychology, Medical, Nursing)",
|
||||
"Financial & Billing System with ZATCA E-Invoice Integration",
|
||||
"Package Management & Scheduling",
|
||||
"Multi-Disciplinary Team (MDT) Collaboration",
|
||||
"Notifications & Communication System",
|
||||
"Reporting & Analytics",
|
||||
"User Management & Access Control"
|
||||
]
|
||||
|
||||
for feature in features:
|
||||
feature_para = row_cells[1].add_paragraph(f"• {feature}", style='List Bullet')
|
||||
feature_para.runs[0].font.size = Pt(9)
|
||||
|
||||
row_cells[2].text = "1"
|
||||
row_cells[2].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||
|
||||
row_cells[3].text = "50,000.00"
|
||||
row_cells[3].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.RIGHT
|
||||
|
||||
doc.add_paragraph() # Spacing
|
||||
|
||||
# Totals Section
|
||||
totals_table = doc.add_table(rows=3, cols=2)
|
||||
totals_table.alignment = WD_ALIGN_PARAGRAPH.RIGHT
|
||||
|
||||
# Subtotal
|
||||
totals_table.rows[0].cells[0].text = "Subtotal:"
|
||||
totals_table.rows[0].cells[1].text = "50,000.00 SAR"
|
||||
totals_table.rows[0].cells[1].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.RIGHT
|
||||
|
||||
# VAT
|
||||
totals_table.rows[1].cells[0].text = "VAT (15%):"
|
||||
totals_table.rows[1].cells[1].text = "7,500.00 SAR"
|
||||
totals_table.rows[1].cells[1].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.RIGHT
|
||||
|
||||
# Total
|
||||
totals_table.rows[2].cells[0].text = "TOTAL AMOUNT:"
|
||||
totals_table.rows[2].cells[0].paragraphs[0].runs[0].font.bold = True
|
||||
totals_table.rows[2].cells[0].paragraphs[0].runs[0].font.size = Pt(14)
|
||||
totals_table.rows[2].cells[0].paragraphs[0].runs[0].font.color.rgb = RGBColor(0, 112, 192)
|
||||
|
||||
totals_table.rows[2].cells[1].text = "57,500.00 SAR"
|
||||
totals_table.rows[2].cells[1].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.RIGHT
|
||||
totals_table.rows[2].cells[1].paragraphs[0].runs[0].font.bold = True
|
||||
totals_table.rows[2].cells[1].paragraphs[0].runs[0].font.size = Pt(14)
|
||||
totals_table.rows[2].cells[1].paragraphs[0].runs[0].font.color.rgb = RGBColor(0, 112, 192)
|
||||
|
||||
doc.add_paragraph() # Spacing
|
||||
|
||||
# Payment Terms Section
|
||||
payment_heading = doc.add_paragraph("💳 PAYMENT TERMS")
|
||||
payment_heading.runs[0].font.size = Pt(12)
|
||||
payment_heading.runs[0].font.bold = True
|
||||
payment_heading.runs[0].font.color.rgb = RGBColor(0, 112, 192)
|
||||
|
||||
# Payment Schedule Table
|
||||
payment_table = doc.add_table(rows=5, cols=2)
|
||||
payment_table.style = 'Light List Accent 1'
|
||||
|
||||
payments = [
|
||||
("Down Payment (30%):", "17,250.00 SAR"),
|
||||
("Month 1 Payment:", "13,416.67 SAR"),
|
||||
("Month 2 Payment:", "13,416.67 SAR"),
|
||||
("Month 3 Payment (Final):", "13,416.66 SAR")
|
||||
]
|
||||
|
||||
for i, (label, amount) in enumerate(payments):
|
||||
payment_table.rows[i].cells[0].text = label
|
||||
payment_table.rows[i].cells[0].paragraphs[0].runs[0].font.bold = True
|
||||
payment_table.rows[i].cells[1].text = amount
|
||||
payment_table.rows[i].cells[1].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.RIGHT
|
||||
payment_table.rows[i].cells[1].paragraphs[0].runs[0].font.bold = True
|
||||
payment_table.rows[i].cells[1].paragraphs[0].runs[0].font.color.rgb = RGBColor(0, 112, 192)
|
||||
|
||||
doc.add_paragraph()
|
||||
|
||||
# Payment Schedule Details
|
||||
schedule_para = doc.add_paragraph()
|
||||
schedule_para.add_run("Payment Schedule:\n").bold = True
|
||||
schedule_para.add_run("• 30% down payment due upon acceptance of quotation\n")
|
||||
schedule_para.add_run("• Remaining 70% (40,250.00 SAR) to be paid in 3 equal monthly installments\n")
|
||||
schedule_para.add_run("• Each installment approximately 13,416.67 SAR")
|
||||
for run in schedule_para.runs[1:]:
|
||||
run.font.size = Pt(10)
|
||||
|
||||
doc.add_paragraph() # Spacing
|
||||
|
||||
# Terms & Conditions
|
||||
terms_heading = doc.add_paragraph("📋 TERMS & CONDITIONS")
|
||||
terms_heading.runs[0].font.size = Pt(12)
|
||||
terms_heading.runs[0].font.bold = True
|
||||
terms_heading.runs[0].font.color.rgb = RGBColor(0, 112, 192)
|
||||
|
||||
terms = [
|
||||
"This quotation is valid for 30 days from the date of issue",
|
||||
"Prices are in Saudi Riyals (SAR) and include 15% VAT",
|
||||
"Down payment of 30% is required to commence work",
|
||||
"Monthly installments are due on the same date each month",
|
||||
"Late payment may incur additional charges as per agreement",
|
||||
"All payments should be made via bank transfer or approved payment methods",
|
||||
"Implementation timeline will be confirmed upon contract signing",
|
||||
"Training and support included as per service agreement",
|
||||
"Warranty and maintenance terms as per separate agreement"
|
||||
]
|
||||
|
||||
for term in terms:
|
||||
term_para = doc.add_paragraph(term, style='List Bullet')
|
||||
term_para.runs[0].font.size = Pt(10)
|
||||
|
||||
doc.add_paragraph() # Spacing
|
||||
doc.add_paragraph() # Spacing
|
||||
|
||||
# Signature Section
|
||||
sig_table = doc.add_table(rows=3, cols=2)
|
||||
|
||||
# Prepared By
|
||||
sig_table.rows[0].cells[0].text = ""
|
||||
sig_table.rows[1].cells[0].text = "_" * 30
|
||||
sig_table.rows[2].cells[0].text = "Prepared By\nAgdar Centre"
|
||||
sig_table.rows[2].cells[0].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||
sig_table.rows[2].cells[0].paragraphs[0].runs[0].font.bold = True
|
||||
|
||||
# Accepted By
|
||||
sig_table.rows[0].cells[1].text = ""
|
||||
sig_table.rows[1].cells[1].text = "_" * 30
|
||||
sig_table.rows[1].cells[1].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||
sig_table.rows[2].cells[1].text = "Accepted By\nClient Signature & Date"
|
||||
sig_table.rows[2].cells[1].paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||
sig_table.rows[2].cells[1].paragraphs[0].runs[0].font.bold = True
|
||||
|
||||
doc.add_paragraph() # Spacing
|
||||
|
||||
# Footer
|
||||
footer_line = doc.add_paragraph()
|
||||
add_horizontal_line(footer_line)
|
||||
|
||||
footer = doc.add_paragraph()
|
||||
footer.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||
footer.add_run("AGDAR CENTRE\n").bold = True
|
||||
footer.add_run("Kingdom of Saudi Arabia\n")
|
||||
footer.add_run("Email: info@agdarcentre.com | Phone: +966 XX XXX XXXX\n")
|
||||
footer.add_run("VAT Registration Number: 300000000000003\n\n")
|
||||
footer.add_run("Thank you for your business!").italic = True
|
||||
|
||||
for run in footer.runs:
|
||||
run.font.size = Pt(9)
|
||||
run.font.color.rgb = RGBColor(102, 102, 102)
|
||||
|
||||
# Save document
|
||||
doc.save('AGDAR_CENTRE_QUOTATION.docx')
|
||||
print("✅ Quotation document created successfully: AGDAR_CENTRE_QUOTATION.docx")
|
||||
|
||||
if __name__ == "__main__":
|
||||
create_quotation()
|
||||
BIN
db.sqlite3
BIN
db.sqlite3
Binary file not shown.
9012
logs/django.log
9012
logs/django.log
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -203,12 +203,17 @@ class MDTContributionCreateView(LoginRequiredMixin, CreateView):
|
||||
kwargs['mdt_note'] = self.mdt_note
|
||||
return kwargs
|
||||
|
||||
def get_success_url(self):
|
||||
"""Return URL to redirect to after successful form submission."""
|
||||
return reverse_lazy('mdt:mdt_note_detail', kwargs={'pk': self.mdt_note.pk})
|
||||
|
||||
def form_valid(self, form):
|
||||
"""Set contributor and mdt_note before saving."""
|
||||
form.instance.mdt_note = self.mdt_note
|
||||
form.instance.contributor = self.request.user
|
||||
|
||||
response = super().form_valid(form)
|
||||
# Save the form
|
||||
self.object = form.save()
|
||||
|
||||
# Handle mentions
|
||||
mention_users = form.cleaned_data.get('mention_users', [])
|
||||
|
||||
BIN
media/consents/signatures/signature_000045_20251201_131517.png
Normal file
BIN
media/consents/signatures/signature_000045_20251201_131517.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
BIN
media/consents/signatures/signature_000045_20251201_131531.png
Normal file
BIN
media/consents/signatures/signature_000045_20251201_131531.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
Loading…
x
Reference in New Issue
Block a user