forked from morrning/hesabixCore
890 lines
22 KiB
Vue
890 lines
22 KiB
Vue
|
|
<template>
|
|||
|
|
<div class="template-library">
|
|||
|
|
<v-dialog v-model="showLibrary" max-width="800px">
|
|||
|
|
<v-card>
|
|||
|
|
<v-card-title class="d-flex align-center">
|
|||
|
|
<v-icon class="mr-3">mdi-library</v-icon>
|
|||
|
|
کتابخانه قالبهای آماده
|
|||
|
|
</v-card-title>
|
|||
|
|
|
|||
|
|
<v-card-text>
|
|||
|
|
<v-tabs v-model="activeCategory" color="primary">
|
|||
|
|
<v-tab value="sales">فروش</v-tab>
|
|||
|
|
<v-tab value="purchase">خرید</v-tab>
|
|||
|
|
<v-tab value="return">برگشت</v-tab>
|
|||
|
|
<v-tab value="custom">سفارشی</v-tab>
|
|||
|
|
</v-tabs>
|
|||
|
|
|
|||
|
|
<v-window v-model="activeCategory" class="mt-4">
|
|||
|
|
<v-window-item value="sales">
|
|||
|
|
<div class="templates-grid">
|
|||
|
|
<div
|
|||
|
|
v-for="template in salesTemplates"
|
|||
|
|
:key="template.id"
|
|||
|
|
class="template-card"
|
|||
|
|
@click="selectTemplate(template)"
|
|||
|
|
>
|
|||
|
|
<div class="template-preview">
|
|||
|
|
<img :src="template.preview" :alt="template.name" />
|
|||
|
|
</div>
|
|||
|
|
<div class="template-info">
|
|||
|
|
<h4>{{ template.name }}</h4>
|
|||
|
|
<p>{{ template.description }}</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</v-window-item>
|
|||
|
|
|
|||
|
|
<v-window-item value="purchase">
|
|||
|
|
<div class="templates-grid">
|
|||
|
|
<div
|
|||
|
|
v-for="template in purchaseTemplates"
|
|||
|
|
:key="template.id"
|
|||
|
|
class="template-card"
|
|||
|
|
@click="selectTemplate(template)"
|
|||
|
|
>
|
|||
|
|
<div class="template-preview">
|
|||
|
|
<img :src="template.preview" :alt="template.name" />
|
|||
|
|
</div>
|
|||
|
|
<div class="template-info">
|
|||
|
|
<h4>{{ template.name }}</h4>
|
|||
|
|
<p>{{ template.description }}</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</v-window-item>
|
|||
|
|
|
|||
|
|
<v-window-item value="return">
|
|||
|
|
<div class="templates-grid">
|
|||
|
|
<div
|
|||
|
|
v-for="template in returnTemplates"
|
|||
|
|
:key="template.id"
|
|||
|
|
class="template-card"
|
|||
|
|
@click="selectTemplate(template)"
|
|||
|
|
>
|
|||
|
|
<div class="template-preview">
|
|||
|
|
<img :src="template.preview" :alt="template.name" />
|
|||
|
|
</div>
|
|||
|
|
<div class="template-info">
|
|||
|
|
<h4>{{ template.name }}</h4>
|
|||
|
|
<p>{{ template.description }}</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</v-window-item>
|
|||
|
|
|
|||
|
|
<v-window-item value="custom">
|
|||
|
|
<div class="templates-grid">
|
|||
|
|
<div
|
|||
|
|
v-for="template in customTemplates"
|
|||
|
|
:key="template.id"
|
|||
|
|
class="template-card"
|
|||
|
|
@click="selectTemplate(template)"
|
|||
|
|
>
|
|||
|
|
<div class="template-preview">
|
|||
|
|
<img :src="template.preview" :alt="template.name" />
|
|||
|
|
</div>
|
|||
|
|
<div class="template-info">
|
|||
|
|
<h4>{{ template.name }}</h4>
|
|||
|
|
<p>{{ template.description }}</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</v-window-item>
|
|||
|
|
</v-window>
|
|||
|
|
</v-card-text>
|
|||
|
|
|
|||
|
|
<v-card-actions>
|
|||
|
|
<v-spacer></v-spacer>
|
|||
|
|
<v-btn @click="showLibrary = false" variant="text">انصراف</v-btn>
|
|||
|
|
</v-card-actions>
|
|||
|
|
</v-card>
|
|||
|
|
</v-dialog>
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
export default {
|
|||
|
|
name: 'TemplateLibrary',
|
|||
|
|
props: {
|
|||
|
|
modelValue: {
|
|||
|
|
type: Boolean,
|
|||
|
|
default: false
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
emits: ['update:modelValue', 'select-template'],
|
|||
|
|
data() {
|
|||
|
|
return {
|
|||
|
|
activeCategory: 'sales',
|
|||
|
|
salesTemplates: [
|
|||
|
|
{
|
|||
|
|
id: 'sales-standard',
|
|||
|
|
name: 'قالب استاندارد فروش',
|
|||
|
|
description: 'قالب ساده و کاربردی برای فاکتورهای فروش',
|
|||
|
|
preview: '/templates/sales-standard.png',
|
|||
|
|
code: this.getStandardSalesTemplate()
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
id: 'sales-luxury',
|
|||
|
|
name: 'قالب لوکس فروش',
|
|||
|
|
description: 'قالب زیبا و حرفهای برای فاکتورهای فروش',
|
|||
|
|
preview: '/templates/sales-luxury.png',
|
|||
|
|
code: this.getLuxurySalesTemplate()
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
purchaseTemplates: [
|
|||
|
|
{
|
|||
|
|
id: 'purchase-standard',
|
|||
|
|
name: 'قالب استاندارد خرید',
|
|||
|
|
description: 'قالب مناسب برای فاکتورهای خرید',
|
|||
|
|
preview: '/templates/purchase-standard.png',
|
|||
|
|
code: this.getStandardPurchaseTemplate()
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
returnTemplates: [
|
|||
|
|
{
|
|||
|
|
id: 'return-standard',
|
|||
|
|
name: 'قالب استاندارد برگشت',
|
|||
|
|
description: 'قالب مناسب برای برگشت از فروش/خرید',
|
|||
|
|
preview: '/templates/return-standard.png',
|
|||
|
|
code: this.getStandardReturnTemplate()
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
customTemplates: [
|
|||
|
|
{
|
|||
|
|
id: 'custom-minimal',
|
|||
|
|
name: 'قالب مینیمال',
|
|||
|
|
description: 'قالب ساده و تمیز',
|
|||
|
|
preview: '/templates/custom-minimal.png',
|
|||
|
|
code: this.getMinimalTemplate()
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
computed: {
|
|||
|
|
showLibrary: {
|
|||
|
|
get() {
|
|||
|
|
return this.modelValue
|
|||
|
|
},
|
|||
|
|
set(value) {
|
|||
|
|
this.$emit('update:modelValue', value)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
methods: {
|
|||
|
|
selectTemplate(template) {
|
|||
|
|
this.$emit('select-template', template)
|
|||
|
|
this.showLibrary = false
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
getStandardSalesTemplate() {
|
|||
|
|
return `<!DOCTYPE html>
|
|||
|
|
<html lang="fa" direction="rtl">
|
|||
|
|
<head>
|
|||
|
|
<style>
|
|||
|
|
.invoice-container {
|
|||
|
|
font-family: Arial, sans-serif;
|
|||
|
|
max-width: 800px;
|
|||
|
|
margin: 0 auto;
|
|||
|
|
padding: 20px;
|
|||
|
|
}
|
|||
|
|
.header {
|
|||
|
|
text-align: center;
|
|||
|
|
border-bottom: 2px solid #333;
|
|||
|
|
padding-bottom: 20px;
|
|||
|
|
margin-bottom: 20px;
|
|||
|
|
}
|
|||
|
|
.info-section {
|
|||
|
|
display: grid;
|
|||
|
|
grid-template-columns: 1fr 1fr;
|
|||
|
|
gap: 20px;
|
|||
|
|
margin-bottom: 20px;
|
|||
|
|
}
|
|||
|
|
.info-box {
|
|||
|
|
border: 1px solid #ddd;
|
|||
|
|
padding: 15px;
|
|||
|
|
border-radius: 5px;
|
|||
|
|
}
|
|||
|
|
.info-box h3 {
|
|||
|
|
margin: 0 0 10px 0;
|
|||
|
|
background: #f5f5f5;
|
|||
|
|
padding: 5px;
|
|||
|
|
border-radius: 3px;
|
|||
|
|
}
|
|||
|
|
.items-table {
|
|||
|
|
width: 100%;
|
|||
|
|
border-collapse: collapse;
|
|||
|
|
margin-bottom: 20px;
|
|||
|
|
}
|
|||
|
|
.items-table th,
|
|||
|
|
.items-table td {
|
|||
|
|
border: 1px solid #ddd;
|
|||
|
|
padding: 8px;
|
|||
|
|
text-align: center;
|
|||
|
|
}
|
|||
|
|
.items-table th {
|
|||
|
|
background: #f5f5f5;
|
|||
|
|
font-weight: bold;
|
|||
|
|
}
|
|||
|
|
.totals {
|
|||
|
|
text-align: right;
|
|||
|
|
margin-bottom: 20px;
|
|||
|
|
}
|
|||
|
|
.totals div {
|
|||
|
|
margin: 5px 0;
|
|||
|
|
}
|
|||
|
|
.signatures {
|
|||
|
|
display: grid;
|
|||
|
|
grid-template-columns: 1fr 1fr;
|
|||
|
|
gap: 20px;
|
|||
|
|
margin-top: 40px;
|
|||
|
|
}
|
|||
|
|
.signature-box {
|
|||
|
|
border: 1px solid #ddd;
|
|||
|
|
padding: 20px;
|
|||
|
|
text-align: center;
|
|||
|
|
min-height: 100px;
|
|||
|
|
}
|
|||
|
|
</style>
|
|||
|
|
</head>
|
|||
|
|
<body>
|
|||
|
|
<div class="invoice-container">
|
|||
|
|
<div class="header">
|
|||
|
|
<h1>{{ business.name }}</h1>
|
|||
|
|
<h2>صورتحساب فروش کالا و خدمات</h2>
|
|||
|
|
<p>شماره: {{ doc.code }} | تاریخ: {{ doc.date }}</p>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="info-section">
|
|||
|
|
<div class="info-box">
|
|||
|
|
<h3>فروشنده</h3>
|
|||
|
|
<p><strong>نام:</strong> {{ business.name }}</p>
|
|||
|
|
<p><strong>تلفن:</strong> {{ business.tel }}</p>
|
|||
|
|
<p><strong>آدرس:</strong> {{ business.address }}</p>
|
|||
|
|
</div>
|
|||
|
|
<div class="info-box">
|
|||
|
|
<h3>خریدار</h3>
|
|||
|
|
{% if person %}
|
|||
|
|
<p><strong>نام:</strong> {{ person.name }}</p>
|
|||
|
|
<p><strong>موبایل:</strong> {{ person.mobile }}</p>
|
|||
|
|
<p><strong>آدرس:</strong> {{ person.address }}</p>
|
|||
|
|
{% else %}
|
|||
|
|
<p>مشتری ناشناس</p>
|
|||
|
|
{% endif %}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<table class="items-table">
|
|||
|
|
<thead>
|
|||
|
|
<tr>
|
|||
|
|
<th>ردیف</th>
|
|||
|
|
<th>کالا/خدمات</th>
|
|||
|
|
<th>شرح</th>
|
|||
|
|
<th>تعداد</th>
|
|||
|
|
<th>فی واحد</th>
|
|||
|
|
<th>تخفیف</th>
|
|||
|
|
<th>مالیات</th>
|
|||
|
|
<th>مبلغ کل</th>
|
|||
|
|
</tr>
|
|||
|
|
</thead>
|
|||
|
|
<tbody>
|
|||
|
|
{% for item in rows %}
|
|||
|
|
<tr>
|
|||
|
|
<td>{{ loop.index }}</td>
|
|||
|
|
<td>{{ item.commodity.name ?? '-' }}</td>
|
|||
|
|
<td>{{ item.des }}</td>
|
|||
|
|
<td>{{ item.commodityCount }}</td>
|
|||
|
|
<td>{{ (item.bs / item.commodityCount) | number_format(0, '.', ',') }}</td>
|
|||
|
|
<td>
|
|||
|
|
{% if item.showPercentDiscount %}
|
|||
|
|
{{ item.discountPercent }}%
|
|||
|
|
{% else %}
|
|||
|
|
{{ item.discount | number_format(0, '.', ',') }}
|
|||
|
|
{% endif %}
|
|||
|
|
</td>
|
|||
|
|
<td>{{ item.tax | number_format(0, '.', ',') }}</td>
|
|||
|
|
<td>{{ item.bs | number_format(0, '.', ',') }}</td>
|
|||
|
|
</tr>
|
|||
|
|
{% endfor %}
|
|||
|
|
</tbody>
|
|||
|
|
</table>
|
|||
|
|
|
|||
|
|
<div class="totals">
|
|||
|
|
{% if discount %}
|
|||
|
|
<div><strong>جمع تخفیف:</strong> {{ discount | number_format(0, '.', ',') }}</div>
|
|||
|
|
{% endif %}
|
|||
|
|
{% if transfer %}
|
|||
|
|
<div><strong>هزینه ارسال:</strong> {{ transfer | number_format(0, '.', ',') }}</div>
|
|||
|
|
{% endif %}
|
|||
|
|
<div><strong>جمع کل:</strong> {{ doc.amount | number_format(0, '.', ',') }}</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{% if note %}
|
|||
|
|
<div style="margin-top: 20px; padding: 10px; background: #f9f9f9; border-radius: 5px;">
|
|||
|
|
<strong>یادداشت:</strong> {{ note }}
|
|||
|
|
</div>
|
|||
|
|
{% endif %}
|
|||
|
|
|
|||
|
|
<div class="signatures">
|
|||
|
|
<div class="signature-box">
|
|||
|
|
<h4>مهر و امضا خریدار</h4>
|
|||
|
|
</div>
|
|||
|
|
<div class="signature-box">
|
|||
|
|
<h4>مهر و امضا فروشنده</h4>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</body>
|
|||
|
|
</html>`
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
getLuxurySalesTemplate() {
|
|||
|
|
return `<!DOCTYPE html>
|
|||
|
|
<html lang="fa" direction="rtl">
|
|||
|
|
<head>
|
|||
|
|
<style>
|
|||
|
|
body {
|
|||
|
|
font-family: 'Tahoma', Arial, sans-serif;
|
|||
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|||
|
|
margin: 0;
|
|||
|
|
padding: 20px;
|
|||
|
|
}
|
|||
|
|
.invoice-container {
|
|||
|
|
max-width: 900px;
|
|||
|
|
margin: 0 auto;
|
|||
|
|
background: white;
|
|||
|
|
border-radius: 15px;
|
|||
|
|
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
|
|||
|
|
overflow: hidden;
|
|||
|
|
}
|
|||
|
|
.header {
|
|||
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|||
|
|
color: white;
|
|||
|
|
padding: 30px;
|
|||
|
|
text-align: center;
|
|||
|
|
}
|
|||
|
|
.header h1 {
|
|||
|
|
margin: 0;
|
|||
|
|
font-size: 28px;
|
|||
|
|
font-weight: 300;
|
|||
|
|
}
|
|||
|
|
.header h2 {
|
|||
|
|
margin: 10px 0;
|
|||
|
|
font-size: 20px;
|
|||
|
|
font-weight: 300;
|
|||
|
|
}
|
|||
|
|
.invoice-info {
|
|||
|
|
background: #f8f9fa;
|
|||
|
|
padding: 20px;
|
|||
|
|
display: grid;
|
|||
|
|
grid-template-columns: 1fr 1fr;
|
|||
|
|
gap: 30px;
|
|||
|
|
}
|
|||
|
|
.info-box {
|
|||
|
|
background: white;
|
|||
|
|
padding: 20px;
|
|||
|
|
border-radius: 10px;
|
|||
|
|
box-shadow: 0 5px 15px rgba(0,0,0,0.08);
|
|||
|
|
}
|
|||
|
|
.info-box h3 {
|
|||
|
|
margin: 0 0 15px 0;
|
|||
|
|
color: #667eea;
|
|||
|
|
font-size: 16px;
|
|||
|
|
border-bottom: 2px solid #667eea;
|
|||
|
|
padding-bottom: 5px;
|
|||
|
|
}
|
|||
|
|
.items-table {
|
|||
|
|
width: 100%;
|
|||
|
|
border-collapse: collapse;
|
|||
|
|
margin: 20px 0;
|
|||
|
|
}
|
|||
|
|
.items-table th {
|
|||
|
|
background: #667eea;
|
|||
|
|
color: white;
|
|||
|
|
padding: 15px 10px;
|
|||
|
|
font-weight: 500;
|
|||
|
|
}
|
|||
|
|
.items-table td {
|
|||
|
|
padding: 12px 10px;
|
|||
|
|
border-bottom: 1px solid #eee;
|
|||
|
|
}
|
|||
|
|
.items-table tr:nth-child(even) {
|
|||
|
|
background: #f8f9fa;
|
|||
|
|
}
|
|||
|
|
.totals {
|
|||
|
|
background: #f8f9fa;
|
|||
|
|
padding: 20px;
|
|||
|
|
text-align: right;
|
|||
|
|
}
|
|||
|
|
.total-row {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
margin: 5px 0;
|
|||
|
|
padding: 5px 0;
|
|||
|
|
}
|
|||
|
|
.final-total {
|
|||
|
|
border-top: 2px solid #667eea;
|
|||
|
|
font-size: 18px;
|
|||
|
|
font-weight: bold;
|
|||
|
|
color: #667eea;
|
|||
|
|
}
|
|||
|
|
.signatures {
|
|||
|
|
display: grid;
|
|||
|
|
grid-template-columns: 1fr 1fr;
|
|||
|
|
gap: 30px;
|
|||
|
|
padding: 30px;
|
|||
|
|
}
|
|||
|
|
.signature-box {
|
|||
|
|
border: 2px dashed #667eea;
|
|||
|
|
padding: 30px;
|
|||
|
|
text-align: center;
|
|||
|
|
border-radius: 10px;
|
|||
|
|
background: #f8f9fa;
|
|||
|
|
}
|
|||
|
|
</style>
|
|||
|
|
</head>
|
|||
|
|
<body>
|
|||
|
|
<div class="invoice-container">
|
|||
|
|
<div class="header">
|
|||
|
|
<h1>{{ business.name }}</h1>
|
|||
|
|
<h2>صورتحساب فروش کالا و خدمات</h2>
|
|||
|
|
<p>شماره: {{ doc.code }} | تاریخ: {{ doc.date }}</p>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="invoice-info">
|
|||
|
|
<div class="info-box">
|
|||
|
|
<h3>اطلاعات فروشنده</h3>
|
|||
|
|
<p><strong>نام:</strong> {{ business.name }}</p>
|
|||
|
|
<p><strong>تلفن:</strong> {{ business.tel }}</p>
|
|||
|
|
<p><strong>آدرس:</strong> {{ business.address }}</p>
|
|||
|
|
</div>
|
|||
|
|
<div class="info-box">
|
|||
|
|
<h3>اطلاعات خریدار</h3>
|
|||
|
|
{% if person %}
|
|||
|
|
<p><strong>نام:</strong> {{ person.name }}</p>
|
|||
|
|
<p><strong>موبایل:</strong> {{ person.mobile }}</p>
|
|||
|
|
<p><strong>آدرس:</strong> {{ person.address }}</p>
|
|||
|
|
{% else %}
|
|||
|
|
<p>مشتری ناشناس</p>
|
|||
|
|
{% endif %}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div style="padding: 0 20px;">
|
|||
|
|
<table class="items-table">
|
|||
|
|
<thead>
|
|||
|
|
<tr>
|
|||
|
|
<th>ردیف</th>
|
|||
|
|
<th>کالا/خدمات</th>
|
|||
|
|
<th>شرح</th>
|
|||
|
|
<th>تعداد</th>
|
|||
|
|
<th>فی واحد</th>
|
|||
|
|
<th>تخفیف</th>
|
|||
|
|
<th>مالیات</th>
|
|||
|
|
<th>مبلغ کل</th>
|
|||
|
|
</tr>
|
|||
|
|
</thead>
|
|||
|
|
<tbody>
|
|||
|
|
{% for item in rows %}
|
|||
|
|
<tr>
|
|||
|
|
<td>{{ loop.index }}</td>
|
|||
|
|
<td>{{ item.commodity.name ?? '-' }}</td>
|
|||
|
|
<td>{{ item.des }}</td>
|
|||
|
|
<td>{{ item.commodityCount }}</td>
|
|||
|
|
<td>{{ (item.bs / item.commodityCount) | number_format(0, '.', ',') }}</td>
|
|||
|
|
<td>
|
|||
|
|
{% if item.showPercentDiscount %}
|
|||
|
|
{{ item.discountPercent }}%
|
|||
|
|
{% else %}
|
|||
|
|
{{ item.discount | number_format(0, '.', ',') }}
|
|||
|
|
{% endif %}
|
|||
|
|
</td>
|
|||
|
|
<td>{{ item.tax | number_format(0, '.', ',') }}</td>
|
|||
|
|
<td>{{ item.bs | number_format(0, '.', ',') }}</td>
|
|||
|
|
</tr>
|
|||
|
|
{% endfor %}
|
|||
|
|
</tbody>
|
|||
|
|
</table>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="totals">
|
|||
|
|
{% if discount %}
|
|||
|
|
<div class="total-row">
|
|||
|
|
<span>جمع تخفیف:</span>
|
|||
|
|
<span>{{ discount | number_format(0, '.', ',') }}</span>
|
|||
|
|
</div>
|
|||
|
|
{% endif %}
|
|||
|
|
{% if transfer %}
|
|||
|
|
<div class="total-row">
|
|||
|
|
<span>هزینه ارسال:</span>
|
|||
|
|
<span>{{ transfer | number_format(0, '.', ',') }}</span>
|
|||
|
|
</div>
|
|||
|
|
{% endif %}
|
|||
|
|
<div class="total-row final-total">
|
|||
|
|
<span>جمع کل:</span>
|
|||
|
|
<span>{{ doc.amount | number_format(0, '.', ',') }}</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{% if note %}
|
|||
|
|
<div style="margin: 20px; padding: 15px; background: #e3f2fd; border-radius: 10px; border-right: 4px solid #2196f3;">
|
|||
|
|
<strong>یادداشت:</strong> {{ note }}
|
|||
|
|
</div>
|
|||
|
|
{% endif %}
|
|||
|
|
|
|||
|
|
<div class="signatures">
|
|||
|
|
<div class="signature-box">
|
|||
|
|
<h4>مهر و امضا خریدار</h4>
|
|||
|
|
</div>
|
|||
|
|
<div class="signature-box">
|
|||
|
|
<h4>مهر و امضا فروشنده</h4>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</body>
|
|||
|
|
</html>`
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
getStandardPurchaseTemplate() {
|
|||
|
|
return `<!DOCTYPE html>
|
|||
|
|
<html lang="fa" direction="rtl">
|
|||
|
|
<head>
|
|||
|
|
<style>
|
|||
|
|
.invoice-container {
|
|||
|
|
font-family: Arial, sans-serif;
|
|||
|
|
max-width: 800px;
|
|||
|
|
margin: 0 auto;
|
|||
|
|
padding: 20px;
|
|||
|
|
}
|
|||
|
|
.header {
|
|||
|
|
text-align: center;
|
|||
|
|
border-bottom: 2px solid #333;
|
|||
|
|
padding-bottom: 20px;
|
|||
|
|
margin-bottom: 20px;
|
|||
|
|
}
|
|||
|
|
.items-table {
|
|||
|
|
width: 100%;
|
|||
|
|
border-collapse: collapse;
|
|||
|
|
margin-bottom: 20px;
|
|||
|
|
}
|
|||
|
|
.items-table th,
|
|||
|
|
.items-table td {
|
|||
|
|
border: 1px solid #ddd;
|
|||
|
|
padding: 8px;
|
|||
|
|
text-align: center;
|
|||
|
|
}
|
|||
|
|
.items-table th {
|
|||
|
|
background: #f5f5f5;
|
|||
|
|
font-weight: bold;
|
|||
|
|
}
|
|||
|
|
</style>
|
|||
|
|
</head>
|
|||
|
|
<body>
|
|||
|
|
<div class="invoice-container">
|
|||
|
|
<div class="header">
|
|||
|
|
<h1>{{ business.name }}</h1>
|
|||
|
|
<h2>فاکتور خرید</h2>
|
|||
|
|
<p>شماره: {{ doc.code }} | تاریخ: {{ doc.date }}</p>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<table class="items-table">
|
|||
|
|
<thead>
|
|||
|
|
<tr>
|
|||
|
|
<th>ردیف</th>
|
|||
|
|
<th>کالا/خدمات</th>
|
|||
|
|
<th>شرح</th>
|
|||
|
|
<th>تعداد</th>
|
|||
|
|
<th>بدهکار</th>
|
|||
|
|
<th>بستانکار</th>
|
|||
|
|
</tr>
|
|||
|
|
</thead>
|
|||
|
|
<tbody>
|
|||
|
|
{% for item in rows %}
|
|||
|
|
<tr>
|
|||
|
|
<td>{{ loop.index }}</td>
|
|||
|
|
<td>{{ item.commodity.name ?? '-' }}</td>
|
|||
|
|
<td>{{ item.des }}</td>
|
|||
|
|
<td>{{ item.commodityCount }}</td>
|
|||
|
|
<td>{{ item.bd | number_format(0, '.', ',') }}</td>
|
|||
|
|
<td>{{ item.bs | number_format(0, '.', ',') }}</td>
|
|||
|
|
</tr>
|
|||
|
|
{% endfor %}
|
|||
|
|
</tbody>
|
|||
|
|
</table>
|
|||
|
|
</div>
|
|||
|
|
</body>
|
|||
|
|
</html>`
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
getStandardReturnTemplate() {
|
|||
|
|
return `<!DOCTYPE html>
|
|||
|
|
<html lang="fa" direction="rtl">
|
|||
|
|
<head>
|
|||
|
|
<style>
|
|||
|
|
.invoice-container {
|
|||
|
|
font-family: Arial, sans-serif;
|
|||
|
|
max-width: 800px;
|
|||
|
|
margin: 0 auto;
|
|||
|
|
padding: 20px;
|
|||
|
|
}
|
|||
|
|
.header {
|
|||
|
|
text-align: center;
|
|||
|
|
border-bottom: 2px solid #333;
|
|||
|
|
padding-bottom: 20px;
|
|||
|
|
margin-bottom: 20px;
|
|||
|
|
}
|
|||
|
|
.items-table {
|
|||
|
|
width: 100%;
|
|||
|
|
border-collapse: collapse;
|
|||
|
|
margin-bottom: 20px;
|
|||
|
|
}
|
|||
|
|
.items-table th,
|
|||
|
|
.items-table td {
|
|||
|
|
border: 1px solid #ddd;
|
|||
|
|
padding: 8px;
|
|||
|
|
text-align: center;
|
|||
|
|
}
|
|||
|
|
.items-table th {
|
|||
|
|
background: #f5f5f5;
|
|||
|
|
font-weight: bold;
|
|||
|
|
}
|
|||
|
|
</style>
|
|||
|
|
</head>
|
|||
|
|
<body>
|
|||
|
|
<div class="invoice-container">
|
|||
|
|
<div class="header">
|
|||
|
|
<h1>{{ business.name }}</h1>
|
|||
|
|
<h2>برگشت از فروش</h2>
|
|||
|
|
<p>شماره: {{ doc.code }} | تاریخ: {{ doc.date }}</p>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<table class="items-table">
|
|||
|
|
<thead>
|
|||
|
|
<tr>
|
|||
|
|
<th>ردیف</th>
|
|||
|
|
<th>کالا/خدمات</th>
|
|||
|
|
<th>شرح</th>
|
|||
|
|
<th>تعداد</th>
|
|||
|
|
<th>تخفیف</th>
|
|||
|
|
<th>مالیات</th>
|
|||
|
|
<th>مبلغ کل</th>
|
|||
|
|
</tr>
|
|||
|
|
</thead>
|
|||
|
|
<tbody>
|
|||
|
|
{% for item in rows %}
|
|||
|
|
<tr>
|
|||
|
|
<td>{{ loop.index }}</td>
|
|||
|
|
<td>{{ item.commodity.name ?? '-' }}</td>
|
|||
|
|
<td>{{ item.des }}</td>
|
|||
|
|
<td>{{ item.commodityCount }}</td>
|
|||
|
|
<td>
|
|||
|
|
{% if item.showPercentDiscount %}
|
|||
|
|
{{ item.discountPercent }}%
|
|||
|
|
{% else %}
|
|||
|
|
{{ item.discount | number_format(0, '.', ',') }}
|
|||
|
|
{% endif %}
|
|||
|
|
</td>
|
|||
|
|
<td>{{ item.tax | number_format(0, '.', ',') }}</td>
|
|||
|
|
<td>{{ item.bs | number_format(0, '.', ',') }}</td>
|
|||
|
|
</tr>
|
|||
|
|
{% endfor %}
|
|||
|
|
</tbody>
|
|||
|
|
</table>
|
|||
|
|
</div>
|
|||
|
|
</body>
|
|||
|
|
</html>`
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
getMinimalTemplate() {
|
|||
|
|
return `<!DOCTYPE html>
|
|||
|
|
<html lang="fa" direction="rtl">
|
|||
|
|
<head>
|
|||
|
|
<style>
|
|||
|
|
body {
|
|||
|
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
|||
|
|
margin: 0;
|
|||
|
|
padding: 40px;
|
|||
|
|
background: #fafafa;
|
|||
|
|
}
|
|||
|
|
.invoice-container {
|
|||
|
|
max-width: 600px;
|
|||
|
|
margin: 0 auto;
|
|||
|
|
background: white;
|
|||
|
|
padding: 40px;
|
|||
|
|
border-radius: 8px;
|
|||
|
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
|||
|
|
}
|
|||
|
|
.header {
|
|||
|
|
text-align: center;
|
|||
|
|
margin-bottom: 40px;
|
|||
|
|
}
|
|||
|
|
.header h1 {
|
|||
|
|
margin: 0;
|
|||
|
|
color: #333;
|
|||
|
|
font-weight: 300;
|
|||
|
|
}
|
|||
|
|
.info {
|
|||
|
|
display: grid;
|
|||
|
|
grid-template-columns: 1fr 1fr;
|
|||
|
|
gap: 30px;
|
|||
|
|
margin-bottom: 30px;
|
|||
|
|
}
|
|||
|
|
.info-section h3 {
|
|||
|
|
margin: 0 0 15px 0;
|
|||
|
|
color: #666;
|
|||
|
|
font-size: 14px;
|
|||
|
|
text-transform: uppercase;
|
|||
|
|
letter-spacing: 1px;
|
|||
|
|
}
|
|||
|
|
.items-table {
|
|||
|
|
width: 100%;
|
|||
|
|
border-collapse: collapse;
|
|||
|
|
margin-bottom: 30px;
|
|||
|
|
}
|
|||
|
|
.items-table th {
|
|||
|
|
background: #f8f9fa;
|
|||
|
|
padding: 12px 8px;
|
|||
|
|
text-align: left;
|
|||
|
|
font-weight: 500;
|
|||
|
|
color: #666;
|
|||
|
|
border-bottom: 2px solid #eee;
|
|||
|
|
}
|
|||
|
|
.items-table td {
|
|||
|
|
padding: 12px 8px;
|
|||
|
|
border-bottom: 1px solid #eee;
|
|||
|
|
}
|
|||
|
|
.total {
|
|||
|
|
text-align: right;
|
|||
|
|
font-size: 18px;
|
|||
|
|
font-weight: 500;
|
|||
|
|
color: #333;
|
|||
|
|
border-top: 2px solid #333;
|
|||
|
|
padding-top: 15px;
|
|||
|
|
}
|
|||
|
|
</style>
|
|||
|
|
</head>
|
|||
|
|
<body>
|
|||
|
|
<div class="invoice-container">
|
|||
|
|
<div class="header">
|
|||
|
|
<h1>{{ business.name }}</h1>
|
|||
|
|
<p>شماره: {{ doc.code }} | تاریخ: {{ doc.date }}</p>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="info">
|
|||
|
|
<div class="info-section">
|
|||
|
|
<h3>فروشنده</h3>
|
|||
|
|
<p>{{ business.name }}</p>
|
|||
|
|
<p>{{ business.tel }}</p>
|
|||
|
|
<p>{{ business.address }}</p>
|
|||
|
|
</div>
|
|||
|
|
<div class="info-section">
|
|||
|
|
<h3>خریدار</h3>
|
|||
|
|
{% if person %}
|
|||
|
|
<p>{{ person.name }}</p>
|
|||
|
|
<p>{{ person.mobile }}</p>
|
|||
|
|
<p>{{ person.address }}</p>
|
|||
|
|
{% else %}
|
|||
|
|
<p>مشتری ناشناس</p>
|
|||
|
|
{% endif %}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<table class="items-table">
|
|||
|
|
<thead>
|
|||
|
|
<tr>
|
|||
|
|
<th>کالا/خدمات</th>
|
|||
|
|
<th>تعداد</th>
|
|||
|
|
<th>فی واحد</th>
|
|||
|
|
<th>مبلغ کل</th>
|
|||
|
|
</tr>
|
|||
|
|
</thead>
|
|||
|
|
<tbody>
|
|||
|
|
{% for item in rows %}
|
|||
|
|
<tr>
|
|||
|
|
<td>{{ item.commodity.name ?? '-' }}</td>
|
|||
|
|
<td>{{ item.commodityCount }}</td>
|
|||
|
|
<td>{{ (item.bs / item.commodityCount) | number_format(0, '.', ',') }}</td>
|
|||
|
|
<td>{{ item.bs | number_format(0, '.', ',') }}</td>
|
|||
|
|
</tr>
|
|||
|
|
{% endfor %}
|
|||
|
|
</tbody>
|
|||
|
|
</table>
|
|||
|
|
|
|||
|
|
<div class="total">
|
|||
|
|
جمع کل: {{ doc.amount | number_format(0, '.', ',') }}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</body>
|
|||
|
|
</html>`
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style scoped>
|
|||
|
|
.template-library {
|
|||
|
|
/* Component styles */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.templates-grid {
|
|||
|
|
display: grid;
|
|||
|
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
|||
|
|
gap: 20px;
|
|||
|
|
padding: 20px 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.template-card {
|
|||
|
|
border: 1px solid #e0e0e0;
|
|||
|
|
border-radius: 8px;
|
|||
|
|
overflow: hidden;
|
|||
|
|
cursor: pointer;
|
|||
|
|
transition: all 0.3s ease;
|
|||
|
|
background: white;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.template-card:hover {
|
|||
|
|
transform: translateY(-2px);
|
|||
|
|
box-shadow: 0 8px 25px rgba(0,0,0,0.15);
|
|||
|
|
border-color: #2196f3;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.template-preview {
|
|||
|
|
height: 150px;
|
|||
|
|
background: #f5f5f5;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
border-bottom: 1px solid #e0e0e0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.template-preview img {
|
|||
|
|
max-width: 100%;
|
|||
|
|
max-height: 100%;
|
|||
|
|
object-fit: cover;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.template-info {
|
|||
|
|
padding: 16px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.template-info h4 {
|
|||
|
|
margin: 0 0 8px 0;
|
|||
|
|
font-size: 16px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
color: #333;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.template-info p {
|
|||
|
|
margin: 0;
|
|||
|
|
font-size: 14px;
|
|||
|
|
color: #666;
|
|||
|
|
line-height: 1.4;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* Responsive */
|
|||
|
|
@media (max-width: 768px) {
|
|||
|
|
.templates-grid {
|
|||
|
|
grid-template-columns: 1fr;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</style>
|