add some option and bug fix in business list and wallet controll

This commit is contained in:
Hesabix 2025-04-03 10:46:18 +00:00
parent 58b97be2ae
commit b794ea76b7
8 changed files with 678 additions and 292 deletions

View file

@ -112,4 +112,25 @@ export default {
background: rgba(0, 0, 0, 0.4); background: rgba(0, 0, 0, 0.4);
/* رنگ هنگام هاور */ /* رنگ هنگام هاور */
} }
.v-data-table {
overflow-x: auto;
}
.expanded-row {
background-color: #f5f5f5 !important;
padding: 8px;
}
.custom-header {
background-color: #213e8b !important;
color: #ffffff !important;
text-align: center !important;
}
.v-data-table, .v-data-table-server, .v-data-table-header__content {
margin: 0 auto;
width: fit-content;
text-align: center !important;
}
</style> </style>

View file

@ -3,8 +3,12 @@
<v-text-field v-model="displayDate" :label="label" prepend-inner-icon="mdi-calendar" persistent-placeholder <v-text-field v-model="displayDate" :label="label" prepend-inner-icon="mdi-calendar" persistent-placeholder
:class="['v-date-input', `date-input-${uniqueId}`]" :rules="rules" @input="updateDateFromInput" @click:prepend="togglePicker"></v-text-field> :class="['v-date-input', `date-input-${uniqueId}`]" :rules="rules" @input="updateDateFromInput" @click:prepend="togglePicker"></v-text-field>
<date-picker v-model="displayDate" type="date" format="jYYYY/jMM/jDD" display-format="jYYYY/jMM/jDD" <date-picker v-model="displayDate" type="date" format="jYYYY/jMM/jDD" display-format="jYYYY/jMM/jDD"
:min="minDatePersian" :max="maxDatePersian" :custom-input="`.date-input-${uniqueId}`" :input-mode="true" :min="ignoreYearRange ? (min || null) : minDatePersian"
:editable="pickerActive" @close="pickerActive = false"></date-picker> :max="ignoreYearRange ? null : maxDatePersian"
:custom-input="`.date-input-${uniqueId}`"
:input-mode="true"
:editable="pickerActive"
@close="pickerActive = false"></date-picker>
</div> </div>
</template> </template>
@ -26,6 +30,14 @@ export default {
type: Array, type: Array,
default: () => [], default: () => [],
}, },
ignoreYearRange: {
type: Boolean,
default: false
},
min: {
type: String,
default: null
}
}, },
data() { data() {
return { return {
@ -79,15 +91,7 @@ export default {
updateDateFromInput(value) { updateDateFromInput(value) {
// بررسی و اعتبارسنجی تاریخ وارد شده توسط کاربر // بررسی و اعتبارسنجی تاریخ وارد شده توسط کاربر
if (value && moment(value, 'YYYY/MM/DD', 'fa', true).isValid()) { if (value && moment(value, 'YYYY/MM/DD', 'fa', true).isValid()) {
const parsedDate = moment(value, 'YYYY/MM/DD').locale('fa');
if (
parsedDate.isSameOrAfter(moment(this.minDatePersian, 'YYYY/MM/DD')) &&
parsedDate.isSameOrBefore(moment(this.maxDatePersian, 'YYYY/MM/DD'))
) {
this.displayDate = value; this.displayDate = value;
} else {
this.displayDate = ''; // یا خطا نمایش بدید
}
} }
}, },
togglePicker() { togglePicker() {

View file

@ -90,6 +90,7 @@ const fa_lang = {
} }
}, },
drawer: { drawer: {
wallets: "کیف پول‌ها",
ultimate_package: 'بسته‌های نامحدود', ultimate_package: 'بسته‌های نامحدود',
sell_chart: "فروش هفته گذشته", sell_chart: "فروش هفته گذشته",
bankaccounts_transactions: "کارت حساب بانک", bankaccounts_transactions: "کارت حساب بانک",

View file

@ -146,6 +146,14 @@ const router = createRouter({
'login': true 'login': true
} }
}, },
{
path: 'manager/wallet/list',
component: () => import('../views/user/manager/wallet/list.vue'),
meta: {
'title': 'کیف پول',
'login': true
}
},
{ {
path: 'manager/changes/list', path: 'manager/changes/list',
component: () => import('../views/user/manager/reportchange/list.vue'), component: () => import('../views/user/manager/reportchange/list.vue'),

View file

@ -970,18 +970,4 @@ export default {
.shortcut-input { .shortcut-input {
max-width: 60px; max-width: 60px;
} }
.v-data-table {
overflow-x: auto;
}
.expanded-row {
background-color: #f5f5f5 !important;
padding: 8px;
}
.custom-header {
background-color: #213e8b !important;
color: #ffffff !important;
}
</style> </style>

View file

@ -24,9 +24,6 @@
<v-tab value="2"> <v-tab value="2">
{{ $t('dialog.global_settings') }} {{ $t('dialog.global_settings') }}
</v-tab> </v-tab>
<v-tab value="3">
{{ $t('dialog.gate_pay') }}
</v-tab>
</v-tabs> </v-tabs>
</template> </template>
</v-toolbar> </v-toolbar>
@ -37,140 +34,161 @@
<v-card> <v-card>
<v-card-text> <v-card-text>
<h3 class="text-primary">اطلاعات کسب و کار</h3> <h3 class="text-primary">اطلاعات کسب و کار</h3>
<div class="row"> <v-row>
<div class="col-sm-12 col-md-6 mb-2"> <v-col cols="12" md="6">
<div class="form-floating required"> <v-text-field
<input class="form-control" type="text" v-model="content.name"> v-model="content.name"
<label class="form-label">نام کسب و کار</label> label="نام کسب و کار"
</div> variant="outlined"
</div> required
<div class="col-sm-12 col-md-6 mb-2"> density="compact"
<div class="form-floating required"> ></v-text-field>
<input class="form-control" type="text" v-model="content.legal_name"> </v-col>
<label class="form-label">نام قانونی کسب و کار</label> <v-col cols="12" md="6">
</div> <v-text-field
</div> v-model="content.legal_name"
<div class="col-sm-12 col-md-6 mb-2"> label="نام قانونی کسب و کار"
<div class="form-floating"> variant="outlined"
<input class="form-control" type="text" v-model="content.field"> required
<label>زمینه فعالیت</label> density="compact"
</div> ></v-text-field>
</div> </v-col>
<div class="col-sm-12 col-md-6 mb-2"> <v-col cols="12" md="6">
<div class="form-floating"> <v-text-field
<select v-model="content.type" class="form-select"> v-model="content.field"
<option value="شرکت">شرکت</option> label="زمینه فعالیت"
<option value="مغازه">مغازه</option> variant="outlined"
<option value="فروشگاه">فروشگاه</option> density="compact"
<option value="اتحادیه">اتحادیه</option> ></v-text-field>
<option value="باشگاه">باشگاه</option> </v-col>
<option value="موسسه">موسسه</option> <v-col cols="12" md="6">
<option value="شخصی">شخصی</option> <v-select
</select> v-model="content.type"
<label>نوع فعالیت</label> :items="['شرکت', 'مغازه', 'فروشگاه', 'اتحادیه', 'باشگاه', 'موسسه', 'شخصی']"
</div> label="نوع فعالیت"
</div> variant="outlined"
</div> density="compact"
<h3 class="text-primary">اطلاعات اقتصادی</h3> ></v-select>
<div class="row"> </v-col>
<div class="col-sm-12 col-md-6 mb-2"> </v-row>
<div class="form-floating">
<input v-model="content.shenasemeli" type="text" class="form-control"> <h3 class="text-primary mt-4">اطلاعات اقتصادی</h3>
<label class="form-label">شناسه ملی</label> <v-row>
</div> <v-col cols="12" md="6">
</div> <v-text-field
<div class="col-sm-12 col-md-6 mb-2"> v-model="content.shenasemeli"
<div class="form-floating"> label="شناسه ملی"
<input v-model="content.codeeqtesadi" type="text" class="form-control"> variant="outlined"
<label class="form-label">کد اقتصادی</label> density="compact"
</div> ></v-text-field>
</div> </v-col>
<div class="col-sm-12 col-md-6 mb-2"> <v-col cols="12" md="6">
<div class="form-floating"> <v-text-field
<input v-model="content.shomaresabt" type="text" class="form-control"> v-model="content.codeeqtesadi"
<label class="form-label">شماره ثبت</label> label="کد اقتصادی"
</div> variant="outlined"
</div> density="compact"
</div> ></v-text-field>
<h3 class="text-primary">اطلاعات تماس</h3> </v-col>
<div class="row"> <v-col cols="12" md="6">
<div class="col-sm-12 col-md-4 mb-2"> <v-text-field
<div class="form-floating"> v-model="content.shomaresabt"
<input v-model="content.country" type="text" class="form-control"> label="شماره ثبت"
<label class="form-label">کشور</label> variant="outlined"
</div> density="compact"
</div> ></v-text-field>
<div class="col-sm-12 col-md-4 mb-2"> </v-col>
<div class="form-floating"> </v-row>
<input v-model="content.ostan" type="text" id="business_new_ostan" name="business_new[ostan]"
maxlength="50" class="form-control form-control-sm"> <h3 class="text-primary mt-4">اطلاعات تماس</h3>
<label class="form-label">استان</label> <v-row>
</div> <v-col cols="12" md="4">
</div> <v-text-field
<div class="col-sm-12 col-md-4 mb-2"> v-model="content.country"
<div class="form-floating"> label="کشور"
<input v-model="content.shahrestan" type="text" id="business_new_shahr" name="business_new[shahr]" variant="outlined"
maxlength="50" class="form-control form-control-sm"> density="compact"
<label class="form-label">شهر</label> ></v-text-field>
</div> </v-col>
</div> <v-col cols="12" md="4">
<div class="col-sm-12 col-md-4 mb-2"> <v-text-field
<div class="form-floating"> v-model="content.ostan"
<input v-model="content.postalcode" type="text" id="business_new_codeposti" label="استان"
name="business_new[codeposti]" maxlength="10" class="form-control form-control-sm"> variant="outlined"
<label class="form-label">کد پستی</label> density="compact"
</div> ></v-text-field>
</div> </v-col>
<div class="col-sm-12 col-md-4 mb-2"> <v-col cols="12" md="4">
<div class="form-floating"> <v-text-field
<input v-model="content.tel" type="text" id="business_new_tel" name="business_new[tel]" v-model="content.shahrestan"
maxlength="15" class="form-control form-control-sm"> label="شهر"
<label class="form-label">تلفن</label> variant="outlined"
</div> density="compact"
</div> ></v-text-field>
<div class="col-sm-12 col-md-4 mb-2"> </v-col>
<div class="form-floating"> <v-col cols="12" md="4">
<input v-model="content.mobile" type="tel" id="business_new_fax" name="business_new[fax]" <v-text-field
maxlength="15" class="form-control form-control-sm"> v-model="content.postalcode"
<label class="form-label">موبایل</label> label="کد پستی"
</div> variant="outlined"
</div> density="compact"
</div> ></v-text-field>
<div class="row"> </v-col>
<div class="col-sm-12 col-md-12 mb-2"> <v-col cols="12" md="4">
<div class="form-floating"> <v-text-field
<input type="text" v-model="content.address" id="business_new_address" name="business_new[address]" v-model="content.tel"
maxlength="255" class="form-control form-control-sm"> label="تلفن"
<label class="form-label">آدرس</label> variant="outlined"
</div> density="compact"
</div> ></v-text-field>
</div> </v-col>
<div class="row"> <v-col cols="12" md="4">
<div class="col-sm-12 col-md-6 mb-2"> <v-text-field
<div class="form-floating"> v-model="content.mobile"
<input v-model="content.website" type="url" id="business_new_website" name="business_new[website]" label="موبایل"
inputmode="url" class="form-control form-control-sm"> variant="outlined"
<label class="form-label">وبسایت</label> density="compact"
</div> ></v-text-field>
</div> </v-col>
<div class="col-sm-12 col-md-6 mb-2"> <v-col cols="12">
<div class="form-floating"> <v-text-field
<input v-model="content.email" type="email" id="business_new_email" name="business_new[email]" v-model="content.address"
maxlength="255" class="form-control form-control-sm"> label="آدرس"
<label class="form-label">پست الکترونیکی</label> variant="outlined"
</div> density="compact"
</div> ></v-text-field>
</div> </v-col>
<h3 class="text-primary">اطلاعات مالی</h3> <v-col cols="12" md="6">
<div class="row"> <v-text-field
<div class="col-sm-12 col-md-6 mb-2"> v-model="content.website"
<div class="form-floating required"> label="وب‌سایت"
<input v-model="content.maliyatafzode" type="number" id="business_new_maliyatafzode" variant="outlined"
name="business_new[maliyatafzode]" required="required" class="form-control form-control-sm"> density="compact"
<label class="form-label">مالیات بر ارزش افزوده</label> ></v-text-field>
</div> </v-col>
</div> <v-col cols="12" md="6">
</div> <v-text-field
v-model="content.email"
label="پست الکترونیکی"
variant="outlined"
density="compact"
></v-text-field>
</v-col>
</v-row>
<h3 class="text-primary mt-4">اطلاعات مالی</h3>
<v-row>
<v-col cols="12" md="6">
<v-text-field
v-model="content.maliyatafzode"
label="مالیات بر ارزش افزوده"
type="number"
variant="outlined"
required
density="compact"
></v-text-field>
</v-col>
</v-row>
</v-card-text> </v-card-text>
</v-card> </v-card>
</v-tabs-window-item> </v-tabs-window-item>
@ -178,37 +196,34 @@
<v-card> <v-card>
<v-card-text> <v-card-text>
<h3 class="text-primary">سال مالی</h3> <h3 class="text-primary">سال مالی</h3>
<div class="row"> <v-row>
<div class="col-sm-12 col-md-6 mb-2"> <v-col cols="12" md="6">
<div class="form-control"> <Hdatepicker
<label class="form-label"> v-model="content.year.startShamsi"
<span class="text-danger">*</span> label="شروع سال مالی"
شروع سال مالی :rules="[v => !!v || 'این فیلد الزامی است']"
</label> :ignore-year-range="true"
<date-picker class="" v-model="content.year.startShamsi" format="jYYYY/jMM/jDD" />
display-format="jYYYY/jMM/jDD" /> </v-col>
</div> <v-col cols="12" md="6">
</div> <Hdatepicker
<div class="col-sm-12 col-md-6 mb-2"> v-model="content.year.endShamsi"
<div class="form-control"> label="اتمام سال مالی"
<label class="form-label"> :rules="[v => !!v || 'این فیلد الزامی است']"
<span class="text-danger">*</span> :ignore-year-range="true"
اتمام سال مالی :min="content.year.startShamsi"
</label> />
<date-picker class="" v-model="content.year.endShamsi" format="jYYYY/jMM/jDD" </v-col>
display-format="jYYYY/jMM/jDD" :min="content.year.startShamsi" /> <v-col cols="12">
</div> <v-text-field
</div> v-model="content.year.label"
<div class="col-sm-12 col-md-12"> label="عنوان سال مالی"
<div class="form-control mb-2"> variant="outlined"
<label class="form-label"> required
<span class="text-danger">*</span> density="compact"
عنوان سال مالی ></v-text-field>
</label> </v-col>
<input v-model="content.year.label" class="form-control" type="text"> </v-row>
</div>
</div>
</div>
</v-card-text> </v-card-text>
</v-card> </v-card>
</v-tabs-window-item> </v-tabs-window-item>
@ -216,108 +231,95 @@
<v-card> <v-card>
<v-card-text> <v-card-text>
<h3 class="text-primary">نمایش پیوند یکتا</h3> <h3 class="text-primary">نمایش پیوند یکتا</h3>
<div class="row"> <v-row>
<div class="col-sm-12 col-md-8 mb-2"> <v-col cols="12" md="8">
<div class="space-y-2"> <v-switch
<div class="form-check form-switch"> v-model="content.shortlinks"
<input v-model="content.shortlinks" class="form-check-input" type="checkbox"> label="فعال‌سازی پیوند‌های یکتا"
<label class="form-check-label">فعالسازی پیوندهای یکتا</label> color="primary"
<br> hide-details
<label class="text-muted">این قابلیت برای تولید پیوندهای یکتا برای ارسال به مشتری جهت مشاهده ></v-switch>
فاکتورها است.</label> <div class="text-caption text-medium-emphasis mt-1">
این قابلیت برای تولید پیوندهای یکتا برای ارسال به مشتری جهت مشاهده فاکتورها است.
</div> </div>
</div> </v-col>
</div> </v-row>
</div>
<h3 class="text-primary">دریافت مبلغ فاکتور از طریق کیف پول</h3>
<div class="row">
<div class="col-sm-12 col-md-12 mb-2">
<div class="space-y-2">
<div class="form-check form-switch">
<input @change="checkBanksExist()" v-model="content.walletEnabled" class="form-check-input"
type="checkbox">
<label class="form-check-label">فعالسازی دریافت آنلاین از طریق کیف پول</label>
<br>
<label class="text-muted">با فعال سازی این قابلیت قادر خواهید بود مبالغ فاکتورهای ثبت شده را
به صورت آنلاین از مشتریان خود دریافت کنید.</label>
</div>
</div>
<div class="row" v-show="content.walletEnabled">
<div class="col-sm-12 col-md-6">
<label class="mb-2">حساب بانکی متصل به کیف پول</label>
<div class="col">
<v-cob dir="rtl" :options="listBanks" label="name" v-model="content.walletMatchBank"
@option:deselecting="" @search:focus="" @option:selecting="">
<template #no-options="{ search, searching, loading }">
نتیجهای یافت نشد!
</template>
</v-cob>
</div>
</div>
<label class="text-muted">برای تسویه اتوماتیک به حساب انتخاب شده حتما باید تمام موارد از جمله
شماره شبا و شماره کارت و
... به درستی تکمیل شده باشد در غیر این صورت تراکنش با خطا مواجه خواهد شد.</label>
<h3 class="text-primary mt-4">دریافت مبلغ فاکتور از طریق کیف پول</h3>
<v-row>
<v-col cols="12">
<v-switch
v-model="content.walletEnabled"
label="فعال‌سازی دریافت آنلاین از طریق کیف پول"
color="primary"
@change="checkBanksExist"
hide-details
></v-switch>
<div class="text-caption text-medium-emphasis mt-1">
با فعال سازی این قابلیت قادر خواهید بود مبالغ فاکتورهای ثبت شده را به صورت آنلاین از مشتریان خود دریافت کنید.
</div> </div>
<v-row v-if="content.walletEnabled" class="mt-4">
<v-col cols="12" md="6">
<v-select
v-model="content.walletMatchBank"
:items="listBanks"
item-title="name"
item-value="id"
label="حساب بانکی متصل به کیف پول"
variant="outlined"
density="compact"
></v-select>
</v-col>
<v-col cols="12">
<div class="text-caption text-medium-emphasis">
برای تسویه اتوماتیک به حساب انتخاب شده حتما باید تمام موارد از جمله شماره شبا و شماره کارت و ... به درستی تکمیل شده باشد در غیر این صورت تراکنش با خطا مواجه خواهد شد.
</div> </div>
</v-col>
</v-row>
</v-col>
</v-row>
<h3 class="text-primary mt-4">کالا و خدمات</h3>
<v-row>
<v-col cols="12" md="8">
<v-switch
v-model="content.updateBuyPrice"
label="به روز رسانی قیمت خرید هنگام صدور فاکتور"
color="primary"
hide-details
></v-switch>
<div class="text-caption text-medium-emphasis mt-1">
با صدور فاکتور خرید یا برگشت از خرید قیمت خرید کالا و خدمات به روزرسانی خواهد شد.
</div> </div>
<h3 class="text-primary">کالا و خدمات</h3> </v-col>
<div class="row"> <v-col cols="12" md="8">
<div class="col-sm-12 col-md-8 mb-2"> <v-switch
<div class="space-y-2"> v-model="content.updateSellPrice"
<div class="form-check form-switch"> label="به روز رسانی قیمت فروش هنگام صدور فاکتور"
<input v-model="content.updateBuyPrice" class="form-check-input" type="checkbox"> color="primary"
<label class="form-check-label">به روز رسانی قیمت خرید هنگام صدور فاکتور</label> hide-details
<br> ></v-switch>
<label class="text-muted">با صدور فاکتور خرید یا برگشت از خرید قیمت خرید کالا و خدمات به <div class="text-caption text-medium-emphasis mt-1">
روزرسانی خواهد با صدور فاکتور فروش یا برگشت از فروش قیمت خرید کالا و خدمات به روزرسانی خواهد شد.
شد.</label>
</div>
</div>
</div>
<div class="col-sm-12 col-md-8 mb-2">
<div class="space-y-2">
<div class="form-check form-switch">
<input v-model="content.updateSellPrice" class="form-check-input" type="checkbox">
<label class="form-check-label">به روز رسانی قیمت فروش هنگام صدور فاکتور</label>
<br>
<label class="text-muted">با صدور فاکتور فروش یا برگشت از فروش قیمت خرید کالا و خدمات به
روزرسانی خواهد
شد.</label>
</div>
</div>
</div>
<div class="col-sm-12 col-md-8 mb-2">
<div class="space-y-2">
<div class="form-floating">
<select class="form-select" v-model="content.profitCalcType">
<option value="simple">بر اساس اختلاف قیمت خرید و فروش</option>
<option value="lis">بر اساس آخرین قیمت ورود به انبار</option>
<option value="avgis">بر اساس میانگین قیمت ورود به انبار</option>
</select>
<label for="floatingSelect">نحوه محاسبه سود فاکتور</label>
</div>
</div>
</div>
</div>
</v-card-text>
</v-card>
</v-tabs-window-item>
<v-tabs-window-item value="3">
<v-card>
<v-card-text>
<h3 class="text-primary">درگاه پرداخت زرین پال</h3>
<div class="row">
<div class="col-sm-12 col-md-8 mb-2">
<div class="form-floating required">
<input class="form-control" type="text" v-model="content.zarinpal">
<label class="form-label">کد شناسایی: مثال a1104652-18b9-4b63-911c-0a5046e61be1</label>
</div>
<label class="text-muted mt-2">برای غیر فعال کردن درگاه پرداخت آن را خالی بگذارید. در صورت اشتباه
بودن کد وارد
شده × مشتری در هنگام تسویه فاکتورها با خطا مواجه خواهد شد.</label>
</div>
</div> </div>
</v-col>
<v-col cols="12" md="8">
<v-select
v-model="content.profitCalcType"
:items="[
{ title: 'بر اساس اختلاف قیمت خرید و فروش', value: 'simple' },
{ title: 'بر اساس آخرین قیمت ورود به انبار', value: 'lis' },
{ title: 'بر اساس میانگین قیمت ورود به انبار', value: 'avgis' }
]"
item-title="title"
item-value="value"
label="نحوه محاسبه سود فاکتور"
variant="outlined"
density="compact"
></v-select>
</v-col>
</v-row>
</v-card-text> </v-card-text>
</v-card> </v-card>
</v-tabs-window-item> </v-tabs-window-item>
@ -329,9 +331,13 @@
<script> <script>
import axios from "axios"; import axios from "axios";
import Swal from "sweetalert2"; import Swal from "sweetalert2";
import Hdatepicker from "@/components/forms/Hdatepicker.vue";
export default { export default {
name: "bussiness", name: "bussiness",
components: {
Hdatepicker
},
data: () => { data: () => {
return { return {
tabs: '', tabs: '',
@ -356,7 +362,6 @@ export default {
email: '', email: '',
arzmain: [], arzmain: [],
maliyatafzode: 9, maliyatafzode: 9,
zarinpalCode: '',
shortlinks: false, shortlinks: false,
walletEnabled: false, walletEnabled: false,
walletMatchBank: '', walletMatchBank: '',
@ -425,7 +430,6 @@ export default {
'email': this.content.email, 'email': this.content.email,
'arzmain': this.content.arzmain, 'arzmain': this.content.arzmain,
'maliyatafzode': this.content.maliyatafzode, 'maliyatafzode': this.content.maliyatafzode,
'zarinpalCode': this.content.zarinpalCode,
'shortlinks': this.content.shortlinks, 'shortlinks': this.content.shortlinks,
'walletEnabled': this.content.walletEnabled, 'walletEnabled': this.content.walletEnabled,
'walletMatchBank': this.content.walletMatchBank, 'walletMatchBank': this.content.walletMatchBank,

View file

@ -0,0 +1,360 @@
<template>
<v-toolbar color="toolbar" :title="$t('drawer.wallets')">
<v-spacer />
<template v-slot:extension>
<v-tabs v-model="activeTab" color="primary" fixed-tabs>
<v-tab value="wallets">کیف پولها</v-tab>
<v-tab value="transactions">تراکنشها</v-tab>
</v-tabs>
</template>
</v-toolbar>
<v-window v-model="activeTab">
<!-- تب کیف پولها -->
<v-window-item value="wallets">
<v-card :loading="loading ? 'red' : null" :disabled="loading">
<v-card-text>
<v-row>
<v-col cols="12" sm="4" md="3">
<v-text-field v-model="search" label="جستجو..." prepend-inner-icon="mdi-magnify" single-line hide-details
density="compact" variant="outlined"></v-text-field>
</v-col>
<v-col cols="12" sm="4" md="3">
<v-select v-model="statusFilter" :items="statusOptions" label="وضعیت" density="compact" variant="outlined"
hide-details clearable></v-select>
</v-col>
</v-row>
<v-row>
<v-col>
<v-data-table :headers="headers" :items="filteredItems" :loading="loading" class="elevation-1"
no-data-text="اطلاعاتی برای نمایش وجود ندارد" loading-text="در حال بارگذاری..." :items-per-page="10"
:items-per-page-text="'تعداد سطر'" :header-props="{ class: 'custom-header' }">
<template v-slot:item="{ item }">
<tr>
<td>{{ item.bidName }}</td>
<td>{{ item.bankAcName }}</td>
<td>{{ item.bankAcOwner }}</td>
<td>{{ item.bankAcShaba }}</td>
<td>{{ item.bankAcCardNum }}</td>
<td>{{ item.totalPays }}</td>
<td>{{ item.totalIncome }}</td>
<td>{{ calculateStatus(item) }}</td>
<td>
<v-tooltip v-if="calculateStatus(item) === 'در صف تسویه'" location="top">
<template v-slot:activator="{ props }">
<v-btn variant="text" icon v-bind="props" @click="openTransactionDialog(item)">
<v-icon>mdi-cash-register</v-icon>
</v-btn>
</template>
<span>ثبت تراکنش</span>
</v-tooltip>
</td>
</tr>
</template>
</v-data-table>
</v-col>
</v-row>
</v-card-text>
</v-card>
</v-window-item>
<!-- تب تراکنشها -->
<v-window-item value="transactions">
<v-card :loading="transactionsLoading ? 'red' : null" :disabled="transactionsLoading">
<v-card-text>
<v-row>
<v-col cols="12" sm="4" md="3">
<v-text-field v-model="transactionSearch" label="جستجو..." prepend-inner-icon="mdi-magnify" single-line
hide-details density="compact" variant="outlined"></v-text-field>
</v-col>
</v-row>
<v-row>
<v-col>
<v-data-table :headers="transactionHeaders" :items="filteredTransactions" :loading="transactionsLoading"
class="elevation-1" no-data-text="اطلاعاتی برای نمایش وجود ندارد" loading-text="در حال بارگذاری..."
:items-per-page="10" :items-per-page-text="'تعداد سطر'" :header-props="{ class: 'custom-header' }">
<template v-slot:item="{ item }">
<tr>
<td>{{ item.bidName }}</td>
<td>{{ item.bankAcName }}</td>
<td>{{ item.type === 'pay' ? 'پرداخت' : 'دریافت' }}</td>
<td>{{ item.gatePay }}</td>
<td>{{ item.refID }}</td>
<td>{{ item.shaba }}</td>
<td>{{ item.cardPan }}</td>
<td>{{ item.dateSubmit }}</td>
</tr>
</template>
</v-data-table>
</v-col>
</v-row>
</v-card-text>
</v-card>
</v-window-item>
</v-window>
<v-dialog v-model="dialogVisible" max-width="500px">
<v-card>
<v-card-title>ثبت تراکنش تسویه کیف پول</v-card-title>
<v-card-text>
<v-form ref="form" v-model="formValid" @submit.prevent="submitTransaction">
<v-row>
<v-col cols="12">
<v-select v-model="transaction.bank" :items="bankOptions" label="بانک پرداخت کننده"
:rules="[v => !!v || 'بانک الزامی است']" variant="outlined" required></v-select>
</v-col>
<v-col cols="12">
<v-text-field v-model="transaction.refID" label="شناسه تراکنش"
:rules="[v => !!v || 'شناسه تراکنش الزامی است']" variant="outlined" required></v-text-field>
</v-col>
<v-col cols="12">
<v-text-field v-model="transaction.amount" label="مبلغ (ریال)" type="number"
:rules="[v => !!v || 'مبلغ الزامی است']" variant="outlined" required></v-text-field>
</v-col>
<v-col cols="12">
<v-text-field v-model="selectedItemShaba" label="شبا" disabled variant="outlined"></v-text-field>
</v-col>
<v-col cols="12">
<v-text-field v-model="selectedItemCard" label="شماره کارت" disabled variant="outlined"></v-text-field>
</v-col>
</v-row>
</v-form>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error" @click="dialogVisible = false">انصراف</v-btn>
<v-btn color="primary" :loading="submitting" @click="submitTransaction">ثبت تراکنش</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
import axios from "axios";
import Swal from "sweetalert2";
export default {
name: "dashboard",
data() {
return {
activeTab: 'wallets',
loading: true,
transactionsLoading: true,
submitting: false,
formValid: false,
items: [],
transactions: [],
search: '',
transactionSearch: '',
statusFilter: null,
transaction: {
bank: null,
refID: '',
amount: '',
shaba: '',
card: '',
bid: null
},
bankOptions: [
{ title: 'بانک ملی', value: 'بانک ملی' },
{ title: 'بانک ملت', value: 'بانک ملت' },
{ title: 'بانک صادرات', value: 'بانک صادرات' },
{ title: 'بانک تجارت', value: 'بانک تجارت' },
{ title: 'بانک پاسارگاد', value: 'بانک پاسارگاد' },
{ title: 'بانک سامان', value: 'بانک سامان' }
],
statusOptions: [
{ title: 'تسویه شده', value: 'تسویه شده' },
{ title: 'در صف تسویه', value: 'در صف تسویه' },
{ title: 'در انتظار پرداخت', value: 'در انتظار پرداخت' },
],
dialogVisible: false,
selectedItem: null,
headers: [
{ title: "کسب‌و‌کار", key: "bidName", sortable: false, align: 'center' },
{ title: "بانک", key: "bankAcName", sortable: false, align: 'center' },
{ title: "حساب", key: "bankAcOwner", sortable: false, align: 'center' },
{ title: "شبا", key: "bankAcShaba", sortable: false, align: 'center' },
{ title: "شماره کارت", key: "bankAcCardNum", sortable: false, align: 'center' },
{ title: "مبلغ پرداختی", key: "totalPays", sortable: false, align: 'center' },
{ title: "مبلغ دریافتی", key: "totalIncome", sortable: false, align: 'center' },
{ title: "وضعیت", key: "status", sortable: false, align: 'center' },
{ title: "عملیات", key: "operations", sortable: false, align: 'center' },
],
transactionHeaders: [
{ title: "کسب‌و‌کار", key: "bidName", sortable: false, align: 'center' },
{ title: "بانک", key: "bankAcName", sortable: false, align: 'center' },
{ title: "نوع", key: "type", sortable: false, align: 'center' },
{ title: "درگاه پرداخت", key: "gatePay", sortable: false, align: 'center' },
{ title: "شناسه تراکنش", key: "refID", sortable: false, align: 'center' },
{ title: "شبا", key: "shaba", sortable: false, align: 'center' },
{ title: "شماره کارت", key: "cardPan", sortable: false, align: 'center' },
{ title: "تاریخ", key: "dateSubmit", sortable: false, align: 'center' },
],
}
},
computed: {
filteredItems() {
let filtered = [...this.items];
// اعمال فیلتر جستجو
if (this.search) {
const searchLower = this.search.toLowerCase();
filtered = filtered.filter(item =>
item.bidName?.toLowerCase().includes(searchLower) ||
item.bankAcName?.toLowerCase().includes(searchLower) ||
item.bankAcOwner?.toLowerCase().includes(searchLower) ||
item.bankAcShaba?.toLowerCase().includes(searchLower) ||
item.bankAcCardNum?.toLowerCase().includes(searchLower)
);
}
// اعمال فیلتر وضعیت
if (this.statusFilter) {
filtered = filtered.filter(item =>
this.calculateStatus(item) === this.statusFilter
);
}
return filtered;
},
filteredTransactions() {
if (!this.transactionSearch) {
// مرتبسازی بر اساس تاریخ (جدیدترین اول)
return [...this.transactions].sort((a, b) => {
return a.dateSubmit < b.dateSubmit ? 1 : -1;
});
}
const searchLower = this.transactionSearch.toLowerCase();
return this.transactions.filter(item =>
item.bidName?.toLowerCase().includes(searchLower) ||
item.bankAcName?.toLowerCase().includes(searchLower) ||
item.refID?.toLowerCase().includes(searchLower) ||
item.shaba?.toLowerCase().includes(searchLower) ||
item.cardPan?.toLowerCase().includes(searchLower) ||
item.gatePay?.toLowerCase().includes(searchLower)
).sort((a, b) => {
return a.dateSubmit < b.dateSubmit ? 1 : -1;
});
},
selectedItemShaba() {
return this.selectedItem ? this.selectedItem.bankAcShaba : '';
},
selectedItemCard() {
return this.selectedItem ? this.selectedItem.bankAcCardNum : '';
}
},
watch: {
activeTab(newVal) {
if (newVal === 'transactions' && this.transactions.length === 0) {
this.loadTransactions();
}
}
},
methods: {
loadData() {
axios.post('/api/admin/wallets/list').then((response) => {
this.items = response.data;
this.loading = false;
});
},
loadTransactions() {
this.transactionsLoading = true;
axios.post('/api/admin/wallets/transactions/list').then((response) => {
this.transactions = response.data;
this.transactionsLoading = false;
}).catch(error => {
console.error('Error loading transactions:', error);
this.transactionsLoading = false;
});
},
calculateStatus(item) {
if (!item) {
return 'نامشخص';
}
const totalPays = Number(item.totalPays || 0);
const totalIncome = Number(item.totalIncome || 0);
if (totalPays === totalIncome) {
return 'تسویه شده';
} else if (totalPays > totalIncome) {
return 'در صف تسویه';
} else {
return 'در انتظار پرداخت';
}
},
openTransactionDialog(item) {
this.selectedItem = item;
// محاسبه مبلغ قابل پرداخت (مبلغ دریافتی - پرداختی)
const amount = Number(item.totalIncome || 0) - Number(item.totalPays || 0);
// تنظیم مقادیر پیشفرض فرم
this.transaction = {
bank: null,
refID: '',
amount: Math.abs(amount),
shaba: item.bankAcShaba,
card: item.bankAcCardNum,
bid: { id: item.id }
};
this.dialogVisible = true;
},
submitTransaction() {
if (!this.$refs.form.validate()) {
return;
}
this.submitting = true;
axios.post('/api/admin/wallets/transactions/insert', this.transaction)
.then(response => {
if (response.data.result === 1) {
this.dialogVisible = false;
Swal.fire({
icon: 'success',
title: 'موفق',
text: 'تراکنش با موفقیت ثبت شد',
confirmButtonText: 'تایید'
});
// بارگذاری مجدد دادهها
this.loadData();
this.loadTransactions();
} else {
throw new Error('خطا در ثبت تراکنش');
}
})
.catch(error => {
console.error('Error submitting transaction:', error);
Swal.fire({
icon: 'error',
title: 'خطا',
text: 'خطا در ثبت تراکنش. لطفا مجددا تلاش کنید.',
confirmButtonText: 'تایید'
});
})
.finally(() => {
this.submitting = false;
});
}
},
mounted() {
this.loadData();
},
beforeUnmount() {
if (this.intervalId) {
clearInterval(this.intervalId);
}
},
}
</script>
<style scoped>
.v-window {
margin-top: 16px;
}
</style>

View file

@ -105,6 +105,8 @@ export default defineComponent({
{ text: 'به روز رسانی هسته', url: '/profile/manager/update-core', icon: 'mdi-undo', visible: true }, { text: 'به روز رسانی هسته', url: '/profile/manager/update-core', icon: 'mdi-undo', visible: true },
{ text: 'تغییرات', url: '/profile/manager/changes/list', icon: 'mdi-cellphone-arrow-down', visible: true }, { text: 'تغییرات', url: '/profile/manager/changes/list', icon: 'mdi-cellphone-arrow-down', visible: true },
{ text: 'تاریخچه سیستم', url: '/profile/manager/logs/list', icon: 'mdi-history', visible: true }, { text: 'تاریخچه سیستم', url: '/profile/manager/logs/list', icon: 'mdi-history', visible: true },
{ text: 'کیف پول', url: '/profile/manager/wallet/list', icon: 'mdi-wallet', visible: true },
], ],
adminSettings: [ adminSettings: [
{ text: 'پیامک', url: '/profile/manager/system/sms/settings', icon: 'mdi-message-alert', visible: true }, { text: 'پیامک', url: '/profile/manager/system/sms/settings', icon: 'mdi-message-alert', visible: true },