forked from morrning/hesabixCore
progress in inquery panel
This commit is contained in:
parent
2cb7b8945c
commit
227767b0d6
|
@ -455,6 +455,10 @@ class AdminController extends AbstractController
|
|||
$resp['enablePostalCodeToAddress'] = $registryMGR->get('system', key: 'enablePostalCodeToAddress');
|
||||
$resp['inquiryPanelEnable'] = $registryMGR->get('system', key: 'inquiryPanelEnable');
|
||||
$resp['postalCodeToAddressFee'] = $registryMGR->get('system', key: 'postalCodeToAddressFee');
|
||||
$resp['enableCardToSheba'] = $registryMGR->get('system', key: 'enableCardToSheba');
|
||||
$resp['cardToShebaFee'] = $registryMGR->get('system', key: 'cardToShebaFee');
|
||||
$resp['enableAccountToSheba'] = $registryMGR->get('system', key: 'enableAccountToSheba');
|
||||
$resp['accountToShebaFee'] = $registryMGR->get('system', key: 'accountToShebaFee');
|
||||
return $this->json($resp);
|
||||
}
|
||||
|
||||
|
@ -484,6 +488,10 @@ class AdminController extends AbstractController
|
|||
$registryMGR->update('system', 'enablePostalCodeToAddress', $params['enablePostalCodeToAddress']);
|
||||
$registryMGR->update('system', 'inquiryPanelEnable', $params['inquiryPanelEnable']);
|
||||
$registryMGR->update('system', 'postalCodeToAddressFee', $params['postalCodeToAddressFee']);
|
||||
$registryMGR->update('system', 'enableCardToSheba', $params['enableCardToSheba']);
|
||||
$registryMGR->update('system', 'cardToShebaFee', $params['cardToShebaFee']);
|
||||
$registryMGR->update('system', 'enableAccountToSheba', $params['enableAccountToSheba']);
|
||||
$registryMGR->update('system', 'accountToShebaFee', $params['accountToShebaFee']);
|
||||
$entityManager->persist($item);
|
||||
$entityManager->flush();
|
||||
return $this->json(['result' => 1]);
|
||||
|
|
|
@ -544,6 +544,7 @@ class BusinessController extends AbstractController
|
|||
'plugRepservice' => true,
|
||||
'plugHrmDocs' => true,
|
||||
'plugGhestaManager' => true,
|
||||
'plugTaxSettings' => true,
|
||||
];
|
||||
} elseif ($perm) {
|
||||
$result = [
|
||||
|
@ -587,6 +588,7 @@ class BusinessController extends AbstractController
|
|||
'plugAccproPresell' => $perm->isPlugAccproPresell(),
|
||||
'plugHrmDocs' => $perm->isPlugHrmDocs(),
|
||||
'plugGhestaManager' => $perm->isPlugGhestaManager(),
|
||||
'plugTaxSettings' => $perm->isPlugTaxSettings(),
|
||||
];
|
||||
}
|
||||
return $this->json($result);
|
||||
|
@ -656,6 +658,7 @@ class BusinessController extends AbstractController
|
|||
$perm->setPlugRepservice($params['plugRepservice']);
|
||||
$perm->setPlugHrmDocs($params['plugHrmDocs']);
|
||||
$perm->setPlugGhestaManager($params['plugGhestaManager']);
|
||||
$perm->setPlugTaxSettings($params['plugTaxSettings']);
|
||||
$entityManager->persist($perm);
|
||||
$entityManager->flush();
|
||||
$log->insert('تنظیمات پایه', 'ویرایش دسترسیهای کاربر با پست الکترونیکی ' . $user->getEmail(), $this->getUser(), $business);
|
||||
|
|
201
hesabixCore/src/Controller/Plugins/TaxSettingsController.php
Normal file
201
hesabixCore/src/Controller/Plugins/TaxSettingsController.php
Normal file
|
@ -0,0 +1,201 @@
|
|||
<?php
|
||||
|
||||
namespace App\Controller\Plugins;
|
||||
|
||||
use App\Service\Access;
|
||||
use App\Service\Extractor;
|
||||
use App\Service\Log;
|
||||
use App\Service\registryMGR;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use App\Entity\PluginTaxsettingsKey;
|
||||
|
||||
class TaxSettingsController extends AbstractController
|
||||
{
|
||||
#[Route('/api/plugins/tax/settings/get', name: 'plugin_tax_settings_get', methods: ['GET'])]
|
||||
public function plugin_tax_settings_get(EntityManagerInterface $em, Access $access): JsonResponse
|
||||
{
|
||||
$acc = $access->hasRole('plugTaxSettings');
|
||||
if (!$acc) {
|
||||
throw $this->createAccessDeniedException('شما دسترسی لازم را ندارید.');
|
||||
}
|
||||
|
||||
$businessId = is_object($acc['bid']) ? $acc['bid']->getId() : $acc['bid'];
|
||||
$userId = $this->getUser()->getId();
|
||||
|
||||
// دریافت تنظیمات از جدول اختصاصی
|
||||
$repo = $em->getRepository(PluginTaxsettingsKey::class);
|
||||
$entity = $repo->findOneBy(['business_id' => $businessId, 'user_id' => $userId]);
|
||||
|
||||
$settings = [
|
||||
'taxMemoryId' => $entity ? $entity->getTaxMemoryId() : '',
|
||||
'economicCode' => $entity ? $entity->getEconomicCode() : '',
|
||||
'privateKey' => $entity ? $entity->getPrivateKey() : '',
|
||||
];
|
||||
|
||||
return $this->json($settings);
|
||||
}
|
||||
|
||||
#[Route('/api/plugins/tax/settings/save', name: 'plugin_tax_settings_save', methods: ['POST'])]
|
||||
public function plugin_tax_settings_save(Request $request, registryMGR $registryMGR, Access $access, Log $log, EntityManagerInterface $em): JsonResponse
|
||||
{
|
||||
$acc = $access->hasRole('plugTaxSettings');
|
||||
if (!$acc) {
|
||||
throw $this->createAccessDeniedException('شما دسترسی لازم را ندارید.');
|
||||
}
|
||||
|
||||
$params = $request->getPayload()->all();
|
||||
$businessId = is_object($acc['bid']) ? $acc['bid']->getId() : $acc['bid'];
|
||||
$userId = $this->getUser()->getId();
|
||||
|
||||
// بررسی وجود رکورد قبلی
|
||||
$repo = $em->getRepository(PluginTaxsettingsKey::class);
|
||||
$entity = $repo->findOneBy(['business_id' => $businessId, 'user_id' => $userId]);
|
||||
if (!$entity) {
|
||||
$entity = new PluginTaxsettingsKey();
|
||||
$entity->setBusinessId($businessId);
|
||||
$entity->setUserId($userId);
|
||||
$entity->setCreatedAt(new \DateTime());
|
||||
}
|
||||
$entity->setPrivateKey($params['privateKey'] ?? '');
|
||||
$entity->setTaxMemoryId($params['taxMemoryId'] ?? null);
|
||||
$entity->setEconomicCode($params['economicCode'] ?? null);
|
||||
$entity->setUpdatedAt(new \DateTime());
|
||||
|
||||
$em->persist($entity);
|
||||
$em->flush();
|
||||
|
||||
$log->insert('تنظیمات مالیاتی', 'تنظیمات مالیاتی ذخیره شد (در جدول اختصاصی)', $this->getUser(), $businessId);
|
||||
|
||||
return $this->json(['success' => true, 'message' => 'تنظیمات با موفقیت ذخیره شد']);
|
||||
}
|
||||
|
||||
private function generatePrivateKey(): string
|
||||
{
|
||||
// تولید کلید خصوصی واقعی با OpenSSL
|
||||
$config = [
|
||||
"private_key_bits" => 2048,
|
||||
"private_key_type" => OPENSSL_KEYTYPE_RSA,
|
||||
];
|
||||
|
||||
$res = openssl_pkey_new($config);
|
||||
if (!$res) {
|
||||
throw new \Exception('خطا در تولید کلید خصوصی: ' . openssl_error_string());
|
||||
}
|
||||
|
||||
$privateKey = '';
|
||||
if (!openssl_pkey_export($res, $privateKey)) {
|
||||
throw new \Exception('خطا در استخراج کلید خصوصی: ' . openssl_error_string());
|
||||
}
|
||||
|
||||
openssl_pkey_free($res);
|
||||
return $privateKey;
|
||||
}
|
||||
|
||||
private function generatePublicKey(string $privateKey): string
|
||||
{
|
||||
// استخراج کلید عمومی از کلید خصوصی
|
||||
$res = openssl_pkey_get_private($privateKey);
|
||||
if (!$res) {
|
||||
throw new \Exception('خطا در خواندن کلید خصوصی: ' . openssl_error_string());
|
||||
}
|
||||
|
||||
$keyDetails = openssl_pkey_get_details($res);
|
||||
if (!$keyDetails) {
|
||||
throw new \Exception('خطا در استخراج جزئیات کلید: ' . openssl_error_string());
|
||||
}
|
||||
|
||||
openssl_pkey_free($res);
|
||||
return $keyDetails['key'];
|
||||
}
|
||||
|
||||
#[Route('/api/plugins/tax/settings/generate-csr', name: 'plugin_tax_settings_generate_csr', methods: ['POST'])]
|
||||
public function plugin_tax_settings_generate_csr(Request $request, registryMGR $registryMGR, Access $access, Log $log): JsonResponse
|
||||
{
|
||||
$acc = $access->hasRole('plugTaxSettings');
|
||||
if (!$acc) {
|
||||
throw $this->createAccessDeniedException('شما دسترسی لازم را ندارید.');
|
||||
}
|
||||
|
||||
$params = $request->getPayload()->all();
|
||||
|
||||
// بررسی فیلدهای اجباری
|
||||
if (empty($params['nationalId']) || empty($params['nameFa']) || empty($params['nameEn']) || empty($params['email'])) {
|
||||
return $this->json([
|
||||
'success' => false,
|
||||
'message' => 'تمام فیلدها الزامی هستند'
|
||||
]);
|
||||
}
|
||||
|
||||
try {
|
||||
$privateKey = $this->generatePrivateKey();
|
||||
$publicKey = $this->generatePublicKey($privateKey);
|
||||
$csr = $this->generateCSR($privateKey, $params);
|
||||
|
||||
// هیچ ذخیرهای در دیتابیس انجام نمیشود
|
||||
$businessId = is_object($acc['bid']) ? $acc['bid']->getId() : $acc['bid'];
|
||||
$log->insert('تنظیمات مالیاتی', 'کلید و CSR تولید شد (بدون ذخیره)', $this->getUser(), $businessId);
|
||||
|
||||
return $this->json([
|
||||
'success' => true,
|
||||
'message' => 'کلید و CSR با موفقیت تولید شد',
|
||||
'privateKey' => $privateKey,
|
||||
'publicKey' => $publicKey,
|
||||
'csr' => $csr
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
return $this->json([
|
||||
'success' => false,
|
||||
'message' => 'خطا در تولید کلید و CSR: ' . $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
private function generateCSR(string $privateKey, array $params): string
|
||||
{
|
||||
// تولید CSR واقعی با OpenSSL
|
||||
$dn = [
|
||||
"countryName" => "IR",
|
||||
"stateOrProvinceName" => "Tehran",
|
||||
"localityName" => "Tehran",
|
||||
"organizationName" => $params['nameEn'],
|
||||
"organizationalUnitName" => "Tax Department",
|
||||
"commonName" => $params['nameFa'],
|
||||
"emailAddress" => $params['email']
|
||||
];
|
||||
|
||||
// اضافه کردن شناسه ملی به عنوان extension
|
||||
$config = [
|
||||
"req" => [
|
||||
"distinguished_name" => $dn,
|
||||
"req_extensions" => "v3_req",
|
||||
"x509_extensions" => "v3_req"
|
||||
],
|
||||
"v3_req" => [
|
||||
"subjectAltName" => "email:" . $params['email'],
|
||||
"subjectKeyIdentifier" => "hash"
|
||||
]
|
||||
];
|
||||
|
||||
// ایجاد CSR
|
||||
$res = openssl_csr_new($dn, $privateKey, [
|
||||
'config' => $config,
|
||||
'digest_alg' => 'sha256',
|
||||
'req_extensions' => 'v3_req'
|
||||
]);
|
||||
|
||||
if (!$res) {
|
||||
throw new \Exception('خطا در تولید CSR: ' . openssl_error_string());
|
||||
}
|
||||
|
||||
$csr = '';
|
||||
if (!openssl_csr_export($res, $csr)) {
|
||||
throw new \Exception('خطا در استخراج CSR: ' . openssl_error_string());
|
||||
}
|
||||
|
||||
return $csr;
|
||||
}
|
||||
}
|
|
@ -128,6 +128,4 @@ class PlugInquiryMainController extends AbstractController
|
|||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -129,6 +129,9 @@ class Permission
|
|||
#[ORM\Column(nullable: true)]
|
||||
private ?bool $plugGhestaManager = null;
|
||||
|
||||
#[ORM\Column(nullable: true)]
|
||||
private ?bool $plugTaxSettings = null;
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
|
@ -590,4 +593,16 @@ class Permission
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function isPlugTaxSettings(): ?bool
|
||||
{
|
||||
return $this->plugTaxSettings;
|
||||
}
|
||||
|
||||
public function setPlugTaxSettings(?bool $plugTaxSettings): static
|
||||
{
|
||||
$this->plugTaxSettings = $plugTaxSettings;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
53
hesabixCore/src/Entity/PluginTaxsettingsKey.php
Normal file
53
hesabixCore/src/Entity/PluginTaxsettingsKey.php
Normal file
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity]
|
||||
#[ORM\Table(name: "plugin_taxsettings_keys")]
|
||||
class PluginTaxsettingsKey
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column(type: "integer")]
|
||||
private $id;
|
||||
|
||||
#[ORM\Column(type: "integer")]
|
||||
private $business_id;
|
||||
|
||||
#[ORM\Column(type: "integer")]
|
||||
private $user_id;
|
||||
|
||||
#[ORM\Column(type: "text", nullable: true)]
|
||||
private $private_key;
|
||||
|
||||
#[ORM\Column(type: "string", length: 64, nullable: true)]
|
||||
private $tax_memory_id;
|
||||
|
||||
#[ORM\Column(type: "string", length: 64, nullable: true)]
|
||||
private $economic_code;
|
||||
|
||||
#[ORM\Column(type: "datetime")]
|
||||
private $created_at;
|
||||
|
||||
#[ORM\Column(type: "datetime")]
|
||||
private $updated_at;
|
||||
|
||||
// Getters and setters ...
|
||||
public function getId() { return $this->id; }
|
||||
public function getBusinessId() { return $this->business_id; }
|
||||
public function setBusinessId($val) { $this->business_id = $val; }
|
||||
public function getUserId() { return $this->user_id; }
|
||||
public function setUserId($val) { $this->user_id = $val; }
|
||||
public function getPrivateKey() { return $this->private_key; }
|
||||
public function setPrivateKey($val) { $this->private_key = $val; }
|
||||
public function getTaxMemoryId() { return $this->tax_memory_id; }
|
||||
public function setTaxMemoryId($val) { $this->tax_memory_id = $val; }
|
||||
public function getEconomicCode() { return $this->economic_code; }
|
||||
public function setEconomicCode($val) { $this->economic_code = $val; }
|
||||
public function getCreatedAt() { return $this->created_at; }
|
||||
public function setCreatedAt($val) { $this->created_at = $val; }
|
||||
public function getUpdatedAt() { return $this->updated_at; }
|
||||
public function setUpdatedAt($val) { $this->updated_at = $val; }
|
||||
}
|
|
@ -86,6 +86,7 @@ const en_lang = {
|
|||
cheque_output: "Cheque Output",
|
||||
presells: "Presells",
|
||||
presell_view: "View Presell",
|
||||
inquiry: "Inquiries",
|
||||
hrm: 'HR & Payroll',
|
||||
hrm_docs: 'Payroll Document',
|
||||
},
|
||||
|
|
|
@ -173,6 +173,7 @@ const fa_lang = {
|
|||
reports: "گزارشات",
|
||||
settings: "تنظیمات",
|
||||
bid_settings: "تنظیمات کسبوکار",
|
||||
tax_settings: "تنظیمات مالیاتی",
|
||||
print_settings: "چاپ اسناد",
|
||||
user_perms: "کاربران و دسترسیها",
|
||||
avatar_settings: "نمایه و مهر کسبوکار",
|
||||
|
@ -193,13 +194,16 @@ const fa_lang = {
|
|||
plugins_invoices: "صورت حسابها",
|
||||
repservice: "مدیریت تعمیرگاه",
|
||||
repservice_reqs: "درخواستها",
|
||||
inquiry: "استعلامات",
|
||||
hrm: 'منابع انسانی',
|
||||
hrm_docs: 'سند حقوق',
|
||||
buysellByPerson: "گزارش خرید و فروش های اشخاص",
|
||||
tax_system: "سامانه مودیان مالیاتی",
|
||||
tax_invoices: "صورتحساب ها",
|
||||
},
|
||||
time: {
|
||||
month: "{id} ماه",
|
||||
},
|
||||
},
|
||||
calendar: {
|
||||
shamsi: "هجری شمسی",
|
||||
gregorian: "میلادی",
|
||||
|
@ -818,6 +822,10 @@ const fa_lang = {
|
|||
inquiry_zohal_api_key_label: "کلید API زحل",
|
||||
enable_postalcode_to_address: "تبدیل کد پستی به آدرس",
|
||||
postalcode_to_address_fee: "کارمزد تبدیل کد پستی به آدرس",
|
||||
enable_card_to_sheba: "تبدیل شماره کارت به شبا",
|
||||
card_to_sheba_fee: "کارمزد تبدیل شماره کارت به شبا",
|
||||
enable_account_to_sheba: "تبدیل حساب به شبا",
|
||||
account_to_sheba_fee: "کارمزد تبدیل حساب به شبا",
|
||||
inquiry_panel_enable: "فعال سازی پنل سامانه استعلامات",
|
||||
inquiry_panel: "پنل سامانه استعلامات",
|
||||
inquiry_panel_zohal: "زحل",
|
||||
|
|
|
@ -510,6 +510,18 @@ const router = createRouter({
|
|||
component: () =>
|
||||
import('../views/acc/settings/extramoneys.vue'),
|
||||
},
|
||||
{
|
||||
path: 'plugins/tax/settings',
|
||||
name: 'business_tax_settings',
|
||||
component: () =>
|
||||
import('../views/acc/tax/tax-settings.vue'),
|
||||
},
|
||||
{
|
||||
path: 'plugins/tax/invoices/list',
|
||||
name: 'tax_invoices_list',
|
||||
component: () =>
|
||||
import('../views/acc/tax/invoices/list.vue'),
|
||||
},
|
||||
{
|
||||
path: 'business/logs',
|
||||
name: 'business_logs',
|
||||
|
@ -988,6 +1000,12 @@ const router = createRouter({
|
|||
component: () =>
|
||||
import('../views/acc/plugins/hrm/docs/view.vue'),
|
||||
},
|
||||
{
|
||||
path: 'inquiry/panel',
|
||||
name: 'inquiry_panel',
|
||||
component: () =>
|
||||
import('../views/acc/inquiry/panel.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
|
@ -169,8 +169,9 @@ export default {
|
|||
{ path: '/acc/business/extramoneys', key: '-', label: this.$t('drawer.extra_moneys'), ctrl: true, shift: true, permission: () => this.permissions.settings && this.isPluginActive('accpro') },
|
||||
{ path: '/acc/business/logs', key: '=', label: this.$t('drawer.history'), ctrl: true, shift: true, permission: () => this.permissions.log },
|
||||
{ path: '/acc/plugin/repservice/order/list', key: '[', label: this.$t('drawer.repservice_reqs'), ctrl: true, shift: true, permission: () => this.permissions.plugRepservice && this.isPluginActive('repservice') },
|
||||
{ path: '/acc/sms/panel', key: ']', label: this.$t('drawer.sms_panel'), ctrl: true, shift: true, permission: () => this.permissions.owner },
|
||||
{ path: '/acc/inquiry/panel', key: ']', label: this.$t('drawer.inquiry'), ctrl: true, shift: true, permission: () => true },
|
||||
{ path: '/acc/printers/list', key: ';', label: this.$t('drawer.cloud_printers'), ctrl: true, shift: true, permission: () => this.permissions.owner },
|
||||
{ path: '/acc/sms/panel', key: '`', label: this.$t('drawer.sms_panel'), ctrl: true, shift: true, permission: () => this.permissions.owner },
|
||||
{ path: '/acc/archive/list', key: '\'', label: this.$t('drawer.archive_files'), ctrl: true, shift: true, permission: () => this.permissions.archiveUpload || this.permissions.archiveMod || this.permissions.archiveDelete },
|
||||
{ path: '/acc/archive/order/new', key: ',', label: this.$t('drawer.archive_order'), ctrl: true, shift: true, permission: () => this.permissions.owner },
|
||||
{ path: '/acc/archive/order/list', key: '.', label: this.$t('drawer.archive_log'), ctrl: true, shift: true, permission: () => this.permissions.owner },
|
||||
|
@ -179,6 +180,8 @@ export default {
|
|||
{ path: '/acc/plugin-center/invoice', key: '`', label: this.$t('drawer.plugins_invoices'), ctrl: true, shift: true, permission: () => this.permissions.owner },
|
||||
{ path: '/acc/hrm/docs/list', key: 'H', label: this.$t('drawer.hrm_docs'), ctrl: true, shift: true, permission: () => this.isPluginActive('hrm') && this.permissions.plugHrmDocs },
|
||||
{ path: '/acc/plugins/ghesta/list', key: 'G', label: this.$t('drawer.ghesta_invoices'), ctrl: true, shift: true, permission: () => this.isPluginActive('ghesta') && this.permissions.plugGhestaManager },
|
||||
{ path: '/acc/plugins/tax/invoices/list', key: 'L', label: this.$t('drawer.tax_invoices'), ctrl: true, shift: true, permission: () => this.permissions.settings && this.isPluginActive('taxsettings') },
|
||||
{ path: '/acc/plugins/tax/settings', key: 'T', label: this.$t('drawer.tax_settings'), ctrl: true, shift: true, permission: () => this.permissions.settings && this.isPluginActive('taxsettings') },
|
||||
];
|
||||
},
|
||||
restorePermissions(shortcuts) {
|
||||
|
@ -741,7 +744,7 @@ export default {
|
|||
<v-list-item-title>
|
||||
{{ $t('drawer.user_perms') }}
|
||||
<span v-if="isCtrlShiftPressed" class="shortcut-key">{{ getShortcutKey('/acc/business/users') }}</span>
|
||||
</v-list-item-title>
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item v-if="permissions.owner" to="/acc/business/apis">
|
||||
<v-list-item-title>
|
||||
|
@ -788,6 +791,13 @@ export default {
|
|||
</template>
|
||||
</v-list-item>
|
||||
</v-list-group>
|
||||
<v-list-item class="text-dark" to="/acc/inquiry/panel">
|
||||
<template v-slot:prepend><v-icon icon="mdi-magnify" color="primary"></v-icon></template>
|
||||
<v-list-item-title>
|
||||
{{ $t('drawer.inquiry') }}
|
||||
<span v-if="isCtrlShiftPressed" class="shortcut-key">{{ getShortcutKey('/acc/inquiry/panel') }}</span>
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-group v-show="isPluginActive('hrm') && permissions.plugHrmDocs">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-list-item class="text-dark" v-bind="props" :title="$t('drawer.hrm')">
|
||||
|
@ -828,6 +838,23 @@ export default {
|
|||
</template>
|
||||
</v-list-item>
|
||||
</v-list-group>
|
||||
<v-list-group v-show="isPluginActive('taxsettings') && permissions.plugTaxSettings">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-list-item class="text-dark" v-bind="props" :title="$t('drawer.tax_system')">
|
||||
<template v-slot:prepend><v-icon icon="mdi-file-document-multiple" color="primary"></v-icon></template>
|
||||
</v-list-item>
|
||||
</template>
|
||||
<v-list-item to="/acc/plugins/tax/invoices/list">
|
||||
<v-list-item-title>
|
||||
{{ $t('drawer.tax_invoices') }}
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item to="/acc/plugins/tax/settings">
|
||||
<v-list-item-title>
|
||||
{{ $t('drawer.tax_settings') }}
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list-group>
|
||||
<v-list-item class="text-dark" v-if="permissions.owner" to="/acc/sms/panel">
|
||||
<template v-slot:prepend><v-icon icon="mdi-message-cog" color="primary"></v-icon></template>
|
||||
<v-list-item-title>
|
||||
|
|
24
webUI/src/views/acc/inquiry/panel.vue
Normal file
24
webUI/src/views/acc/inquiry/panel.vue
Normal file
|
@ -0,0 +1,24 @@
|
|||
|
||||
<template>
|
||||
<div>
|
||||
<h1>پنل استعلامات</h1>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'panel',
|
||||
data() {
|
||||
return {
|
||||
// دادههای اولیه
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// متدها
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* استایلهای اختصاصی */
|
||||
</style>
|
|
@ -241,6 +241,12 @@ const router = createRouter({
|
|||
component: () =>
|
||||
import ('../views/settings/extramoneys.vue'),
|
||||
},
|
||||
{
|
||||
path: '/acc/business/tax-settings',
|
||||
name: 'business_tax_settings',
|
||||
component: () =>
|
||||
import ('../views/settings/tax-settings.vue'),
|
||||
},
|
||||
{
|
||||
path: '/acc/business/logs',
|
||||
name: 'business_logs',
|
||||
|
|
321
webUI/src/views/acc/settings/tax-settings.vue
Normal file
321
webUI/src/views/acc/settings/tax-settings.vue
Normal file
|
@ -0,0 +1,321 @@
|
|||
<template>
|
||||
<div>
|
||||
<v-toolbar color="toolbar" title="تنظیمات مالیاتی">
|
||||
<template v-slot:prepend>
|
||||
<v-tooltip text="بازگشت" location="bottom">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn v-bind="props" @click="$router.back()" class="d-none d-sm-flex" variant="text"
|
||||
icon="mdi-arrow-right" />
|
||||
</template>
|
||||
</v-tooltip>
|
||||
</template>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn :loading="loading" @click="saveSettings()" icon="" color="green">
|
||||
<v-tooltip activator="parent" text="ذخیره تنظیمات" location="bottom" />
|
||||
<v-icon icon="mdi-content-save"></v-icon>
|
||||
</v-btn>
|
||||
</v-toolbar>
|
||||
|
||||
<v-container>
|
||||
<v-card :loading="loading" :disabled="loading">
|
||||
<v-card-text>
|
||||
<v-row>
|
||||
<v-col cols="12" md="6">
|
||||
<v-btn
|
||||
color="primary"
|
||||
@click="showCSRDialog = true"
|
||||
prepend-icon="mdi-key-plus"
|
||||
>
|
||||
ساخت کلید و CSR
|
||||
</v-btn>
|
||||
</v-col>
|
||||
<v-col cols="12" md="6">
|
||||
<v-row>
|
||||
<v-col cols="12" md="6">
|
||||
<v-text-field
|
||||
v-model="settings.taxMemoryId"
|
||||
label="شناسه یکتای حافظه مالیاتی"
|
||||
hide-details
|
||||
density="compact"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="12" md="6">
|
||||
<v-text-field
|
||||
v-model="settings.economicCode"
|
||||
label="کد اقتصادی"
|
||||
hide-details
|
||||
density="compact"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row class="mt-4">
|
||||
<v-col cols="12">
|
||||
<v-textarea
|
||||
v-model="settings.privateKey"
|
||||
label="Private Key"
|
||||
rows="15"
|
||||
variant="outlined"
|
||||
hide-details
|
||||
placeholder="کلید خصوصی اینجا قرار میگیرد..."
|
||||
></v-textarea>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-container>
|
||||
|
||||
<!-- Dialog برای ساخت کلید و CSR -->
|
||||
<v-dialog v-model="showCSRDialog" max-width="600px">
|
||||
<v-card>
|
||||
<v-card-title class="text-h6">
|
||||
ساخت کلید و CSR
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
<v-form ref="csrForm">
|
||||
<div class="mb-4">
|
||||
<div class="text-subtitle-2 mb-2">شخص</div>
|
||||
<v-radio-group
|
||||
v-model="csrData.personType"
|
||||
inline
|
||||
hide-details
|
||||
>
|
||||
<v-radio
|
||||
v-for="type in personTypes"
|
||||
:key="type.value"
|
||||
:label="type.title"
|
||||
:value="type.value"
|
||||
:disabled="type.value === 'natural'"
|
||||
></v-radio>
|
||||
</v-radio-group>
|
||||
</div>
|
||||
|
||||
<v-text-field
|
||||
v-model="csrData.nationalId"
|
||||
label="شناسه ملی"
|
||||
hide-details
|
||||
class="mb-4"
|
||||
></v-text-field>
|
||||
|
||||
<v-text-field
|
||||
v-model="csrData.nameFa"
|
||||
label="نام (فارسی)"
|
||||
hide-details
|
||||
class="mb-4"
|
||||
></v-text-field>
|
||||
|
||||
<v-text-field
|
||||
v-model="csrData.nameEn"
|
||||
label="نام (انگلیسی)"
|
||||
hide-details
|
||||
class="mb-4"
|
||||
></v-text-field>
|
||||
|
||||
<v-text-field
|
||||
v-model="csrData.email"
|
||||
label="ایمیل"
|
||||
type="email"
|
||||
hide-details
|
||||
class="mb-4"
|
||||
></v-text-field>
|
||||
</v-form>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn @click="showCSRDialog = false" variant="text">
|
||||
انصراف
|
||||
</v-btn>
|
||||
<v-btn @click="generateCSR()" color="primary" :loading="csrLoading">
|
||||
تایید
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
|
||||
<v-dialog v-model="showResultDialog" max-width="900px">
|
||||
<v-card>
|
||||
<v-card-title class="text-h6 pb-0">ساخت کلید و CSR</v-card-title>
|
||||
<v-card-text>
|
||||
<v-alert type="info" color="blue" class="mb-4" icon="mdi-alert">
|
||||
<span class="font-weight-bold">توجه: لطفا این اطلاعات را دانلود کنید و در یک جای امن نگهداری کنید. به دلایل امنیتی اطلاعات شما را نگهداری نمیکنیم، در صورتی که این اطلاعات را گم کنید، امکان بازیابی آن وجود ندارد.</span>
|
||||
</v-alert>
|
||||
<v-row>
|
||||
<v-col cols="12" md="4">
|
||||
<div class="mb-2 font-weight-bold">CSR</div>
|
||||
<v-textarea readonly rows="10" :value="resultData.csr" variant="outlined"></v-textarea>
|
||||
<v-row class="mt-2">
|
||||
<v-col cols="6">
|
||||
<v-btn color="success" block @click="copyToClipboard(resultData.csr)"><v-icon start>mdi-content-copy</v-icon>کپی</v-btn>
|
||||
</v-col>
|
||||
<v-col cols="6">
|
||||
<v-btn color="success" block @click="downloadFile(resultData.csr, 'csr.txt')"><v-icon start>mdi-download</v-icon>دانلود</v-btn>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-col>
|
||||
<v-col cols="12" md="4">
|
||||
<div class="mb-2 font-weight-bold">Public Key</div>
|
||||
<v-textarea readonly rows="10" :value="resultData.publicKey" variant="outlined"></v-textarea>
|
||||
<v-row class="mt-2">
|
||||
<v-col cols="6">
|
||||
<v-btn color="success" block @click="copyToClipboard(resultData.publicKey)"><v-icon start>mdi-content-copy</v-icon>کپی</v-btn>
|
||||
</v-col>
|
||||
<v-col cols="6">
|
||||
<v-btn color="success" block @click="downloadFile(resultData.publicKey, 'public_key.txt')"><v-icon start>mdi-download</v-icon>دانلود</v-btn>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-col>
|
||||
<v-col cols="12" md="4">
|
||||
<div class="mb-2 font-weight-bold">Private Key</div>
|
||||
<v-textarea readonly rows="10" :value="resultData.privateKey" variant="outlined"></v-textarea>
|
||||
<v-row class="mt-2">
|
||||
<v-col cols="6">
|
||||
<v-btn color="success" block @click="copyToClipboard(resultData.privateKey)"><v-icon start>mdi-content-copy</v-icon>کپی</v-btn>
|
||||
</v-col>
|
||||
<v-col cols="6">
|
||||
<v-btn color="success" block @click="downloadFile(resultData.privateKey, 'private_key.txt')"><v-icon start>mdi-download</v-icon>دانلود</v-btn>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn @click="showResultDialog = false" color="primary">بستن</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
|
||||
<v-snackbar
|
||||
v-model="snackbar.show"
|
||||
:color="snackbar.color"
|
||||
:timeout="3000"
|
||||
>
|
||||
{{ snackbar.text }}
|
||||
<template v-slot:actions>
|
||||
<v-btn
|
||||
color="white"
|
||||
variant="text"
|
||||
@click="snackbar.show = false"
|
||||
>
|
||||
بستن
|
||||
</v-btn>
|
||||
</template>
|
||||
</v-snackbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios';
|
||||
import Swal from 'sweetalert2';
|
||||
|
||||
export default {
|
||||
name: 'TaxSettings',
|
||||
data: () => ({
|
||||
loading: false,
|
||||
csrLoading: false,
|
||||
showCSRDialog: false,
|
||||
showResultDialog: false,
|
||||
settings: {
|
||||
taxMemoryId: '',
|
||||
economicCode: '',
|
||||
privateKey: '',
|
||||
},
|
||||
csrData: {
|
||||
personType: 'legal',
|
||||
nationalId: '',
|
||||
nameFa: '',
|
||||
nameEn: '',
|
||||
email: '',
|
||||
},
|
||||
resultData: {
|
||||
csr: '',
|
||||
publicKey: '',
|
||||
privateKey: ''
|
||||
},
|
||||
personTypes: [
|
||||
{ title: 'حقیقی', value: 'natural' },
|
||||
{ title: 'حقوقی', value: 'legal' }
|
||||
],
|
||||
snackbar: {
|
||||
show: false,
|
||||
text: '',
|
||||
color: 'success'
|
||||
}
|
||||
}),
|
||||
methods: {
|
||||
async loadSettings() {
|
||||
this.loading = true;
|
||||
try {
|
||||
const response = await axios.get('/api/plugins/tax-settings/get');
|
||||
this.settings = {
|
||||
...this.settings,
|
||||
...response.data
|
||||
};
|
||||
} catch (error) {
|
||||
this.showSnackbar('خطا در بارگذاری تنظیمات', 'error');
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
async saveSettings() {
|
||||
this.loading = true;
|
||||
try {
|
||||
const dataToSave = { ...this.settings };
|
||||
await axios.post('/api/plugins/tax-settings/save', dataToSave);
|
||||
this.showSnackbar('تنظیمات با موفقیت ذخیره شد', 'success');
|
||||
} catch (error) {
|
||||
this.showSnackbar('خطا در ذخیره تنظیمات', 'error');
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
async generateCSR() {
|
||||
this.csrLoading = true;
|
||||
try {
|
||||
const response = await axios.post('/api/plugins/tax-settings/generate-csr', this.csrData);
|
||||
|
||||
if (response.data.success) {
|
||||
// this.settings.privateKey = response.data.privateKey;
|
||||
// نمایش دیالوگ نتیجه
|
||||
this.resultData.csr = response.data.csr;
|
||||
this.resultData.privateKey = response.data.privateKey;
|
||||
this.resultData.publicKey = response.data.publicKey || '';
|
||||
this.showResultDialog = true;
|
||||
this.showCSRDialog = false;
|
||||
this.showSnackbar('کلید و CSR با موفقیت تولید شد', 'success');
|
||||
} else {
|
||||
this.showSnackbar(response.data.message || 'خطا در تولید کلید و CSR', 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
this.showSnackbar('خطا در تولید کلید و CSR', 'error');
|
||||
} finally {
|
||||
this.csrLoading = false;
|
||||
}
|
||||
},
|
||||
copyToClipboard(text) {
|
||||
navigator.clipboard.writeText(text);
|
||||
this.showSnackbar('کپی شد');
|
||||
},
|
||||
downloadFile(content, filename) {
|
||||
const blob = new Blob([content], { type: 'text/plain' });
|
||||
const link = document.createElement('a');
|
||||
link.href = URL.createObjectURL(blob);
|
||||
link.download = filename;
|
||||
link.click();
|
||||
URL.revokeObjectURL(link.href);
|
||||
},
|
||||
showSnackbar(text, color = 'success') {
|
||||
this.snackbar = {
|
||||
show: true,
|
||||
text,
|
||||
color
|
||||
};
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadSettings();
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -601,6 +601,32 @@
|
|||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row v-if="isPluginActive('taxsettings')" class="mt-4">
|
||||
<v-col cols="12">
|
||||
<v-card-title class="text-h6 font-weight-bold mb-4">افزونه تنظیمات مالیاتی</v-card-title>
|
||||
</v-col>
|
||||
<v-col cols="12" md="4">
|
||||
<v-card variant="outlined" class="h-100">
|
||||
<v-card-text>
|
||||
<v-list>
|
||||
<v-list-item>
|
||||
<v-switch
|
||||
v-model="info.plugTaxSettings"
|
||||
label="مدیریت تنظیمات مالیاتی"
|
||||
@change="savePerms('plugTaxSettings')"
|
||||
hide-details
|
||||
color="success"
|
||||
density="comfortable"
|
||||
:loading="loadingSwitches.plugTaxSettings"
|
||||
:disabled="loadingSwitches.plugTaxSettings"
|
||||
></v-switch>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-container>
|
||||
|
@ -679,7 +705,8 @@ export default {
|
|||
plugNoghreSell: false,
|
||||
plugCCAdmin: false,
|
||||
plugHrmDocs: false,
|
||||
plugGhestaManager: false
|
||||
plugGhestaManager: false,
|
||||
plugTaxSettings: false
|
||||
};
|
||||
|
||||
axios.post('/api/business/get/user/permissions',
|
||||
|
|
173
webUI/src/views/acc/tax/invoices/list.vue
Normal file
173
webUI/src/views/acc/tax/invoices/list.vue
Normal file
|
@ -0,0 +1,173 @@
|
|||
<template>
|
||||
<div>
|
||||
<v-toolbar color="toolbar" title="صورتحسابهای ارسالی به سامانه مودیان مالیاتی">
|
||||
<template v-slot:prepend>
|
||||
<v-tooltip text="بازگشت" location="bottom">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn v-bind="props" @click="$router.back()" class="d-none d-sm-flex" variant="text"
|
||||
icon="mdi-arrow-right" />
|
||||
</template>
|
||||
</v-tooltip>
|
||||
</template>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn :loading="loading" @click="loadData()" icon="" color="primary">
|
||||
<v-tooltip activator="parent" text="بازخوانی" location="bottom" />
|
||||
<v-icon icon="mdi-refresh"></v-icon>
|
||||
</v-btn>
|
||||
</v-toolbar>
|
||||
|
||||
<v-container>
|
||||
<v-card :loading="loading" :disabled="loading">
|
||||
<v-card-text>
|
||||
<v-alert type="info" color="blue" class="mb-4" icon="mdi-information">
|
||||
<span class="font-weight-bold">این بخش برای نمایش لیست صورتحسابهایی است که به سامانه مودیان مالیاتی ارسال شدهاند.</span>
|
||||
</v-alert>
|
||||
|
||||
<v-data-table
|
||||
:headers="headers"
|
||||
:items="invoices"
|
||||
:loading="loading"
|
||||
class="elevation-1"
|
||||
:items-per-page="10"
|
||||
:items-per-page-options="[10, 25, 50, 100]"
|
||||
>
|
||||
<template v-slot:item.status="{ item }">
|
||||
<v-chip
|
||||
:color="getStatusColor(item.status)"
|
||||
:text="getStatusText(item.status)"
|
||||
size="small"
|
||||
></v-chip>
|
||||
</template>
|
||||
|
||||
<template v-slot:item.actions="{ item }">
|
||||
<v-btn
|
||||
icon="mdi-eye"
|
||||
variant="text"
|
||||
size="small"
|
||||
@click="viewInvoice(item)"
|
||||
color="primary"
|
||||
></v-btn>
|
||||
</template>
|
||||
</v-data-table>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-container>
|
||||
|
||||
<v-snackbar
|
||||
v-model="snackbar.show"
|
||||
:color="snackbar.color"
|
||||
:timeout="3000"
|
||||
>
|
||||
{{ snackbar.text }}
|
||||
<template v-slot:actions>
|
||||
<v-btn
|
||||
color="white"
|
||||
variant="text"
|
||||
@click="snackbar.show = false"
|
||||
>
|
||||
بستن
|
||||
</v-btn>
|
||||
</template>
|
||||
</v-snackbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios';
|
||||
|
||||
export default {
|
||||
name: 'TaxInvoicesList',
|
||||
data: () => ({
|
||||
loading: false,
|
||||
invoices: [],
|
||||
headers: [
|
||||
{ title: 'شماره فاکتور', key: 'invoiceNumber', sortable: true },
|
||||
{ title: 'تاریخ', key: 'date', sortable: true },
|
||||
{ title: 'مشتری', key: 'customerName', sortable: true },
|
||||
{ title: 'مبلغ کل', key: 'totalAmount', sortable: true },
|
||||
{ title: 'وضعیت ارسال', key: 'status', sortable: true },
|
||||
{ title: 'تاریخ ارسال', key: 'sentDate', sortable: true },
|
||||
{ title: 'عملیات', key: 'actions', sortable: false }
|
||||
],
|
||||
snackbar: {
|
||||
show: false,
|
||||
text: '',
|
||||
color: 'success'
|
||||
}
|
||||
}),
|
||||
methods: {
|
||||
async loadData() {
|
||||
this.loading = true;
|
||||
try {
|
||||
// اینجا باید API مربوط به دریافت لیست صورتحسابهای ارسالی را فراخوانی کنید
|
||||
// const response = await axios.get('/api/plugins/tax-settings/invoices');
|
||||
// this.invoices = response.data;
|
||||
|
||||
// فعلاً دادههای نمونه
|
||||
this.invoices = [
|
||||
{
|
||||
id: 1,
|
||||
invoiceNumber: 'INV-001',
|
||||
date: '1402/12/15',
|
||||
customerName: 'شرکت نمونه',
|
||||
totalAmount: '1,500,000',
|
||||
status: 'sent',
|
||||
sentDate: '1402/12/16'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
invoiceNumber: 'INV-002',
|
||||
date: '1402/12/14',
|
||||
customerName: 'فروشگاه نمونه',
|
||||
totalAmount: '2,300,000',
|
||||
status: 'pending',
|
||||
sentDate: '-'
|
||||
}
|
||||
];
|
||||
} catch (error) {
|
||||
this.showSnackbar('خطا در بارگذاری دادهها', 'error');
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
getStatusColor(status) {
|
||||
switch (status) {
|
||||
case 'sent':
|
||||
return 'success';
|
||||
case 'pending':
|
||||
return 'warning';
|
||||
case 'failed':
|
||||
return 'error';
|
||||
default:
|
||||
return 'grey';
|
||||
}
|
||||
},
|
||||
getStatusText(status) {
|
||||
switch (status) {
|
||||
case 'sent':
|
||||
return 'ارسال شده';
|
||||
case 'pending':
|
||||
return 'در انتظار';
|
||||
case 'failed':
|
||||
return 'ناموفق';
|
||||
default:
|
||||
return 'نامشخص';
|
||||
}
|
||||
},
|
||||
viewInvoice(item) {
|
||||
// اینجا میتوانید به صفحه جزئیات فاکتور بروید
|
||||
this.showSnackbar('نمایش جزئیات فاکتور: ' + item.invoiceNumber);
|
||||
},
|
||||
showSnackbar(text, color = 'success') {
|
||||
this.snackbar = {
|
||||
show: true,
|
||||
text,
|
||||
color
|
||||
};
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadData();
|
||||
}
|
||||
};
|
||||
</script>
|
321
webUI/src/views/acc/tax/tax-settings.vue
Normal file
321
webUI/src/views/acc/tax/tax-settings.vue
Normal file
|
@ -0,0 +1,321 @@
|
|||
<template>
|
||||
<div>
|
||||
<v-toolbar color="toolbar" title="تنظیمات مالیاتی">
|
||||
<template v-slot:prepend>
|
||||
<v-tooltip text="بازگشت" location="bottom">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn v-bind="props" @click="$router.back()" class="d-none d-sm-flex" variant="text"
|
||||
icon="mdi-arrow-right" />
|
||||
</template>
|
||||
</v-tooltip>
|
||||
</template>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn :loading="loading" @click="saveSettings()" icon="" color="green">
|
||||
<v-tooltip activator="parent" text="ذخیره تنظیمات" location="bottom" />
|
||||
<v-icon icon="mdi-content-save"></v-icon>
|
||||
</v-btn>
|
||||
</v-toolbar>
|
||||
|
||||
<v-container>
|
||||
<v-card :loading="loading" :disabled="loading">
|
||||
<v-card-text>
|
||||
<v-row>
|
||||
<v-col cols="12" md="6">
|
||||
<v-btn
|
||||
color="primary"
|
||||
@click="showCSRDialog = true"
|
||||
prepend-icon="mdi-key-plus"
|
||||
>
|
||||
ساخت کلید و CSR
|
||||
</v-btn>
|
||||
</v-col>
|
||||
<v-col cols="12" md="6">
|
||||
<v-row>
|
||||
<v-col cols="12" md="6">
|
||||
<v-text-field
|
||||
v-model="settings.taxMemoryId"
|
||||
label="شناسه یکتای حافظه مالیاتی"
|
||||
hide-details
|
||||
density="compact"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="12" md="6">
|
||||
<v-text-field
|
||||
v-model="settings.economicCode"
|
||||
label="کد اقتصادی"
|
||||
hide-details
|
||||
density="compact"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row class="mt-4">
|
||||
<v-col cols="12">
|
||||
<v-textarea
|
||||
v-model="settings.privateKey"
|
||||
label="Private Key"
|
||||
rows="15"
|
||||
variant="outlined"
|
||||
hide-details
|
||||
placeholder="کلید خصوصی اینجا قرار میگیرد..."
|
||||
></v-textarea>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-container>
|
||||
|
||||
<!-- Dialog برای ساخت کلید و CSR -->
|
||||
<v-dialog v-model="showCSRDialog" max-width="600px">
|
||||
<v-card>
|
||||
<v-card-title class="text-h6">
|
||||
ساخت کلید و CSR
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
<v-form ref="csrForm">
|
||||
<div class="mb-4">
|
||||
<div class="text-subtitle-2 mb-2">شخص</div>
|
||||
<v-radio-group
|
||||
v-model="csrData.personType"
|
||||
inline
|
||||
hide-details
|
||||
>
|
||||
<v-radio
|
||||
v-for="type in personTypes"
|
||||
:key="type.value"
|
||||
:label="type.title"
|
||||
:value="type.value"
|
||||
:disabled="type.value === 'natural'"
|
||||
></v-radio>
|
||||
</v-radio-group>
|
||||
</div>
|
||||
|
||||
<v-text-field
|
||||
v-model="csrData.nationalId"
|
||||
label="شناسه ملی"
|
||||
hide-details
|
||||
class="mb-4"
|
||||
></v-text-field>
|
||||
|
||||
<v-text-field
|
||||
v-model="csrData.nameFa"
|
||||
label="نام (فارسی)"
|
||||
hide-details
|
||||
class="mb-4"
|
||||
></v-text-field>
|
||||
|
||||
<v-text-field
|
||||
v-model="csrData.nameEn"
|
||||
label="نام (انگلیسی)"
|
||||
hide-details
|
||||
class="mb-4"
|
||||
></v-text-field>
|
||||
|
||||
<v-text-field
|
||||
v-model="csrData.email"
|
||||
label="ایمیل"
|
||||
type="email"
|
||||
hide-details
|
||||
class="mb-4"
|
||||
></v-text-field>
|
||||
</v-form>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn @click="showCSRDialog = false" variant="text">
|
||||
انصراف
|
||||
</v-btn>
|
||||
<v-btn @click="generateCSR()" color="primary" :loading="csrLoading">
|
||||
تایید
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
|
||||
<v-dialog v-model="showResultDialog" max-width="900px">
|
||||
<v-card>
|
||||
<v-card-title class="text-h6 pb-0">ساخت کلید و CSR</v-card-title>
|
||||
<v-card-text>
|
||||
<v-alert type="info" color="blue" class="mb-4" icon="mdi-alert">
|
||||
<span class="font-weight-bold">توجه: لطفا این اطلاعات را دانلود کنید و در یک جای امن نگهداری کنید. به دلایل امنیتی اطلاعات شما را نگهداری نمیکنیم، در صورتی که این اطلاعات را گم کنید، امکان بازیابی آن وجود ندارد.</span>
|
||||
</v-alert>
|
||||
<v-row>
|
||||
<v-col cols="12" md="4">
|
||||
<div class="mb-2 font-weight-bold">CSR</div>
|
||||
<v-textarea readonly rows="10" :value="resultData.csr" variant="outlined"></v-textarea>
|
||||
<v-row class="mt-2">
|
||||
<v-col cols="6">
|
||||
<v-btn color="success" block @click="copyToClipboard(resultData.csr)"><v-icon start>mdi-content-copy</v-icon>کپی</v-btn>
|
||||
</v-col>
|
||||
<v-col cols="6">
|
||||
<v-btn color="success" block @click="downloadFile(resultData.csr, 'csr.txt')"><v-icon start>mdi-download</v-icon>دانلود</v-btn>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-col>
|
||||
<v-col cols="12" md="4">
|
||||
<div class="mb-2 font-weight-bold">Public Key</div>
|
||||
<v-textarea readonly rows="10" :value="resultData.publicKey" variant="outlined"></v-textarea>
|
||||
<v-row class="mt-2">
|
||||
<v-col cols="6">
|
||||
<v-btn color="success" block @click="copyToClipboard(resultData.publicKey)"><v-icon start>mdi-content-copy</v-icon>کپی</v-btn>
|
||||
</v-col>
|
||||
<v-col cols="6">
|
||||
<v-btn color="success" block @click="downloadFile(resultData.publicKey, 'public_key.txt')"><v-icon start>mdi-download</v-icon>دانلود</v-btn>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-col>
|
||||
<v-col cols="12" md="4">
|
||||
<div class="mb-2 font-weight-bold">Private Key</div>
|
||||
<v-textarea readonly rows="10" :value="resultData.privateKey" variant="outlined"></v-textarea>
|
||||
<v-row class="mt-2">
|
||||
<v-col cols="6">
|
||||
<v-btn color="success" block @click="copyToClipboard(resultData.privateKey)"><v-icon start>mdi-content-copy</v-icon>کپی</v-btn>
|
||||
</v-col>
|
||||
<v-col cols="6">
|
||||
<v-btn color="success" block @click="downloadFile(resultData.privateKey, 'private_key.txt')"><v-icon start>mdi-download</v-icon>دانلود</v-btn>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn @click="showResultDialog = false" color="primary">بستن</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
|
||||
<v-snackbar
|
||||
v-model="snackbar.show"
|
||||
:color="snackbar.color"
|
||||
:timeout="3000"
|
||||
>
|
||||
{{ snackbar.text }}
|
||||
<template v-slot:actions>
|
||||
<v-btn
|
||||
color="white"
|
||||
variant="text"
|
||||
@click="snackbar.show = false"
|
||||
>
|
||||
بستن
|
||||
</v-btn>
|
||||
</template>
|
||||
</v-snackbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios';
|
||||
import Swal from 'sweetalert2';
|
||||
|
||||
export default {
|
||||
name: 'TaxSettings',
|
||||
data: () => ({
|
||||
loading: false,
|
||||
csrLoading: false,
|
||||
showCSRDialog: false,
|
||||
showResultDialog: false,
|
||||
settings: {
|
||||
taxMemoryId: '',
|
||||
economicCode: '',
|
||||
privateKey: '',
|
||||
},
|
||||
csrData: {
|
||||
personType: 'legal',
|
||||
nationalId: '',
|
||||
nameFa: '',
|
||||
nameEn: '',
|
||||
email: '',
|
||||
},
|
||||
resultData: {
|
||||
csr: '',
|
||||
publicKey: '',
|
||||
privateKey: ''
|
||||
},
|
||||
personTypes: [
|
||||
{ title: 'حقیقی', value: 'natural' },
|
||||
{ title: 'حقوقی', value: 'legal' }
|
||||
],
|
||||
snackbar: {
|
||||
show: false,
|
||||
text: '',
|
||||
color: 'success'
|
||||
}
|
||||
}),
|
||||
methods: {
|
||||
async loadSettings() {
|
||||
this.loading = true;
|
||||
try {
|
||||
const response = await axios.get('/api/plugins/tax-settings/get');
|
||||
this.settings = {
|
||||
...this.settings,
|
||||
...response.data
|
||||
};
|
||||
} catch (error) {
|
||||
this.showSnackbar('خطا در بارگذاری تنظیمات', 'error');
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
async saveSettings() {
|
||||
this.loading = true;
|
||||
try {
|
||||
const dataToSave = { ...this.settings };
|
||||
await axios.post('/api/plugins/tax-settings/save', dataToSave);
|
||||
this.showSnackbar('تنظیمات با موفقیت ذخیره شد', 'success');
|
||||
} catch (error) {
|
||||
this.showSnackbar('خطا در ذخیره تنظیمات', 'error');
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
async generateCSR() {
|
||||
this.csrLoading = true;
|
||||
try {
|
||||
const response = await axios.post('/api/plugins/tax-settings/generate-csr', this.csrData);
|
||||
|
||||
if (response.data.success) {
|
||||
// this.settings.privateKey = response.data.privateKey;
|
||||
// نمایش دیالوگ نتیجه
|
||||
this.resultData.csr = response.data.csr;
|
||||
this.resultData.privateKey = response.data.privateKey;
|
||||
this.resultData.publicKey = response.data.publicKey || '';
|
||||
this.showResultDialog = true;
|
||||
this.showCSRDialog = false;
|
||||
this.showSnackbar('کلید و CSR با موفقیت تولید شد', 'success');
|
||||
} else {
|
||||
this.showSnackbar(response.data.message || 'خطا در تولید کلید و CSR', 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
this.showSnackbar('خطا در تولید کلید و CSR', 'error');
|
||||
} finally {
|
||||
this.csrLoading = false;
|
||||
}
|
||||
},
|
||||
copyToClipboard(text) {
|
||||
navigator.clipboard.writeText(text);
|
||||
this.showSnackbar('کپی شد');
|
||||
},
|
||||
downloadFile(content, filename) {
|
||||
const blob = new Blob([content], { type: 'text/plain' });
|
||||
const link = document.createElement('a');
|
||||
link.href = URL.createObjectURL(blob);
|
||||
link.download = filename;
|
||||
link.click();
|
||||
URL.revokeObjectURL(link.href);
|
||||
},
|
||||
showSnackbar(text, color = 'success') {
|
||||
this.snackbar = {
|
||||
show: true,
|
||||
text,
|
||||
color
|
||||
};
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadSettings();
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -7,6 +7,12 @@ export default defineComponent({
|
|||
name: "system",
|
||||
data: () => {
|
||||
return {
|
||||
activeTab: 0,
|
||||
tabs: [
|
||||
{ title: 'تنظیمات پایه', icon: 'mdi-cog' },
|
||||
{ title: 'درگاههای پرداخت', icon: 'mdi-credit-card' },
|
||||
{ title: 'پنل استعلامات', icon: 'mdi-magnify' }
|
||||
],
|
||||
gatepays: [
|
||||
{
|
||||
title: 'زرینپال',
|
||||
|
@ -50,6 +56,10 @@ export default defineComponent({
|
|||
enablePostalCodeToAddress: false,
|
||||
inquiryPanelEnable: false,
|
||||
postalCodeToAddressFee: 0,
|
||||
enableCardToSheba: false,
|
||||
cardToShebaFee: 0,
|
||||
enableAccountToSheba: false,
|
||||
accountToShebaFee: 0,
|
||||
},
|
||||
loading: true,
|
||||
}
|
||||
|
@ -65,6 +75,8 @@ export default defineComponent({
|
|||
...data,
|
||||
enablePostalCodeToAddress: data.enablePostalCodeToAddress === '1' || data.enablePostalCodeToAddress === true,
|
||||
inquiryPanelEnable: data.inquiryPanelEnable === '1' || data.inquiryPanelEnable === true,
|
||||
enableCardToSheba: data.enableCardToSheba === '1' || data.enableCardToSheba === true,
|
||||
enableAccountToSheba: data.enableAccountToSheba === '1' || data.enableAccountToSheba === true,
|
||||
activeGateway: data.activeGateway || 'zarinpal',
|
||||
inquiryPanel: data.inquiryPanel || 'zohal'
|
||||
};
|
||||
|
@ -85,6 +97,39 @@ export default defineComponent({
|
|||
return;
|
||||
}
|
||||
|
||||
// Validation: if postal code to address is enabled, fee must be set
|
||||
if (this.systemInfo.enablePostalCodeToAddress && this.systemInfo.postalCodeToAddressFee < 0) {
|
||||
Swal.fire({
|
||||
text: 'کارمزد تبدیل کد پستی به آدرس نمیتواند منفی باشد.',
|
||||
icon: 'error',
|
||||
confirmButtonText: 'قبول',
|
||||
});
|
||||
this.loading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Validation: if card to sheba is enabled, fee must be set
|
||||
if (this.systemInfo.enableCardToSheba && this.systemInfo.cardToShebaFee < 0) {
|
||||
Swal.fire({
|
||||
text: 'کارمزد تبدیل شماره کارت به شبا نمیتواند منفی باشد.',
|
||||
icon: 'error',
|
||||
confirmButtonText: 'قبول',
|
||||
});
|
||||
this.loading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Validation: if account to sheba is enabled, fee must be set
|
||||
if (this.systemInfo.enableAccountToSheba && this.systemInfo.accountToShebaFee < 0) {
|
||||
Swal.fire({
|
||||
text: 'کارمزد تبدیل حساب به شبا نمیتواند منفی باشد.',
|
||||
icon: 'error',
|
||||
confirmButtonText: 'قبول',
|
||||
});
|
||||
this.loading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
axios.post('/api/admin/settings/system/info/save', this.systemInfo).then((resp) => {
|
||||
this.loading = false;
|
||||
if (resp.data.result == 1) {
|
||||
|
@ -94,6 +139,13 @@ export default defineComponent({
|
|||
confirmButtonText: 'قبول',
|
||||
});
|
||||
}
|
||||
}).catch((error) => {
|
||||
this.loading = false;
|
||||
Swal.fire({
|
||||
text: 'خطا در ذخیره تنظیمات. لطفاً دوباره تلاش کنید.',
|
||||
icon: 'error',
|
||||
confirmButtonText: 'قبول',
|
||||
});
|
||||
})
|
||||
|
||||
}
|
||||
|
@ -107,92 +159,491 @@ export default defineComponent({
|
|||
<template>
|
||||
<v-toolbar color="toolbar" :title="$t('pages.manager.system_settings_basic')">
|
||||
<v-spacer></v-spacer>
|
||||
<v-tooltip text="ذخیره تنظیمات" location="bottom">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn
|
||||
v-bind="props"
|
||||
icon
|
||||
@click="submit()"
|
||||
:loading="loading"
|
||||
color="primary"
|
||||
class="ml-2"
|
||||
>
|
||||
<v-icon>mdi-content-save</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
</v-toolbar>
|
||||
<v-container class="pa-0">
|
||||
<v-card :loading="loading" :disabled="loading">
|
||||
<v-card-text class="">
|
||||
<v-row class="mb-2">
|
||||
<v-col cols="12" sm="12" md="12">
|
||||
<v-text-field class="" hide-details="auto" :label="$t('pages.manager.app_site')"
|
||||
v-model="systemInfo.appSite" type="text" prepend-inner-icon="mdi-card-text"
|
||||
:rules="[() => systemInfo.appSite.length > 0 || $t('validator.required')]"></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="4">
|
||||
<v-select v-model="systemInfo.activeGateway" hide-details="auto" prepend-inner-icon="mdi-signal" :items="gatepays" item-title="title"
|
||||
item-value="value" label="Select" single-line>
|
||||
</v-select>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="4">
|
||||
<v-text-field class="" hide-details="auto" :label="$t('pages.manager.zarinpal_api')"
|
||||
v-model="systemInfo.zarinpal" type="text" prepend-inner-icon="mdi-text"></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="4">
|
||||
<v-text-field class="" hide-details="auto" :label="$t('pages.manager.parsian_api')"
|
||||
v-model="systemInfo.parsianGatewayAPI" type="text" prepend-inner-icon="mdi-text"></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="4">
|
||||
<v-text-field class="" hide-details="auto" :label="$t('pages.manager.payping_api')"
|
||||
v-model="systemInfo.paypingKey" type="text" prepend-inner-icon="mdi-text"></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="4">
|
||||
<v-text-field class="" hide-details="auto" :label="$t('pages.manager.bitpay_api')"
|
||||
v-model="systemInfo.bitpayKey" type="text" prepend-inner-icon="mdi-text"></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row class="mb-2">
|
||||
<v-col cols="12" sm="12" md="12">
|
||||
<v-subheader>{{ $t('pages.manager.inquiry_panel') }}</v-subheader>
|
||||
</v-col>
|
||||
<v-tabs v-model="activeTab" color="primary" grow>
|
||||
<v-tab
|
||||
v-for="(tab, index) in tabs"
|
||||
:key="index"
|
||||
:value="index"
|
||||
class="text-none"
|
||||
>
|
||||
<v-icon start>{{ tab.icon }}</v-icon>
|
||||
{{ tab.title }}
|
||||
</v-tab>
|
||||
</v-tabs>
|
||||
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<v-select v-model="systemInfo.inquiryPanel" hide-details="auto" prepend-inner-icon="mdi-signal" :items="inquiryPanel" item-title="title"
|
||||
item-value="value" label="Select" single-line>
|
||||
</v-select>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<v-text-field class="" hide-details="auto" :label="$t('pages.manager.inquiry_zohal_api_key')"
|
||||
v-model="systemInfo.inquiryZohalAPIKey" type="text" prepend-inner-icon="mdi-text"></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="12">
|
||||
<v-switch
|
||||
v-model="systemInfo.inquiryPanelEnable"
|
||||
:label="$t('pages.manager.inquiry_panel_enable')"
|
||||
color="primary"
|
||||
hide-details="auto"
|
||||
inset
|
||||
></v-switch>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="4">
|
||||
<v-switch
|
||||
v-model="systemInfo.enablePostalCodeToAddress"
|
||||
:label="$t('pages.manager.enable_postalcode_to_address')"
|
||||
color="primary"
|
||||
hide-details="auto"
|
||||
inset
|
||||
></v-switch>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="4">
|
||||
<v-text-field
|
||||
v-model.number="systemInfo.postalCodeToAddressFee"
|
||||
:label="$t('pages.manager.postalcode_to_address_fee')"
|
||||
type="number"
|
||||
min="0"
|
||||
prepend-inner-icon="mdi-currency-usd"
|
||||
hide-details="auto"
|
||||
suffix="ریال"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row class="mb-2">
|
||||
<v-col cols="12" sm="12" md="12">
|
||||
<v-btn type="submit" @click="submit()" color="primary" prepend-icon="mdi-content-save" :loading="loading">
|
||||
{{ $t('dialog.save') }}
|
||||
</v-btn>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
<v-window v-model="activeTab">
|
||||
<!-- تب اول: تنظیمات پایه -->
|
||||
<v-window-item :value="0">
|
||||
<v-card-text class="pa-8">
|
||||
<v-row class="mb-6">
|
||||
<v-col cols="12">
|
||||
<v-card variant="outlined" class="pa-6" elevation="0">
|
||||
<v-card-text class="pa-0">
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="8" lg="6">
|
||||
<v-text-field
|
||||
class=""
|
||||
hide-details="auto"
|
||||
:label="$t('pages.manager.app_site')"
|
||||
v-model="systemInfo.appSite"
|
||||
type="text"
|
||||
prepend-inner-icon="mdi-link"
|
||||
:rules="[() => systemInfo.appSite.length > 0 || $t('validator.required')]"
|
||||
variant="outlined"
|
||||
density="comfortable"
|
||||
placeholder="https://example.com"
|
||||
></v-text-field>
|
||||
<div class="text-caption text-medium-emphasis mt-2 d-flex align-center">
|
||||
<v-icon size="16" class="mr-1">mdi-information</v-icon>
|
||||
آدرس اصلی سایت که در سیستم استفاده میشود
|
||||
</div>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</v-window-item>
|
||||
|
||||
<!-- تب دوم: درگاههای پرداخت -->
|
||||
<v-window-item :value="1">
|
||||
<v-card-text class="pa-8">
|
||||
<v-row class="mb-6">
|
||||
<v-col cols="12">
|
||||
<v-card variant="outlined" class="pa-6" elevation="0">
|
||||
<v-card-text class="pa-0">
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="6" lg="4">
|
||||
<v-select
|
||||
v-model="systemInfo.activeGateway"
|
||||
hide-details="auto"
|
||||
prepend-inner-icon="mdi-check-circle"
|
||||
:items="gatepays"
|
||||
item-title="title"
|
||||
item-value="value"
|
||||
label="درگاه فعال"
|
||||
single-line
|
||||
variant="outlined"
|
||||
density="comfortable"
|
||||
></v-select>
|
||||
<div class="text-caption text-medium-emphasis mt-2 d-flex align-center">
|
||||
<v-icon size="16" class="mr-1">mdi-information</v-icon>
|
||||
درگاه پرداخت پیشفرض سیستم
|
||||
</div>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-divider class="my-6"></v-divider>
|
||||
|
||||
<div class="d-flex align-center mb-4">
|
||||
<v-icon size="20" color="secondary" class="mr-2">mdi-key</v-icon>
|
||||
<h4 class="text-subtitle-1 font-weight-medium">کلیدهای API</h4>
|
||||
</div>
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="6" lg="4">
|
||||
<v-text-field
|
||||
class=""
|
||||
hide-details="auto"
|
||||
:label="$t('pages.manager.zarinpal_api')"
|
||||
v-model="systemInfo.zarinpal"
|
||||
type="text"
|
||||
prepend-inner-icon="mdi-shield-key"
|
||||
variant="outlined"
|
||||
density="comfortable"
|
||||
placeholder="کلید API زرینپال"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6" lg="4">
|
||||
<v-text-field
|
||||
class=""
|
||||
hide-details="auto"
|
||||
:label="$t('pages.manager.parsian_api')"
|
||||
v-model="systemInfo.parsianGatewayAPI"
|
||||
type="text"
|
||||
prepend-inner-icon="mdi-shield-key"
|
||||
variant="outlined"
|
||||
density="comfortable"
|
||||
placeholder="کلید API پارسیان"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6" lg="4">
|
||||
<v-text-field
|
||||
class=""
|
||||
hide-details="auto"
|
||||
:label="$t('pages.manager.payping_api')"
|
||||
v-model="systemInfo.paypingKey"
|
||||
type="text"
|
||||
prepend-inner-icon="mdi-shield-key"
|
||||
variant="outlined"
|
||||
density="comfortable"
|
||||
placeholder="کلید API پیپینگ"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6" lg="4">
|
||||
<v-text-field
|
||||
class=""
|
||||
hide-details="auto"
|
||||
:label="$t('pages.manager.bitpay_api')"
|
||||
v-model="systemInfo.bitpayKey"
|
||||
type="text"
|
||||
prepend-inner-icon="mdi-shield-key"
|
||||
variant="outlined"
|
||||
density="comfortable"
|
||||
placeholder="کلید API بیتپی"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</v-window-item>
|
||||
|
||||
<!-- تب سوم: پنل استعلامات -->
|
||||
<v-window-item :value="2">
|
||||
<v-card-text class="pa-8">
|
||||
<v-row class="mb-6">
|
||||
<v-col cols="12">
|
||||
|
||||
<!-- تنظیمات اصلی پنل -->
|
||||
<v-card variant="outlined" class="pa-6 mb-6" elevation="0">
|
||||
<v-card-title class="text-subtitle-1 font-weight-medium pb-3 d-flex align-center">
|
||||
<v-icon start class="mr-2" color="secondary">mdi-cog</v-icon>
|
||||
تنظیمات اصلی
|
||||
</v-card-title>
|
||||
<v-card-text class="pa-0">
|
||||
<v-row>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<v-switch
|
||||
v-model="systemInfo.inquiryPanelEnable"
|
||||
:label="$t('pages.manager.inquiry_panel_enable')"
|
||||
color="primary"
|
||||
hide-details="auto"
|
||||
inset
|
||||
density="compact"
|
||||
></v-switch>
|
||||
<div class="text-caption text-medium-emphasis mt-1 d-flex align-center">
|
||||
<v-icon size="16" class="mr-1">mdi-information</v-icon>
|
||||
فعال/غیرفعال کردن پنل استعلامات
|
||||
</div>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<v-select
|
||||
v-model="systemInfo.inquiryPanel"
|
||||
hide-details="auto"
|
||||
prepend-inner-icon="mdi-view-dashboard"
|
||||
:items="inquiryPanel"
|
||||
item-title="title"
|
||||
item-value="value"
|
||||
label="انتخاب پنل"
|
||||
single-line
|
||||
variant="outlined"
|
||||
density="comfortable"
|
||||
></v-select>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="12">
|
||||
<v-text-field
|
||||
class=""
|
||||
hide-details="auto"
|
||||
:label="$t('pages.manager.inquiry_zohal_api_key')"
|
||||
v-model="systemInfo.inquiryZohalAPIKey"
|
||||
type="text"
|
||||
prepend-inner-icon="mdi-key"
|
||||
variant="outlined"
|
||||
density="comfortable"
|
||||
placeholder="کلید API پنل زحل"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
|
||||
<!-- سرویسهای تبدیل -->
|
||||
<div class="d-flex align-center mb-6">
|
||||
<div class="d-flex align-center bg-primary-lighten-5 pa-3 rounded-lg">
|
||||
<v-icon size="28" color="primary" class="mr-3">mdi-sync</v-icon>
|
||||
<div>
|
||||
<h4 class="text-h6 font-weight-medium text-primary mb-1">سرویسهای تبدیل</h4>
|
||||
<p class="text-caption text-medium-emphasis mb-0">مدیریت قابلیتهای تبدیل اطلاعات</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<v-row class="mb-4">
|
||||
<!-- تبدیل کد پستی به آدرس -->
|
||||
<v-col cols="12" sm="12" md="4">
|
||||
<v-card
|
||||
variant="outlined"
|
||||
class="service-card h-100"
|
||||
elevation="0"
|
||||
:class="{ 'service-card-active': systemInfo.enablePostalCodeToAddress }"
|
||||
>
|
||||
<div class="service-card-header bg-success-lighten-5 pa-4">
|
||||
<div class="d-flex align-center justify-space-between mb-3">
|
||||
<div class="d-flex align-center">
|
||||
<v-icon size="32" color="success" class="mr-3">mdi-map-marker</v-icon>
|
||||
<div>
|
||||
<h5 class="text-subtitle-1 font-weight-medium text-success mb-1">تبدیل کد پستی به آدرس</h5>
|
||||
<p class="text-caption text-medium-emphasis mb-0">تبدیل خودکار کد پستی به آدرس کامل</p>
|
||||
</div>
|
||||
</div>
|
||||
<v-chip
|
||||
:color="systemInfo.enablePostalCodeToAddress ? 'success' : 'grey'"
|
||||
size="small"
|
||||
variant="flat"
|
||||
>
|
||||
{{ systemInfo.enablePostalCodeToAddress ? 'فعال' : 'غیرفعال' }}
|
||||
</v-chip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<v-card-text class="pa-4">
|
||||
<v-row>
|
||||
<v-col cols="12" class="mb-3">
|
||||
<v-switch
|
||||
v-model="systemInfo.enablePostalCodeToAddress"
|
||||
:label="$t('pages.manager.enable_postalcode_to_address')"
|
||||
color="success"
|
||||
hide-details="auto"
|
||||
inset
|
||||
density="comfortable"
|
||||
></v-switch>
|
||||
</v-col>
|
||||
<v-col cols="12">
|
||||
<v-text-field
|
||||
v-model.number="systemInfo.postalCodeToAddressFee"
|
||||
:label="$t('pages.manager.postalcode_to_address_fee')"
|
||||
type="number"
|
||||
min="0"
|
||||
prepend-inner-icon="mdi-currency-usd"
|
||||
hide-details="auto"
|
||||
suffix="ریال"
|
||||
density="comfortable"
|
||||
variant="outlined"
|
||||
:disabled="!systemInfo.enablePostalCodeToAddress"
|
||||
:rules="[v => v >= 0 || 'کارمزد نمیتواند منفی باشد']"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
|
||||
<!-- تبدیل شماره کارت به شبا -->
|
||||
<v-col cols="12" sm="12" md="4">
|
||||
<v-card
|
||||
variant="outlined"
|
||||
class="service-card h-100"
|
||||
elevation="0"
|
||||
:class="{ 'service-card-active': systemInfo.enableCardToSheba }"
|
||||
>
|
||||
<div class="service-card-header bg-info-lighten-5 pa-4">
|
||||
<div class="d-flex align-center justify-space-between mb-3">
|
||||
<div class="d-flex align-center">
|
||||
<v-icon size="32" color="info" class="mr-3">mdi-credit-card</v-icon>
|
||||
<div>
|
||||
<h5 class="text-subtitle-1 font-weight-medium text-info mb-1">تبدیل شماره کارت به شبا</h5>
|
||||
<p class="text-caption text-medium-emphasis mb-0">تبدیل شماره کارت بانکی به شماره شبا</p>
|
||||
</div>
|
||||
</div>
|
||||
<v-chip
|
||||
:color="systemInfo.enableCardToSheba ? 'info' : 'grey'"
|
||||
size="small"
|
||||
variant="flat"
|
||||
>
|
||||
{{ systemInfo.enableCardToSheba ? 'فعال' : 'غیرفعال' }}
|
||||
</v-chip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<v-card-text class="pa-4">
|
||||
<v-row>
|
||||
<v-col cols="12" class="mb-3">
|
||||
<v-switch
|
||||
v-model="systemInfo.enableCardToSheba"
|
||||
:label="$t('pages.manager.enable_card_to_sheba')"
|
||||
color="info"
|
||||
hide-details="auto"
|
||||
inset
|
||||
density="comfortable"
|
||||
></v-switch>
|
||||
</v-col>
|
||||
<v-col cols="12">
|
||||
<v-text-field
|
||||
v-model.number="systemInfo.cardToShebaFee"
|
||||
:label="$t('pages.manager.card_to_sheba_fee')"
|
||||
type="number"
|
||||
min="0"
|
||||
prepend-inner-icon="mdi-currency-usd"
|
||||
hide-details="auto"
|
||||
suffix="ریال"
|
||||
density="comfortable"
|
||||
variant="outlined"
|
||||
:disabled="!systemInfo.enableCardToSheba"
|
||||
:rules="[v => v >= 0 || 'کارمزد نمیتواند منفی باشد']"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
|
||||
<!-- تبدیل حساب به شبا -->
|
||||
<v-col cols="12" sm="12" md="4">
|
||||
<v-card
|
||||
variant="outlined"
|
||||
class="service-card h-100"
|
||||
elevation="0"
|
||||
:class="{ 'service-card-active': systemInfo.enableAccountToSheba }"
|
||||
>
|
||||
<div class="service-card-header bg-warning-lighten-5 pa-4">
|
||||
<div class="d-flex align-center justify-space-between mb-3">
|
||||
<div class="d-flex align-center">
|
||||
<v-icon size="32" color="warning" class="mr-3">mdi-bank</v-icon>
|
||||
<div>
|
||||
<h5 class="text-subtitle-1 font-weight-medium text-warning mb-1">تبدیل حساب به شبا</h5>
|
||||
<p class="text-caption text-medium-emphasis mb-0">تبدیل شماره حساب بانکی به شماره شبا</p>
|
||||
</div>
|
||||
</div>
|
||||
<v-chip
|
||||
:color="systemInfo.enableAccountToSheba ? 'warning' : 'grey'"
|
||||
size="small"
|
||||
variant="flat"
|
||||
>
|
||||
{{ systemInfo.enableAccountToSheba ? 'فعال' : 'غیرفعال' }}
|
||||
</v-chip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<v-card-text class="pa-4">
|
||||
<v-row>
|
||||
<v-col cols="12" class="mb-3">
|
||||
<v-switch
|
||||
v-model="systemInfo.enableAccountToSheba"
|
||||
:label="$t('pages.manager.enable_account_to_sheba')"
|
||||
color="warning"
|
||||
hide-details="auto"
|
||||
inset
|
||||
density="comfortable"
|
||||
></v-switch>
|
||||
</v-col>
|
||||
<v-col cols="12">
|
||||
<v-text-field
|
||||
v-model.number="systemInfo.accountToShebaFee"
|
||||
:label="$t('pages.manager.account_to_sheba_fee')"
|
||||
type="number"
|
||||
min="0"
|
||||
prepend-inner-icon="mdi-currency-usd"
|
||||
hide-details="auto"
|
||||
suffix="ریال"
|
||||
density="comfortable"
|
||||
variant="outlined"
|
||||
:disabled="!systemInfo.enableAccountToSheba"
|
||||
:rules="[v => v >= 0 || 'کارمزد نمیتواند منفی باشد']"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</v-window-item>
|
||||
</v-window>
|
||||
</v-card>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped>
|
||||
.service-card {
|
||||
transition: all 0.3s ease;
|
||||
border: 2px solid transparent;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.service-card:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1) !important;
|
||||
}
|
||||
|
||||
.service-card-active {
|
||||
border-color: var(--v-primary-base);
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08) !important;
|
||||
}
|
||||
|
||||
.service-card-active::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 3px;
|
||||
background: linear-gradient(90deg, var(--v-primary-base), var(--v-secondary-base));
|
||||
}
|
||||
|
||||
.service-card-header {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.service-card-header::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 1px;
|
||||
background: linear-gradient(90deg, transparent, rgba(0, 0, 0, 0.1), transparent);
|
||||
}
|
||||
|
||||
/* انیمیشن برای chip ها */
|
||||
.v-chip {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.v-chip:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
/* استایل برای فیلدهای غیرفعال */
|
||||
.v-text-field--disabled {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
/* بهبود ظاهر switch */
|
||||
.v-switch {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
/* استایل برای آیکونها */
|
||||
.service-card .v-icon {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.service-card:hover .v-icon {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
</style>
|
Loading…
Reference in a new issue