forked from morrning/hesabixCore
Compare commits
11 commits
c20652b8cd
...
574bdd1a5b
Author | SHA1 | Date | |
---|---|---|---|
|
574bdd1a5b | ||
|
7090ff44dc | ||
|
2a8ea8cb4a | ||
|
227767b0d6 | ||
|
2cb7b8945c | ||
|
7762613814 | ||
|
90f5a5b338 | ||
|
b1f8af83f4 | ||
|
0d18762f1e | ||
|
82740193cb | ||
|
ddbbf1f102 |
|
@ -1,8 +1,3 @@
|
|||
# توقف فعالیت در گیتهاب به دلیل نگرانیهای اخلاقی
|
||||
ما به دلیل استفاده مایکروسافت از هوش مصنوعی در تولید سلاحهای نظامی و آموزش مدلهای هوش مصنوعی با دادههای غیرنظامیان، تصمیم گرفتیم تمام فعالیتهای خود را در پلتفرم گیتهاب متوقف کنیم. این تصمیم به منظور پایبندی به اصول اخلاقی و مسئولیت اجتماعی اتخاذ شده است.
|
||||
برای دسترسی به سورسکدها و مشارکت در پروژههای ما، لطفاً به وبسایت رسمی ما به آدرس [source.hesabix.ir](https://source.hesabix.ir) مراجعه کنید.
|
||||
با تشکر از حمایت و همراهی شما.
|
||||
|
||||
# حسابیکس - نرمافزار حسابداری متنباز
|
||||
|
||||
<img src="https://hesabix.ir/favicon/favicon.svg" alt="Hesabix Logo" width="100" height="100" />
|
||||
|
|
|
@ -109,7 +109,7 @@
|
|||
"symfony/browser-kit": "7.2.*",
|
||||
"symfony/css-selector": "7.2.*",
|
||||
"symfony/debug-bundle": "7.2.*",
|
||||
"symfony/maker-bundle": "^1.64",
|
||||
"symfony/maker-bundle": "^1.62",
|
||||
"symfony/phpunit-bridge": "^7.2",
|
||||
"symfony/stopwatch": "7.2.*",
|
||||
"symfony/web-profiler-bundle": "7.2.*"
|
||||
|
|
21
hesabixCore/composer.lock
generated
21
hesabixCore/composer.lock
generated
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "fc8e55a0f3d505b2453542a73030d32c",
|
||||
"content-hash": "389f897ebd1e0befdd15876e5d6a43a7",
|
||||
"packages": [
|
||||
{
|
||||
"name": "brick/math",
|
||||
|
@ -11063,21 +11063,21 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/maker-bundle",
|
||||
"version": "v1.64.0",
|
||||
"version": "v1.62.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/maker-bundle.git",
|
||||
"reference": "c86da84640b0586e92aee2b276ee3638ef2f425a"
|
||||
"reference": "468ff2708200c95ebc0d85d3174b6c6711b8a590"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/maker-bundle/zipball/c86da84640b0586e92aee2b276ee3638ef2f425a",
|
||||
"reference": "c86da84640b0586e92aee2b276ee3638ef2f425a",
|
||||
"url": "https://api.github.com/repos/symfony/maker-bundle/zipball/468ff2708200c95ebc0d85d3174b6c6711b8a590",
|
||||
"reference": "468ff2708200c95ebc0d85d3174b6c6711b8a590",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"doctrine/inflector": "^2.0",
|
||||
"nikic/php-parser": "^5.0",
|
||||
"nikic/php-parser": "^4.18|^5.0",
|
||||
"php": ">=8.1",
|
||||
"symfony/config": "^6.4|^7.0",
|
||||
"symfony/console": "^6.4|^7.0",
|
||||
|
@ -11100,7 +11100,6 @@
|
|||
"symfony/http-client": "^6.4|^7.0",
|
||||
"symfony/phpunit-bridge": "^6.4.1|^7.0",
|
||||
"symfony/security-core": "^6.4|^7.0",
|
||||
"symfony/security-http": "^6.4|^7.0",
|
||||
"symfony/yaml": "^6.4|^7.0",
|
||||
"twig/twig": "^3.0|^4.x-dev"
|
||||
},
|
||||
|
@ -11136,7 +11135,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/symfony/maker-bundle/issues",
|
||||
"source": "https://github.com/symfony/maker-bundle/tree/v1.64.0"
|
||||
"source": "https://github.com/symfony/maker-bundle/tree/v1.62.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -11152,7 +11151,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-06-23T16:12:08+00:00"
|
||||
"time": "2025-01-15T00:21:40+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/phpunit-bridge",
|
||||
|
@ -11371,7 +11370,7 @@
|
|||
],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": {},
|
||||
"stability-flags": [],
|
||||
"prefer-stable": true,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
|
@ -11381,6 +11380,6 @@
|
|||
"ext-fileinfo": "*",
|
||||
"ext-iconv": "*"
|
||||
},
|
||||
"platform-dev": {},
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.6.0"
|
||||
}
|
||||
|
|
37
hesabixCore/migrations/Version20241201000000.php
Normal file
37
hesabixCore/migrations/Version20241201000000.php
Normal file
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20241201000000 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Create postal_code_inquiry table';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('CREATE TABLE postal_code_inquiry (
|
||||
id INT AUTO_INCREMENT NOT NULL,
|
||||
postal_code VARCHAR(10) NOT NULL,
|
||||
address_data JSON NOT NULL,
|
||||
created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\',
|
||||
updated_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\',
|
||||
UNIQUE INDEX UNIQ_POSTAL_CODE (postal_code),
|
||||
PRIMARY KEY(id)
|
||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('DROP TABLE postal_code_inquiry');
|
||||
}
|
||||
}
|
|
@ -430,7 +430,7 @@ class AdminController extends AbstractController
|
|||
if (array_key_exists('rejectChequeInput', $params['plugAccpro']))
|
||||
$registryMGR->update('sms', 'plugAccproRejectChequeInput', $params['plugAccpro']['rejectChequeInput']);
|
||||
}
|
||||
|
||||
|
||||
return $this->json(JsonResp::success());
|
||||
}
|
||||
|
||||
|
@ -450,6 +450,15 @@ class AdminController extends AbstractController
|
|||
$resp['parsianGatewayAPI'] = $registryMGR->get('system', key: 'parsianGatewayAPI');
|
||||
$resp['paypingKey'] = $registryMGR->get('system', key: 'paypingKey');
|
||||
$resp['bitpayKey'] = $registryMGR->get('system', key: 'bitpayKey');
|
||||
$resp['inquiryPanel'] = $registryMGR->get('system', key: 'inquiryPanel');
|
||||
$resp['inquiryZohalAPIKey'] = $registryMGR->get('system', key: 'inquiryZohalAPIKey');
|
||||
$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);
|
||||
}
|
||||
|
||||
|
@ -474,6 +483,15 @@ class AdminController extends AbstractController
|
|||
$registryMGR->update('system', 'parsianGatewayAPI', $params['parsianGatewayAPI']);
|
||||
$registryMGR->update('system', 'paypingKey', $params['paypingKey']);
|
||||
$registryMGR->update('system', 'bitpayKey', $params['bitpayKey']);
|
||||
$registryMGR->update('system', 'inquiryPanel', $params['inquiryPanel']);
|
||||
$registryMGR->update('system', 'inquiryZohalAPIKey', $params['inquiryZohalAPIKey']);
|
||||
$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]);
|
||||
|
@ -592,6 +610,7 @@ class AdminController extends AbstractController
|
|||
$temp['cardPan'] = $item->getCardPan();
|
||||
$temp['refID'] = $item->getRefID();
|
||||
$temp['shaba'] = $item->getShaba();
|
||||
$temp['amount'] = $item->getAmount();
|
||||
$temp['dateSubmit'] = $jdate->jdate('Y/n/d H:i', $item->getDateSubmit());
|
||||
$temp['gatePay'] = $item->getGatePay();
|
||||
$resp[] = $temp;
|
||||
|
|
|
@ -545,6 +545,7 @@ class BusinessController extends AbstractController
|
|||
'plugHrmDocs' => true,
|
||||
'plugGhestaManager' => true,
|
||||
'plugTaxSettings' => true,
|
||||
'inquiry' => true,
|
||||
];
|
||||
} elseif ($perm) {
|
||||
$result = [
|
||||
|
@ -589,6 +590,7 @@ class BusinessController extends AbstractController
|
|||
'plugHrmDocs' => $perm->isPlugHrmDocs(),
|
||||
'plugGhestaManager' => $perm->isPlugGhestaManager(),
|
||||
'plugTaxSettings' => $perm->isPlugTaxSettings(),
|
||||
'inquiry' => $perm->isInquiry(),
|
||||
];
|
||||
}
|
||||
return $this->json($result);
|
||||
|
@ -658,6 +660,8 @@ class BusinessController extends AbstractController
|
|||
$perm->setPlugRepservice($params['plugRepservice']);
|
||||
$perm->setPlugHrmDocs($params['plugHrmDocs']);
|
||||
$perm->setPlugGhestaManager($params['plugGhestaManager']);
|
||||
$perm->setPlugTaxSettings($params['plugTaxSettings']);
|
||||
$perm->setInquiry($params['inquiry']);
|
||||
$entityManager->persist($perm);
|
||||
$entityManager->flush();
|
||||
$log->insert('تنظیمات پایه', 'ویرایش دسترسیهای کاربر با پست الکترونیکی ' . $user->getEmail(), $this->getUser(), $business);
|
||||
|
|
|
@ -143,7 +143,8 @@ class CommodityController extends AbstractController
|
|||
$count += $row->getCommdityCount();
|
||||
} else {
|
||||
$count -= $row->getCommdityCount();
|
||||
} }
|
||||
}
|
||||
}
|
||||
$temp['count'] = $count;
|
||||
}
|
||||
return $temp;
|
||||
|
@ -1071,17 +1072,41 @@ class CommodityController extends AbstractController
|
|||
if ($content = $request->getContent()) {
|
||||
$params = json_decode($content, true);
|
||||
}
|
||||
if (!array_key_exists('upper', $params) || !array_key_exists('text', $params))
|
||||
|
||||
if (!array_key_exists('text', $params))
|
||||
return $this->json(['result' => -1]);
|
||||
|
||||
|
||||
if ($this->isDefaultCategoryName($params['text'])) {
|
||||
return $this->json([
|
||||
'result' => 4,
|
||||
'result' => 4,
|
||||
'message' => 'این نام برای دستهبندی مجاز نیست',
|
||||
'errorCode' => 'DEFAULT_CATEGORY_NAME'
|
||||
]);
|
||||
}
|
||||
|
||||
if (!array_key_exists('upper', $params)) {
|
||||
$upper = $entityManager->getRepository(CommodityCat::class)->findOneBy([
|
||||
'upper' => null,
|
||||
'bid' => $acc['bid']
|
||||
]);
|
||||
if (!$upper) {
|
||||
$upper = new CommodityCat();
|
||||
$upper->setBid($acc['bid']);
|
||||
$upper->setUpper(null);
|
||||
$upper->setName('دسته بندی ها');
|
||||
$upper->setRoot(true);
|
||||
$entityManager->persist($upper);
|
||||
$entityManager->flush();
|
||||
}
|
||||
$cat = new CommodityCat();
|
||||
$cat->setBid($acc['bid']);
|
||||
$cat->setRoot(false);
|
||||
$cat->setName($params['text']);
|
||||
$cat->setUpper($upper->getId());
|
||||
$entityManager->persist($cat);
|
||||
$entityManager->flush();
|
||||
return $this->json(['result' => 1, 'id' => $cat->getId()]);
|
||||
}
|
||||
|
||||
$upper = $entityManager->getRepository(CommodityCat::class)->find($params['upper']);
|
||||
if ($upper) {
|
||||
if ($upper->getBid() == $acc['bid']) {
|
||||
|
@ -1109,22 +1134,22 @@ class CommodityController extends AbstractController
|
|||
}
|
||||
if (!array_key_exists('id', $params) || !array_key_exists('text', $params))
|
||||
return $this->json(['result' => -1]);
|
||||
|
||||
|
||||
if ($this->isDefaultCategoryName($params['text'])) {
|
||||
return $this->json([
|
||||
'result' => 4,
|
||||
'result' => 4,
|
||||
'message' => 'این نام برای دستهبندی مجاز نیست',
|
||||
'errorCode' => 'DEFAULT_CATEGORY_NAME'
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
$node = $entityManager->getRepository(CommodityCat::class)->find($params['id']);
|
||||
if ($node) {
|
||||
if ($node->getBid() == $acc['bid']) {
|
||||
// بررسی دستهبندی پیشفرض
|
||||
if ($this->isDefaultCategoryName($node->getName())) {
|
||||
return $this->json([
|
||||
'result' => 4,
|
||||
'result' => 4,
|
||||
'message' => 'ویرایش دستهبندی پیشفرض مجاز نیست',
|
||||
'errorCode' => 'DEFAULT_CATEGORY_EDIT'
|
||||
]);
|
||||
|
@ -1588,7 +1613,7 @@ class CommodityController extends AbstractController
|
|||
// بررسی دستهبندی پیشفرض
|
||||
if ($this->isDefaultCategoryName($category->getName())) {
|
||||
return $this->json([
|
||||
'Success' => false,
|
||||
'Success' => false,
|
||||
'message' => 'حذف دستهبندی پیشفرض مجاز نیست',
|
||||
'errorCode' => 'DEFAULT_CATEGORY_DELETE'
|
||||
], 400);
|
||||
|
|
|
@ -12,8 +12,6 @@ use Symfony\Component\HttpFoundation\JsonResponse;
|
|||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use App\Entity\PluginTaxsettingsKey;
|
||||
use App\Entity\HesabdariDoc;
|
||||
use App\Entity\PluginTaxInvoice;
|
||||
|
||||
class TaxSettingsController extends AbstractController
|
||||
{
|
||||
|
@ -200,285 +198,4 @@ class TaxSettingsController extends AbstractController
|
|||
|
||||
return $csr;
|
||||
}
|
||||
|
||||
#[Route('/api/plugins/tax/settings/send-invoice', name: 'plugin_tax_settings_send_invoice', methods: ['POST'])]
|
||||
public function plugin_tax_settings_send_invoice(Request $request, Access $access, Log $log, EntityManagerInterface $em): JsonResponse
|
||||
{
|
||||
$acc = $access->hasRole('plugTaxSettings');
|
||||
if (!$acc) {
|
||||
throw $this->createAccessDeniedException('شما دسترسی لازم را ندارید.');
|
||||
}
|
||||
|
||||
$params = $request->getPayload()->all();
|
||||
$invoiceCode = $params['code'] ?? null;
|
||||
|
||||
if (!$invoiceCode) {
|
||||
return $this->json([
|
||||
'success' => false,
|
||||
'message' => 'کد فاکتور الزامی است'
|
||||
]);
|
||||
}
|
||||
|
||||
$businessId = is_object($acc['bid']) ? $acc['bid']->getId() : $acc['bid'];
|
||||
$userId = $this->getUser()->getId();
|
||||
|
||||
try {
|
||||
// دریافت اطلاعات فاکتور از دیتابیس
|
||||
$invoiceRepo = $em->getRepository(HesabdariDoc::class);
|
||||
$invoice = $invoiceRepo->findOneBy([
|
||||
'code' => $invoiceCode,
|
||||
'bid' => $businessId,
|
||||
'type' => 'sell'
|
||||
]);
|
||||
|
||||
if (!$invoice) {
|
||||
return $this->json([
|
||||
'success' => false,
|
||||
'message' => 'فاکتور مورد نظر یافت نشد'
|
||||
]);
|
||||
}
|
||||
|
||||
// دریافت تنظیمات مالیاتی
|
||||
$taxRepo = $em->getRepository(PluginTaxsettingsKey::class);
|
||||
$taxSettings = $taxRepo->findOneBy([
|
||||
'business_id' => $businessId,
|
||||
'user_id' => $userId
|
||||
]);
|
||||
|
||||
if (!$taxSettings || !$taxSettings->getPrivateKey()) {
|
||||
return $this->json([
|
||||
'success' => false,
|
||||
'message' => 'تنظیمات مالیاتی تکمیل نشده است. لطفاً ابتدا تنظیمات را تکمیل کنید.'
|
||||
]);
|
||||
}
|
||||
|
||||
// اینجا کد ارسال به سامانه مودیان قرار میگیرد
|
||||
// فعلاً فقط پیام موفقیت برمیگردانیم
|
||||
$result = $this->sendInvoiceToTaxSystem($invoice, $taxSettings, $em, $businessId, $userId);
|
||||
|
||||
if ($result['success']) {
|
||||
$log->insert('ارسال به سامانه مودیان', 'فاکتور ' . $invoiceCode . ' به سامانه مودیان ارسال شد', $this->getUser(), $businessId);
|
||||
|
||||
return $this->json([
|
||||
'success' => true,
|
||||
'message' => 'فاکتور با موفقیت به سامانه مودیان ارسال شد',
|
||||
'data' => $result['data'] ?? null
|
||||
]);
|
||||
} else {
|
||||
return $this->json([
|
||||
'success' => false,
|
||||
'message' => $result['message'] ?? 'خطا در ارسال به سامانه مودیان'
|
||||
]);
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$log->insert('خطا در ارسال به سامانه مودیان', 'خطا در ارسال فاکتور ' . $invoiceCode . ': ' . $e->getMessage(), $this->getUser(), $businessId);
|
||||
|
||||
return $this->json([
|
||||
'success' => false,
|
||||
'message' => 'خطا در ارسال به سامانه مودیان: ' . $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
private function sendInvoiceToTaxSystem($invoice, $taxSettings, $em, $businessId, $userId): array
|
||||
{
|
||||
try {
|
||||
// بررسی اینکه آیا این فاکتور قبلاً ارسال شده یا نه
|
||||
$taxInvoiceRepo = $em->getRepository(PluginTaxInvoice::class);
|
||||
$existingRecord = $taxInvoiceRepo->findByInvoiceCodeAndBusiness($invoice->getCode(), $businessId);
|
||||
|
||||
if ($existingRecord) {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'این فاکتور قبلاً به سامانه مودیان ارسال شده است.'
|
||||
];
|
||||
}
|
||||
|
||||
// ایجاد رکورد جدید
|
||||
$taxInvoice = new PluginTaxInvoice();
|
||||
$taxInvoice->setBusiness($em->getRepository(\App\Entity\Business::class)->find($businessId));
|
||||
$taxInvoice->setUser($em->getRepository(\App\Entity\User::class)->find($userId));
|
||||
$taxInvoice->setInvoice($invoice);
|
||||
$taxInvoice->setInvoiceCode($invoice->getCode());
|
||||
$taxInvoice->setAmount($invoice->getAmount());
|
||||
$taxInvoice->setStatus('pending');
|
||||
|
||||
// دریافت اطلاعات مشتری
|
||||
$customerName = null;
|
||||
$customerId = null;
|
||||
$rows = $invoice->getHesabdariRows();
|
||||
foreach ($rows as $row) {
|
||||
if ($row->getPerson()) {
|
||||
$customerName = $row->getPerson()->getNikename();
|
||||
$customerId = $row->getPerson()->getCode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
$taxInvoice->setCustomerName($customerName);
|
||||
$taxInvoice->setCustomerId($customerId);
|
||||
|
||||
// ذخیره رکورد
|
||||
$em->persist($taxInvoice);
|
||||
$em->flush();
|
||||
|
||||
// اینجا کد واقعی ارسال به سامانه مودیان قرار میگیرد
|
||||
// فعلاً یک پیام موفقیت برمیگردانیم
|
||||
|
||||
// مثال کد ارسال به API سامانه مودیان:
|
||||
/*
|
||||
$invoiceData =
|
||||
invoiceNumber => $invoice->getCode(),
|
||||
date => $invoice->getDate(),
|
||||
totalAmount => $invoice->getAmount(),
|
||||
customerName=> $customerName,
|
||||
customerNationalId' => $customerNationalId,
|
||||
// سایر اطلاعات فاکتور
|
||||
];
|
||||
|
||||
$response = $this->callTaxSystemAPI($invoiceData, $taxSettings);
|
||||
|
||||
if ($response['success']) {
|
||||
// بهروزرسانی وضعیت به sent
|
||||
$taxInvoice->setStatus('sent');
|
||||
$taxInvoice->setSentAt(new \DateTimeImmutable());
|
||||
$taxInvoice->setTaxSystemInvoiceNumber($response['data']['invoiceNumber'] ?? null);
|
||||
$taxInvoice->setTaxSystemReferenceNumber($response['data']['referenceNumber'] ?? null);
|
||||
$taxInvoice->setResponseData(json_encode($response['data']));
|
||||
$em->flush();
|
||||
|
||||
return [
|
||||
success' => true,
|
||||
data' => $response['data] ];
|
||||
} else {
|
||||
// بهروزرسانی وضعیت به failed
|
||||
$taxInvoice->setStatus('failed');
|
||||
$taxInvoice->setErrorMessage($response['message']);
|
||||
$em->flush();
|
||||
|
||||
return [
|
||||
success' => false,
|
||||
message' => $response['message] ];
|
||||
}
|
||||
*/
|
||||
|
||||
// فعلاً برای تست، پیام موفقیت برمیگردانیم
|
||||
$taxInvoice->setStatus('sent');
|
||||
$taxInvoice->setSentAt(new \DateTimeImmutable());
|
||||
$taxInvoice->setTaxSystemInvoiceNumber('TAX-' . $invoice->getCode());
|
||||
$taxInvoice->setTaxSystemReferenceNumber('REF-' . $invoice->getCode());
|
||||
$taxInvoice->setResponseData(json_encode(['status' => 'success', 'message' => 'Test response']));
|
||||
$em->flush();
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'data' => [
|
||||
'invoiceNumber' => $invoice->getCode(),
|
||||
'taxSystemInvoiceNumber' => $taxInvoice->getTaxSystemInvoiceNumber(),
|
||||
'taxSystemReferenceNumber' => $taxInvoice->getTaxSystemReferenceNumber(),
|
||||
'sentAt' => $taxInvoice->getSentAt()->format('Y-m-d H:i:s')
|
||||
]
|
||||
];
|
||||
|
||||
} catch (\Exception $e) {
|
||||
// در صورت خطا، وضعیت را به failed تغییر دهید
|
||||
if (isset($taxInvoice)) {
|
||||
$taxInvoice->setStatus('failed');
|
||||
$taxInvoice->setErrorMessage($e->getMessage());
|
||||
$em->flush();
|
||||
}
|
||||
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'خطا در ارسال به سامانه مودیان: ' . $e->getMessage()
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
#[Route('/api/plugins/tax/invoices/list', name: 'plugin_tax_settings_invoices_list', methods: ['GET'])]
|
||||
public function plugin_tax_settings_invoices_list(Request $request, Access $access, EntityManagerInterface $em): JsonResponse
|
||||
{
|
||||
$acc = $access->hasRole('plugTaxSettings');
|
||||
if (!$acc) {
|
||||
throw $this->createAccessDeniedException('شما دسترسی لازم را ندارید.');
|
||||
}
|
||||
|
||||
$businessId = is_object($acc['bid']) ? $acc['bid']->getId() : $acc['bid'];
|
||||
|
||||
try {
|
||||
$taxInvoiceRepo = $em->getRepository(PluginTaxInvoice::class);
|
||||
$invoices = $taxInvoiceRepo->findByBusiness($businessId);
|
||||
|
||||
$result = [];
|
||||
foreach ($invoices as $taxInvoice) {
|
||||
$invoice = $taxInvoice->getInvoice();
|
||||
|
||||
// دریافت اطلاعات کامل فاکتور اصلی
|
||||
$invoiceDetails = null;
|
||||
if ($invoice) {
|
||||
$invoiceDetails = [
|
||||
'id' => $invoice->getId(),
|
||||
'code' => $invoice->getCode(),
|
||||
'date' => $invoice->getDate(),
|
||||
'des' => $invoice->getDes(),
|
||||
'amount' => $invoice->getAmount(),
|
||||
'type' => $invoice->getType(),
|
||||
'status' => $invoice->getStatus(),
|
||||
'shortlink' => $invoice->getShortlink(),
|
||||
'taxPercent' => $invoice->getTaxPercent(),
|
||||
'discountType' => $invoice->getDiscountType(),
|
||||
'discountPercent' => $invoice->getDiscountPercent()
|
||||
];
|
||||
}
|
||||
|
||||
$result[] = [
|
||||
'id' => $taxInvoice->getId(),
|
||||
'invoiceNumber' => $taxInvoice->getInvoiceCode(),
|
||||
'date' => $invoice ? $invoice->getDate() : null,
|
||||
'customerName' => $taxInvoice->getCustomerName(),
|
||||
'customerId' => $taxInvoice->getCustomerId(),
|
||||
'totalAmount' => $taxInvoice->getAmount(),
|
||||
'status' => $taxInvoice->getStatus(),
|
||||
'sentDate' => $taxInvoice->getSentAt() ? $taxInvoice->getSentAt()->format('Y-m-d H:i:s') : null,
|
||||
'errorMessage' => $taxInvoice->getErrorMessage(),
|
||||
'createdAt' => $taxInvoice->getCreatedAt()->format('Y-m-d H:i:s'),
|
||||
'uniqueTaxNumber' => $taxInvoice->getTaxSystemInvoiceNumber(),
|
||||
'referenceUniqueTaxNumber' => $taxInvoice->getTaxSystemReferenceNumber(),
|
||||
'invoiceType' => $this->getInvoiceType($invoice),
|
||||
'invoiceDetails' => $invoiceDetails
|
||||
];
|
||||
}
|
||||
|
||||
return $this->json([
|
||||
'success' => true,
|
||||
'data' => $result
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return $this->json([
|
||||
'success' => false,
|
||||
'message' => 'خطا در دریافت لیست فاکتورها: ' . $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
private function getInvoiceType($invoice): string
|
||||
{
|
||||
if (!$invoice) {
|
||||
return 'اصلی';
|
||||
}
|
||||
|
||||
switch ($invoice->getType()) {
|
||||
case 'sell':
|
||||
return 'اصلی';
|
||||
case 'return_sell':
|
||||
return 'برگشت از فروش';
|
||||
case 'correction':
|
||||
return 'اصلاحی';
|
||||
case 'cancel':
|
||||
return 'ابطالی';
|
||||
default:
|
||||
return 'اصلی';
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,327 @@
|
|||
<?php
|
||||
|
||||
namespace App\Controller\Plugins\inquiry;
|
||||
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use App\Entity\PlugGhestaDoc;
|
||||
use App\Entity\PlugGhestaItem;
|
||||
use App\Entity\HesabdariDoc;
|
||||
use App\Entity\Person;
|
||||
use App\Service\Access;
|
||||
use App\Service\Provider;
|
||||
use App\Service\Printers;
|
||||
use App\Entity\PrintOptions;
|
||||
use App\Service\Log;
|
||||
use App\Entity\Business;
|
||||
use App\Service\registryMGR;
|
||||
use App\Service\Inquiry;
|
||||
|
||||
class PlugInquiryMainController extends AbstractController
|
||||
{
|
||||
private $entityManager;
|
||||
|
||||
public function __construct(EntityManagerInterface $entityManager)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
#[Route('/api/plugins/inquiry/settings/get', name: 'plugin_inquiry_settings_get', methods: ['GET'])]
|
||||
public function plugin_inquiry_settings_get(registryMGR $registryMGR): JsonResponse
|
||||
{
|
||||
$resp['inquiryPanel'] = $registryMGR->get('system', key: 'inquiryPanel');
|
||||
$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);
|
||||
}
|
||||
|
||||
#[Route('/api/plugins/inquiry/postalcode-to-address', name: 'plugin_inquiry_postalcode_to_address', methods: ['POST'])]
|
||||
public function plugin_inquiry_postalcode_to_address(Inquiry $inquiry, Access $access, Request $request, registryMGR $registryMGR, Log $log): JsonResponse
|
||||
{
|
||||
$acc = $access->hasRole('inquiry');
|
||||
if (!$acc) {
|
||||
return $this->json([
|
||||
'success' => false,
|
||||
'message' => 'شما دسترسی به این سرویس را ندارید'
|
||||
]);
|
||||
}
|
||||
|
||||
// دریافت کد پستی از درخواست
|
||||
$data = json_decode($request->getContent(), true);
|
||||
$postalCode = $data['postal_code'] ?? null;
|
||||
if (!$postalCode) {
|
||||
return $this->json([
|
||||
'success' => false,
|
||||
'message' => 'کد پستی ارسال نشده است'
|
||||
]);
|
||||
}
|
||||
|
||||
// فراخوانی سرویس استعلام کد پستی
|
||||
$result = $inquiry->postalCodeToAddress($postalCode);
|
||||
|
||||
// بررسی نتیجه و بازگرداندن پاسخ مناسب
|
||||
if (isset($result['result']) && $result['result'] == 1) {
|
||||
$isFromCache = isset($result['response_body']['message']) &&
|
||||
strpos($result['response_body']['message'], 'از کش') !== false;
|
||||
|
||||
// ثبت لاگ بر اساس منبع داده
|
||||
$logMessage = $isFromCache
|
||||
? "استعلام کد پستی {$postalCode} از کش (بدون کسر کارمزد)"
|
||||
: "استعلام کد پستی {$postalCode} از API (کسر کارمزد: " . $registryMGR->get('system', key: 'postalCodeToAddressFee') . " ریال)";
|
||||
|
||||
$log->insert(
|
||||
'استعلام',
|
||||
$logMessage,
|
||||
$acc['user'],
|
||||
$acc['bid']
|
||||
);
|
||||
|
||||
// فقط در صورت عدم وجود در کش، کارمزد کسر شود
|
||||
if (!$isFromCache) {
|
||||
if ($acc['bid']->getSmsCharge() < $registryMGR->get('system', key: 'postalCodeToAddressFee')) {
|
||||
// ثبت لاگ عدم موجودی کافی
|
||||
$log->insert(
|
||||
'استعلام',
|
||||
"عدم موجودی کافی برای استعلام کد پستی {$postalCode}",
|
||||
$acc['user'],
|
||||
$acc['bid']
|
||||
);
|
||||
|
||||
return $this->json([
|
||||
'success' => false,
|
||||
'message' => 'موجودی شما برای این سرویس کافی نیست'
|
||||
]);
|
||||
}
|
||||
|
||||
$business = $acc['bid'];
|
||||
$business->setSmsCharge($business->getSmsCharge() - $registryMGR->get('system', key: 'postalCodeToAddressFee'));
|
||||
$this->entityManager->persist($business);
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
|
||||
return $this->json([
|
||||
'success' => true,
|
||||
'data' => $result['response_body']['data']['address'] ?? null,
|
||||
'message' => $result['response_body']['message'] ?? 'موفق',
|
||||
'from_cache' => $isFromCache
|
||||
]);
|
||||
} else {
|
||||
// ثبت لاگ خطا
|
||||
$errorMessage = $result['message'] ?? 'خطا در استعلام کد پستی';
|
||||
$log->insert(
|
||||
'استعلام',
|
||||
"خطا در استعلام کد پستی {$postalCode}: {$errorMessage}",
|
||||
$acc['user'],
|
||||
$acc['bid']
|
||||
);
|
||||
|
||||
return $this->json([
|
||||
'success' => false,
|
||||
'message' => $errorMessage,
|
||||
'error_code' => $result['error_code'] ?? null
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
#[Route('/api/plugins/inquiry/card-to-sheba', name: 'plugin_inquiry_card_to_sheba', methods: ['POST'])]
|
||||
public function plugin_inquiry_card_to_sheba(Inquiry $inquiry, Access $access, Request $request, registryMGR $registryMGR, Log $log): JsonResponse
|
||||
{
|
||||
$acc = $access->hasRole('inquiry');
|
||||
if (!$acc) {
|
||||
return $this->json([
|
||||
'success' => false,
|
||||
'message' => 'شما دسترسی به این سرویس را ندارید'
|
||||
]);
|
||||
}
|
||||
|
||||
// بررسی فعال بودن سرویس
|
||||
if (!$registryMGR->get('system', key: 'enableCardToSheba')) {
|
||||
return $this->json([
|
||||
'success' => false,
|
||||
'message' => 'این سرویس در حال حاضر غیرفعال است'
|
||||
]);
|
||||
}
|
||||
|
||||
// دریافت شماره کارت از درخواست
|
||||
$data = json_decode($request->getContent(), true);
|
||||
$cardNumber = $data['card_number'] ?? null;
|
||||
if (!$cardNumber) {
|
||||
return $this->json([
|
||||
'success' => false,
|
||||
'message' => 'شماره کارت ارسال نشده است'
|
||||
]);
|
||||
}
|
||||
|
||||
// فراخوانی سرویس استعلام کارت به شبا
|
||||
$result = $inquiry->cardToSheba($cardNumber);
|
||||
|
||||
// بررسی نتیجه و بازگرداندن پاسخ مناسب
|
||||
if (isset($result['result']) && $result['result'] == 1) {
|
||||
$isFromCache = isset($result['response_body']['message']) &&
|
||||
strpos($result['response_body']['message'], 'از حافظه موقت') !== false;
|
||||
|
||||
// ثبت لاگ بر اساس منبع داده
|
||||
$logMessage = $isFromCache
|
||||
? "استعلام کارت به شبا {$cardNumber} از حافظه موقت (بدون کسر کارمزد)"
|
||||
: "استعلام کارت به شبا {$cardNumber} از API (کسر کارمزد: " . $registryMGR->get('system', key: 'cardToShebaFee') . " ریال)";
|
||||
|
||||
$log->insert(
|
||||
'استعلام',
|
||||
$logMessage,
|
||||
$acc['user'],
|
||||
$acc['bid']
|
||||
);
|
||||
|
||||
// فقط در صورت عدم وجود در کش، کارمزد کسر شود
|
||||
if (!$isFromCache) {
|
||||
if ($acc['bid']->getSmsCharge() < $registryMGR->get('system', key: 'cardToShebaFee')) {
|
||||
// ثبت لاگ عدم موجودی کافی
|
||||
$log->insert(
|
||||
'استعلام',
|
||||
"عدم موجودی کافی برای استعلام کارت به شبا {$cardNumber}",
|
||||
$acc['user'],
|
||||
$acc['bid']
|
||||
);
|
||||
|
||||
return $this->json([
|
||||
'success' => false,
|
||||
'message' => 'موجودی شما برای این سرویس کافی نیست'
|
||||
]);
|
||||
}
|
||||
|
||||
$business = $acc['bid'];
|
||||
$business->setSmsCharge($business->getSmsCharge() - $registryMGR->get('system', key: 'cardToShebaFee'));
|
||||
$this->entityManager->persist($business);
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
|
||||
return $this->json([
|
||||
'success' => true,
|
||||
'data' => $result['response_body']['data'] ?? null,
|
||||
'message' => $result['response_body']['message'] ?? 'موفق',
|
||||
'from_cache' => $isFromCache
|
||||
]);
|
||||
} else {
|
||||
// ثبت لاگ خطا
|
||||
$errorMessage = $result['message'] ?? 'خطا در استعلام کارت به شبا';
|
||||
$log->insert(
|
||||
'استعلام',
|
||||
"خطا در استعلام کارت به شبا {$cardNumber}: {$errorMessage}",
|
||||
$acc['user'],
|
||||
$acc['bid']
|
||||
);
|
||||
|
||||
return $this->json([
|
||||
'success' => false,
|
||||
'message' => $errorMessage,
|
||||
'error_code' => $result['error_code'] ?? null
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
#[Route('/api/plugins/inquiry/account-to-sheba', name: 'plugin_inquiry_account_to_sheba', methods: ['POST'])]
|
||||
public function plugin_inquiry_account_to_sheba(Inquiry $inquiry, Access $access, Request $request, registryMGR $registryMGR, Log $log): JsonResponse
|
||||
{
|
||||
$acc = $access->hasRole('inquiry');
|
||||
if (!$acc) {
|
||||
return $this->json([
|
||||
'success' => false,
|
||||
'message' => 'شما دسترسی به این سرویس را ندارید'
|
||||
]);
|
||||
}
|
||||
|
||||
// بررسی فعال بودن سرویس
|
||||
if (!$registryMGR->get('system', key: 'enableAccountToSheba')) {
|
||||
return $this->json([
|
||||
'success' => false,
|
||||
'message' => 'این سرویس در حال حاضر غیرفعال است'
|
||||
]);
|
||||
}
|
||||
|
||||
// دریافت دادهها از درخواست
|
||||
$data = json_decode($request->getContent(), true);
|
||||
$bankCode = $data['bank_code'] ?? null;
|
||||
$accountNumber = $data['account_number'] ?? null;
|
||||
|
||||
if (!$bankCode || !$accountNumber) {
|
||||
return $this->json([
|
||||
'success' => false,
|
||||
'message' => 'کد بانک و شماره حساب الزامی است'
|
||||
]);
|
||||
}
|
||||
|
||||
// فراخوانی سرویس استعلام حساب به شبا
|
||||
$result = $inquiry->accountToSheba($bankCode, $accountNumber);
|
||||
|
||||
// بررسی نتیجه و بازگرداندن پاسخ مناسب
|
||||
if (isset($result['result']) && $result['result'] == 1) {
|
||||
$isFromCache = isset($result['response_body']['message']) &&
|
||||
strpos($result['response_body']['message'], 'از حافظه موقت') !== false;
|
||||
|
||||
// ثبت لاگ بر اساس منبع داده
|
||||
$logMessage = $isFromCache
|
||||
? "استعلام حساب به شبا {$bankCode}/{$accountNumber} از حافظه موقت (بدون کسر کارمزد)"
|
||||
: "استعلام حساب به شبا {$bankCode}/{$accountNumber} از API (کسر کارمزد: " . $registryMGR->get('system', key: 'accountToShebaFee') . " ریال)";
|
||||
|
||||
$log->insert(
|
||||
'استعلام',
|
||||
$logMessage,
|
||||
$acc['user'],
|
||||
$acc['bid']
|
||||
);
|
||||
|
||||
// فقط در صورت عدم وجود در کش، کارمزد کسر شود
|
||||
if (!$isFromCache) {
|
||||
if ($acc['bid']->getSmsCharge() < $registryMGR->get('system', key: 'accountToShebaFee')) {
|
||||
// ثبت لاگ عدم موجودی کافی
|
||||
$log->insert(
|
||||
'استعلام',
|
||||
"عدم موجودی کافی برای استعلام حساب به شبا {$bankCode}/{$accountNumber}",
|
||||
$acc['user'],
|
||||
$acc['bid']
|
||||
);
|
||||
|
||||
return $this->json([
|
||||
'success' => false,
|
||||
'message' => 'موجودی شما برای این سرویس کافی نیست'
|
||||
]);
|
||||
}
|
||||
|
||||
$business = $acc['bid'];
|
||||
$business->setSmsCharge($business->getSmsCharge() - $registryMGR->get('system', key: 'accountToShebaFee'));
|
||||
$this->entityManager->persist($business);
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
|
||||
return $this->json([
|
||||
'success' => true,
|
||||
'data' => $result['response_body']['data'] ?? null,
|
||||
'message' => $result['response_body']['message'] ?? 'موفق',
|
||||
'from_cache' => $isFromCache
|
||||
]);
|
||||
} else {
|
||||
// ثبت لاگ خطا
|
||||
$errorMessage = $result['message'] ?? 'خطا در استعلام حساب به شبا';
|
||||
$log->insert(
|
||||
'استعلام',
|
||||
"خطا در استعلام حساب به شبا {$bankCode}/{$accountNumber}: {$errorMessage}",
|
||||
$acc['user'],
|
||||
$acc['bid']
|
||||
);
|
||||
|
||||
return $this->json([
|
||||
'success' => false,
|
||||
'message' => $errorMessage,
|
||||
'error_code' => $result['error_code'] ?? null
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,8 +23,9 @@ final class UpdateCoreController extends AbstractController
|
|||
public function api_admin_updatecore_run(): JsonResponse
|
||||
{
|
||||
$projectDir = $this->getParameter('kernel.project_dir');
|
||||
$gitRoot = dirname($projectDir); // رفتن به ریشه پروژه
|
||||
$uuid = uniqid();
|
||||
$stateFile = $projectDir . '/../hesabixBackup/update_state_' . $uuid . '.json';
|
||||
$stateFile = $gitRoot . '/hesabixBackup/update_state_' . $uuid . '.json';
|
||||
|
||||
if (!file_exists(dirname($stateFile))) {
|
||||
mkdir(dirname($stateFile), 0755, true);
|
||||
|
@ -41,7 +42,7 @@ final class UpdateCoreController extends AbstractController
|
|||
'COMPOSER_HOME' => '/var/www/.composer',
|
||||
]);
|
||||
|
||||
$process = new Process(['php', 'bin/console', 'hesabix:update', $stateFile], $projectDir, $env);
|
||||
$process = new Process(['php', 'hesabixCore/bin/console', 'hesabix:update', $stateFile], $gitRoot, $env);
|
||||
$process->setTimeout(7200); // افزایش تایماوت به 2 ساعت
|
||||
$process->start(function ($type, $buffer) use ($stateFile) {
|
||||
$state = json_decode(file_get_contents($stateFile), true) ?? ['uuid' => uniqid(), 'log' => ''];
|
||||
|
@ -70,7 +71,9 @@ final class UpdateCoreController extends AbstractController
|
|||
], 400);
|
||||
}
|
||||
|
||||
$stateFile = $this->getParameter('kernel.project_dir') . '/../hesabixBackup/update_state_' . $uuid . '.json';
|
||||
$projectDir = $this->getParameter('kernel.project_dir');
|
||||
$gitRoot = dirname($projectDir);
|
||||
$stateFile = $gitRoot . '/hesabixBackup/update_state_' . $uuid . '.json';
|
||||
|
||||
if (!file_exists($stateFile)) {
|
||||
return new JsonResponse([
|
||||
|
@ -97,7 +100,7 @@ final class UpdateCoreController extends AbstractController
|
|||
}
|
||||
|
||||
if (!$isRunning) {
|
||||
$backupDir = $this->getParameter('kernel.project_dir') . '/../hesabixBackup';
|
||||
$backupDir = $gitRoot . '/hesabixBackup';
|
||||
$stateFiles = glob($backupDir . '/update_state_*.json');
|
||||
foreach ($stateFiles as $file) {
|
||||
if (is_file($file)) {
|
||||
|
@ -128,7 +131,9 @@ final class UpdateCoreController extends AbstractController
|
|||
return new JsonResponse(['status' => 'error', 'message' => 'UUID is required'], 400);
|
||||
}
|
||||
|
||||
$stateFile = $this->getParameter('kernel.project_dir') . '/../hesabixBackup/update_state_' . $uuid . '.json';
|
||||
$projectDir = $this->getParameter('kernel.project_dir');
|
||||
$gitRoot = dirname($projectDir);
|
||||
$stateFile = $gitRoot . '/hesabixBackup/update_state_' . $uuid . '.json';
|
||||
|
||||
return new StreamedResponse(function () use ($stateFile) {
|
||||
header('Content-Type: text/event-stream');
|
||||
|
@ -167,13 +172,14 @@ final class UpdateCoreController extends AbstractController
|
|||
public function api_admin_updatecore_commits(): JsonResponse
|
||||
{
|
||||
$projectDir = $this->getParameter('kernel.project_dir');
|
||||
$gitRoot = dirname($projectDir); // رفتن به ریشه پروژه
|
||||
|
||||
$currentProcess = new Process(['git', 'rev-parse', 'HEAD'], $projectDir);
|
||||
$currentProcess = new Process(['git', 'rev-parse', 'HEAD'], $gitRoot);
|
||||
$currentProcess->setTimeout(7200); // افزایش تایماوت
|
||||
$currentProcess->run();
|
||||
$currentCommit = $currentProcess->isSuccessful() ? trim($currentProcess->getOutput()) : 'unknown';
|
||||
|
||||
$targetProcess = new Process(['git', 'ls-remote', 'origin', 'HEAD'], $projectDir);
|
||||
$targetProcess = new Process(['git', 'ls-remote', 'origin', 'HEAD'], $gitRoot);
|
||||
$targetProcess->setTimeout(7200); // افزایش تایماوت
|
||||
$targetProcess->run();
|
||||
$targetOutput = $targetProcess->isSuccessful() ? explode("\t", trim($targetProcess->getOutput()))[0] : 'unknown';
|
||||
|
@ -428,4 +434,170 @@ final class UpdateCoreController extends AbstractController
|
|||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
#[Route('/api/admin/updatecore/current-source', name: 'api_admin_updatecore_current_source', methods: ['GET'])]
|
||||
public function api_admin_updatecore_current_source(): JsonResponse
|
||||
{
|
||||
$projectDir = $this->getParameter('kernel.project_dir');
|
||||
$gitRoot = dirname($projectDir); // رفتن به ریشه پروژه
|
||||
$output = '';
|
||||
|
||||
try {
|
||||
// بررسی اینکه آیا پروژه یک مخزن Git است
|
||||
if (!is_dir($gitRoot . '/.git')) {
|
||||
return new JsonResponse([
|
||||
'status' => 'error',
|
||||
'message' => 'این پروژه یک مخزن Git نیست',
|
||||
'sourceUrl' => '',
|
||||
], 400);
|
||||
}
|
||||
|
||||
// دریافت آدرس مخزن origin فعلی
|
||||
$process = new Process(['git', 'remote', 'get-url', 'origin'], $gitRoot);
|
||||
$process->setTimeout(7200); // افزایش تایماوت
|
||||
$process->run();
|
||||
|
||||
if (!$process->isSuccessful()) {
|
||||
return new JsonResponse([
|
||||
'status' => 'error',
|
||||
'message' => 'خطا در دریافت آدرس مخزن: ' . $process->getErrorOutput(),
|
||||
'sourceUrl' => '',
|
||||
], 500);
|
||||
}
|
||||
|
||||
$sourceUrl = trim($process->getOutput());
|
||||
$output .= "آدرس مخزن فعلی: $sourceUrl\n";
|
||||
|
||||
return new JsonResponse([
|
||||
'status' => 'success',
|
||||
'sourceUrl' => $sourceUrl,
|
||||
'output' => $output,
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return new JsonResponse([
|
||||
'status' => 'error',
|
||||
'message' => 'خطا در بررسی مخزن: ' . $e->getMessage(),
|
||||
'sourceUrl' => '',
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
#[Route('/api/admin/updatecore/change-source', name: 'api_admin_updatecore_change_source', methods: ['POST'])]
|
||||
public function api_admin_updatecore_change_source(Request $request): JsonResponse
|
||||
{
|
||||
$sourceUrl = $request->getPayload()->get('sourceUrl');
|
||||
$output = '';
|
||||
|
||||
if (!$sourceUrl || !filter_var($sourceUrl, FILTER_VALIDATE_URL) && !preg_match('/^git@[^:]+:[^\/]+\/[^\/]+\.git$/', $sourceUrl)) {
|
||||
return new JsonResponse([
|
||||
'status' => 'error',
|
||||
'message' => 'آدرس مخزن نامعتبر است. لطفاً یک آدرس HTTP یا SSH معتبر وارد کنید.',
|
||||
'output' => $output,
|
||||
], 400);
|
||||
}
|
||||
|
||||
$projectDir = $this->getParameter('kernel.project_dir');
|
||||
$gitRoot = dirname($projectDir); // رفتن به ریشه پروژه
|
||||
|
||||
try {
|
||||
// بررسی اینکه آیا پروژه یک مخزن Git است
|
||||
if (!is_dir($gitRoot . '/.git')) {
|
||||
return new JsonResponse([
|
||||
'status' => 'error',
|
||||
'message' => 'این پروژه یک مخزن Git نیست',
|
||||
'output' => $output,
|
||||
], 400);
|
||||
}
|
||||
|
||||
$output .= "شروع تغییر آدرس مخزن...\n";
|
||||
|
||||
// دریافت آدرس مخزن فعلی
|
||||
$currentProcess = new Process(['git', 'remote', 'get-url', 'origin'], $gitRoot);
|
||||
$currentProcess->setTimeout(7200);
|
||||
$currentProcess->run();
|
||||
$currentUrl = $currentProcess->isSuccessful() ? trim($currentProcess->getOutput()) : '';
|
||||
|
||||
if ($currentUrl) {
|
||||
$output .= "آدرس مخزن فعلی: $currentUrl\n";
|
||||
}
|
||||
|
||||
// تغییر آدرس مخزن origin
|
||||
$changeProcess = new Process(['git', 'remote', 'set-url', 'origin', $sourceUrl], $gitRoot);
|
||||
$changeProcess->setTimeout(7200);
|
||||
$changeProcess->run();
|
||||
|
||||
if (!$changeProcess->isSuccessful()) {
|
||||
return new JsonResponse([
|
||||
'status' => 'error',
|
||||
'message' => 'خطا در تغییر آدرس مخزن: ' . $changeProcess->getErrorOutput(),
|
||||
'output' => $output,
|
||||
], 500);
|
||||
}
|
||||
|
||||
$output .= "آدرس مخزن به $sourceUrl تغییر یافت\n";
|
||||
|
||||
// بررسی اتصال به مخزن جدید
|
||||
$testProcess = new Process(['git', 'remote', 'show', 'origin'], $gitRoot);
|
||||
$testProcess->setTimeout(7200);
|
||||
$testProcess->run();
|
||||
|
||||
if (!$testProcess->isSuccessful()) {
|
||||
return new JsonResponse([
|
||||
'status' => 'error',
|
||||
'message' => 'خطا در اتصال به مخزن جدید: ' . $testProcess->getErrorOutput(),
|
||||
'output' => $output,
|
||||
], 500);
|
||||
}
|
||||
|
||||
$output .= "اتصال به مخزن جدید با موفقیت برقرار شد\n";
|
||||
|
||||
// دریافت اطلاعات مخزن جدید
|
||||
$fetchProcess = new Process(['git', 'fetch', 'origin'], $gitRoot);
|
||||
$fetchProcess->setTimeout(7200);
|
||||
$fetchProcess->run();
|
||||
|
||||
if (!$fetchProcess->isSuccessful()) {
|
||||
$output .= "هشدار: خطا در دریافت اطلاعات از مخزن جدید: " . $fetchProcess->getErrorOutput() . "\n";
|
||||
} else {
|
||||
$output .= "اطلاعات مخزن جدید با موفقیت دریافت شد\n";
|
||||
}
|
||||
|
||||
// بررسی branch های موجود
|
||||
$branchProcess = new Process(['git', 'branch', '-r'], $gitRoot);
|
||||
$branchProcess->setTimeout(7200);
|
||||
$branchProcess->run();
|
||||
|
||||
if ($branchProcess->isSuccessful()) {
|
||||
$branches = trim($branchProcess->getOutput());
|
||||
if ($branches) {
|
||||
$output .= "شاخههای موجود در مخزن جدید:\n$branches\n";
|
||||
} else {
|
||||
$output .= "هیچ شاخهای در مخزن جدید یافت نشد\n";
|
||||
}
|
||||
}
|
||||
|
||||
// پاک کردن کش Git
|
||||
$cleanProcess = new Process(['git', 'gc', '--prune=now'], $gitRoot);
|
||||
$cleanProcess->setTimeout(7200);
|
||||
$cleanProcess->run();
|
||||
|
||||
if ($cleanProcess->isSuccessful()) {
|
||||
$output .= "کش Git پاک شد\n";
|
||||
}
|
||||
|
||||
return new JsonResponse([
|
||||
'status' => 'success',
|
||||
'message' => 'آدرس مخزن با موفقیت تغییر یافت و اتصال برقرار شد',
|
||||
'output' => $output,
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return new JsonResponse([
|
||||
'status' => 'error',
|
||||
'message' => 'خطا در تغییر آدرس مخزن: ' . $e->getMessage(),
|
||||
'output' => $output,
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
}
|
63
hesabixCore/src/Entity/AccountToShebaInquiry.php
Normal file
63
hesabixCore/src/Entity/AccountToShebaInquiry.php
Normal file
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\AccountToShebaInquiryRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: AccountToShebaInquiryRepository::class)]
|
||||
#[ORM\Table(name: 'account_to_sheba_inquiry')]
|
||||
class AccountToShebaInquiry
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\Column(length: 50, unique: true)]
|
||||
private ?string $cacheKey = null;
|
||||
|
||||
#[ORM\Column(type: 'json')]
|
||||
private array $shebaData = [];
|
||||
|
||||
#[ORM\Column]
|
||||
private ?\DateTimeImmutable $updatedAt = null;
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getCacheKey(): ?string
|
||||
{
|
||||
return $this->cacheKey;
|
||||
}
|
||||
|
||||
public function setCacheKey(string $cacheKey): static
|
||||
{
|
||||
$this->cacheKey = $cacheKey;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getShebaData(): array
|
||||
{
|
||||
return $this->shebaData;
|
||||
}
|
||||
|
||||
public function setShebaData(array $shebaData): static
|
||||
{
|
||||
$this->shebaData = $shebaData;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUpdatedAt(): ?\DateTimeImmutable
|
||||
{
|
||||
return $this->updatedAt;
|
||||
}
|
||||
|
||||
public function setUpdatedAt(\DateTimeImmutable $updatedAt): static
|
||||
{
|
||||
$this->updatedAt = $updatedAt;
|
||||
return $this;
|
||||
}
|
||||
}
|
63
hesabixCore/src/Entity/CardToShebaInquiry.php
Normal file
63
hesabixCore/src/Entity/CardToShebaInquiry.php
Normal file
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\CardToShebaInquiryRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: CardToShebaInquiryRepository::class)]
|
||||
#[ORM\Table(name: 'card_to_sheba_inquiry')]
|
||||
class CardToShebaInquiry
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\Column(length: 16, unique: true)]
|
||||
private ?string $cardNumber = null;
|
||||
|
||||
#[ORM\Column(type: 'json')]
|
||||
private array $shebaData = [];
|
||||
|
||||
#[ORM\Column]
|
||||
private ?\DateTimeImmutable $updatedAt = null;
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getCardNumber(): ?string
|
||||
{
|
||||
return $this->cardNumber;
|
||||
}
|
||||
|
||||
public function setCardNumber(string $cardNumber): static
|
||||
{
|
||||
$this->cardNumber = $cardNumber;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getShebaData(): array
|
||||
{
|
||||
return $this->shebaData;
|
||||
}
|
||||
|
||||
public function setShebaData(array $shebaData): static
|
||||
{
|
||||
$this->shebaData = $shebaData;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUpdatedAt(): ?\DateTimeImmutable
|
||||
{
|
||||
return $this->updatedAt;
|
||||
}
|
||||
|
||||
public function setUpdatedAt(\DateTimeImmutable $updatedAt): static
|
||||
{
|
||||
$this->updatedAt = $updatedAt;
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -132,6 +132,9 @@ class Permission
|
|||
#[ORM\Column(nullable: true)]
|
||||
private ?bool $plugTaxSettings = null;
|
||||
|
||||
#[ORM\Column(nullable: true)]
|
||||
private ?bool $inquiry = null;
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
|
@ -605,4 +608,15 @@ class Permission
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function isInquiry(): ?bool
|
||||
{
|
||||
return $this->inquiry;
|
||||
}
|
||||
|
||||
public function setInquiry(?bool $inquiry): static
|
||||
{
|
||||
$this->inquiry = $inquiry;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,239 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\PluginTaxInvoiceRepository;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: PluginTaxInvoiceRepository::class)]
|
||||
class PluginTaxInvoice
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\ManyToOne]
|
||||
#[ORM\JoinColumn(nullable: false)]
|
||||
private ?Business $business = null;
|
||||
|
||||
#[ORM\ManyToOne]
|
||||
#[ORM\JoinColumn(nullable: false)]
|
||||
private ?User $user = null;
|
||||
|
||||
#[ORM\ManyToOne]
|
||||
#[ORM\JoinColumn(nullable: false)]
|
||||
private ?HesabdariDoc $invoice = null;
|
||||
|
||||
#[ORM\Column(length:255)]
|
||||
private ?string $invoiceCode = null;
|
||||
|
||||
#[ORM\Column(length: 255, nullable: true)]
|
||||
private ?string $taxSystemInvoiceNumber = null;
|
||||
|
||||
#[ORM\Column(length: 255, nullable: true)]
|
||||
private ?string $taxSystemReferenceNumber = null;
|
||||
|
||||
#[ORM\Column(length:255)]
|
||||
private ?string $status = 'pending'; // pending, sent, failed, confirmed
|
||||
|
||||
#[ORM\Column(type: Types::TEXT, nullable: true)]
|
||||
private ?string $responseData = null;
|
||||
|
||||
#[ORM\Column(type: Types::TEXT, nullable: true)]
|
||||
private ?string $errorMessage = null;
|
||||
|
||||
#[ORM\Column]
|
||||
private ?\DateTimeImmutable $createdAt = null;
|
||||
|
||||
#[ORM\Column(nullable: true)]
|
||||
private ?\DateTimeImmutable $sentAt = null;
|
||||
|
||||
#[ORM\Column(nullable: true)]
|
||||
private ?\DateTimeImmutable $confirmedAt = null;
|
||||
|
||||
#[ORM\Column(type: Types::DECIMAL, precision: 30, scale: 0)]
|
||||
private ?string $amount = '0';
|
||||
|
||||
#[ORM\Column(length: 255, nullable: true)]
|
||||
private ?string $customerName = null;
|
||||
|
||||
#[ORM\Column(length: 255, nullable: true)]
|
||||
private ?string $customerId = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->createdAt = new \DateTimeImmutable();
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getBusiness(): ?Business
|
||||
{
|
||||
return $this->business;
|
||||
}
|
||||
|
||||
public function setBusiness(?Business $business): static
|
||||
{
|
||||
$this->business = $business;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUser(): ?User
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
public function setUser(?User $user): static
|
||||
{
|
||||
$this->user = $user;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getInvoice(): ?HesabdariDoc
|
||||
{
|
||||
return $this->invoice;
|
||||
}
|
||||
|
||||
public function setInvoice(?HesabdariDoc $invoice): static
|
||||
{
|
||||
$this->invoice = $invoice;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getInvoiceCode(): ?string
|
||||
{
|
||||
return $this->invoiceCode;
|
||||
}
|
||||
|
||||
public function setInvoiceCode(string $invoiceCode): static
|
||||
{
|
||||
$this->invoiceCode = $invoiceCode;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTaxSystemInvoiceNumber(): ?string
|
||||
{
|
||||
return $this->taxSystemInvoiceNumber;
|
||||
}
|
||||
|
||||
public function setTaxSystemInvoiceNumber(?string $taxSystemInvoiceNumber): static
|
||||
{
|
||||
$this->taxSystemInvoiceNumber = $taxSystemInvoiceNumber;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTaxSystemReferenceNumber(): ?string
|
||||
{
|
||||
return $this->taxSystemReferenceNumber;
|
||||
}
|
||||
|
||||
public function setTaxSystemReferenceNumber(?string $taxSystemReferenceNumber): static
|
||||
{
|
||||
$this->taxSystemReferenceNumber = $taxSystemReferenceNumber;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getStatus(): ?string
|
||||
{
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
public function setStatus(string $status): static
|
||||
{
|
||||
$this->status = $status;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getResponseData(): ?string
|
||||
{
|
||||
return $this->responseData;
|
||||
}
|
||||
|
||||
public function setResponseData(?string $responseData): static
|
||||
{
|
||||
$this->responseData = $responseData;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getErrorMessage(): ?string
|
||||
{
|
||||
return $this->errorMessage;
|
||||
}
|
||||
|
||||
public function setErrorMessage(?string $errorMessage): static
|
||||
{
|
||||
$this->errorMessage = $errorMessage;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): ?\DateTimeImmutable
|
||||
{
|
||||
return $this->createdAt;
|
||||
}
|
||||
|
||||
public function setCreatedAt(\DateTimeImmutable $createdAt): static
|
||||
{
|
||||
$this->createdAt = $createdAt;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSentAt(): ?\DateTimeImmutable
|
||||
{
|
||||
return $this->sentAt;
|
||||
}
|
||||
|
||||
public function setSentAt(?\DateTimeImmutable $sentAt): static
|
||||
{
|
||||
$this->sentAt = $sentAt;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getConfirmedAt(): ?\DateTimeImmutable
|
||||
{
|
||||
return $this->confirmedAt;
|
||||
}
|
||||
|
||||
public function setConfirmedAt(?\DateTimeImmutable $confirmedAt): static
|
||||
{
|
||||
$this->confirmedAt = $confirmedAt;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getAmount(): ?string
|
||||
{
|
||||
return $this->amount;
|
||||
}
|
||||
|
||||
public function setAmount(string $amount): static
|
||||
{
|
||||
$this->amount = $amount;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCustomerName(): ?string
|
||||
{
|
||||
return $this->customerName;
|
||||
}
|
||||
|
||||
public function setCustomerName(?string $customerName): static
|
||||
{
|
||||
$this->customerName = $customerName;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCustomerId(): ?string
|
||||
{
|
||||
return $this->customerId;
|
||||
}
|
||||
|
||||
public function setCustomerId(?string $customerId): static
|
||||
{
|
||||
$this->customerId = $customerId;
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@ namespace App\Entity;
|
|||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity]
|
||||
#[ORM\Table(name: "plugin_tax_settings")]
|
||||
#[ORM\Table(name: "plugin_taxsettings_keys")]
|
||||
class PluginTaxsettingsKey
|
||||
{
|
||||
#[ORM\Id]
|
||||
|
|
83
hesabixCore/src/Entity/PostalCodeInquiry.php
Normal file
83
hesabixCore/src/Entity/PostalCodeInquiry.php
Normal file
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\PostalCodeInquiryRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: PostalCodeInquiryRepository::class)]
|
||||
#[ORM\Table(name: 'postal_code_inquiry')]
|
||||
class PostalCodeInquiry
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\Column(length: 10, unique: true)]
|
||||
private ?string $postalCode = null;
|
||||
|
||||
#[ORM\Column(type: 'json')]
|
||||
private array $addressData = [];
|
||||
|
||||
#[ORM\Column]
|
||||
private ?\DateTimeImmutable $createdAt = null;
|
||||
|
||||
#[ORM\Column]
|
||||
private ?\DateTimeImmutable $updatedAt = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->createdAt = new \DateTimeImmutable();
|
||||
$this->updatedAt = new \DateTimeImmutable();
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getPostalCode(): ?string
|
||||
{
|
||||
return $this->postalCode;
|
||||
}
|
||||
|
||||
public function setPostalCode(string $postalCode): static
|
||||
{
|
||||
$this->postalCode = $postalCode;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getAddressData(): array
|
||||
{
|
||||
return $this->addressData;
|
||||
}
|
||||
|
||||
public function setAddressData(array $addressData): static
|
||||
{
|
||||
$this->addressData = $addressData;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): ?\DateTimeImmutable
|
||||
{
|
||||
return $this->createdAt;
|
||||
}
|
||||
|
||||
public function setCreatedAt(\DateTimeImmutable $createdAt): static
|
||||
{
|
||||
$this->createdAt = $createdAt;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUpdatedAt(): ?\DateTimeImmutable
|
||||
{
|
||||
return $this->updatedAt;
|
||||
}
|
||||
|
||||
public function setUpdatedAt(\DateTimeImmutable $updatedAt): static
|
||||
{
|
||||
$this->updatedAt = $updatedAt;
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\AccountToShebaInquiry;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<AccountToShebaInquiry>
|
||||
*
|
||||
* @method AccountToShebaInquiry|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method AccountToShebaInquiry|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method AccountToShebaInquiry[] findAll()
|
||||
* @method AccountToShebaInquiry[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class AccountToShebaInquiryRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, AccountToShebaInquiry::class);
|
||||
}
|
||||
|
||||
public function findByCacheKey(string $cacheKey): ?AccountToShebaInquiry
|
||||
{
|
||||
return $this->findOneBy(['cacheKey' => $cacheKey]);
|
||||
}
|
||||
|
||||
public function save(AccountToShebaInquiry $entity, bool $flush = false): void
|
||||
{
|
||||
$this->getEntityManager()->persist($entity);
|
||||
|
||||
if ($flush) {
|
||||
$this->getEntityManager()->flush();
|
||||
}
|
||||
}
|
||||
|
||||
public function remove(AccountToShebaInquiry $entity, bool $flush = false): void
|
||||
{
|
||||
$this->getEntityManager()->remove($entity);
|
||||
|
||||
if ($flush) {
|
||||
$this->getEntityManager()->flush();
|
||||
}
|
||||
}
|
||||
}
|
46
hesabixCore/src/Repository/CardToShebaInquiryRepository.php
Normal file
46
hesabixCore/src/Repository/CardToShebaInquiryRepository.php
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\CardToShebaInquiry;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<CardToShebaInquiry>
|
||||
*
|
||||
* @method CardToShebaInquiry|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method CardToShebaInquiry|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method CardToShebaInquiry[] findAll()
|
||||
* @method CardToShebaInquiry[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class CardToShebaInquiryRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, CardToShebaInquiry::class);
|
||||
}
|
||||
|
||||
public function findByCardNumber(string $cardNumber): ?CardToShebaInquiry
|
||||
{
|
||||
return $this->findOneBy(['cardNumber' => $cardNumber]);
|
||||
}
|
||||
|
||||
public function save(CardToShebaInquiry $entity, bool $flush = false): void
|
||||
{
|
||||
$this->getEntityManager()->persist($entity);
|
||||
|
||||
if ($flush) {
|
||||
$this->getEntityManager()->flush();
|
||||
}
|
||||
}
|
||||
|
||||
public function remove(CardToShebaInquiry $entity, bool $flush = false): void
|
||||
{
|
||||
$this->getEntityManager()->remove($entity);
|
||||
|
||||
if ($flush) {
|
||||
$this->getEntityManager()->flush();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,106 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\PluginTaxInvoice;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<PluginTaxInvoice>
|
||||
*
|
||||
* @method PluginTaxInvoice|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method PluginTaxInvoice|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method PluginTaxInvoice findAll()
|
||||
* @method PluginTaxInvoice findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class PluginTaxInvoiceRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, PluginTaxInvoice::class);
|
||||
}
|
||||
|
||||
public function save(PluginTaxInvoice $entity, bool $flush = false): void
|
||||
{
|
||||
$this->getEntityManager()->persist($entity);
|
||||
|
||||
if ($flush) {
|
||||
$this->getEntityManager()->flush();
|
||||
}
|
||||
}
|
||||
|
||||
public function remove(PluginTaxInvoice $entity, bool $flush = false): void
|
||||
{
|
||||
$this->getEntityManager()->remove($entity);
|
||||
|
||||
if ($flush) {
|
||||
$this->getEntityManager()->flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* پیدا کردن فاکتورهای ارسال شده برای یک کسبوکار
|
||||
*/
|
||||
public function findByBusiness($businessId, $limit = null, $offset = null)
|
||||
{
|
||||
$qb = $this->createQueryBuilder('pti')
|
||||
->leftJoin('pti.invoice', 'invoice')
|
||||
->leftJoin('pti.user', 'user')
|
||||
->where('pti.business = :businessId')
|
||||
->setParameter('businessId', $businessId)
|
||||
->orderBy('pti.createdAt', 'DESC');
|
||||
if ($limit) {
|
||||
$qb->setMaxResults($limit);
|
||||
}
|
||||
if ($offset) {
|
||||
$qb->setFirstResult($offset);
|
||||
}
|
||||
|
||||
return $qb->getQuery()->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* پیدا کردن فاکتور بر اساس کد فاکتور و کسبوکار
|
||||
*/
|
||||
public function findByInvoiceCodeAndBusiness($invoiceCode, $businessId)
|
||||
{
|
||||
return $this->createQueryBuilder('pti')
|
||||
->where('pti.invoiceCode = :invoiceCode')
|
||||
->andWhere('pti.business = :businessId')
|
||||
->setParameter('invoiceCode', $invoiceCode)
|
||||
->setParameter('businessId', $businessId)
|
||||
->getQuery()
|
||||
->getOneOrNullResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* آمار فاکتورهای ارسال شده بر اساس وضعیت
|
||||
*/
|
||||
public function getStatusStats($businessId)
|
||||
{
|
||||
$qb = $this->createQueryBuilder('pti')
|
||||
->select('pti.status, COUNT(pti.id) as count')
|
||||
->where('pti.business = :businessId')
|
||||
->setParameter('businessId', $businessId)
|
||||
->groupBy('pti.status');
|
||||
|
||||
return $qb->getQuery()->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* فاکتورهای با وضعیت مشخص
|
||||
*/
|
||||
public function findByStatus($businessId, $status)
|
||||
{
|
||||
return $this->createQueryBuilder('pti')
|
||||
->leftJoin('pti.invoice', 'invoice')
|
||||
->where('pti.business = :businessId')
|
||||
->andWhere('pti.status = :status')
|
||||
->setParameter('businessId', $businessId)
|
||||
->setParameter('status', $status)
|
||||
->orderBy('pti.createdAt', 'DESC')
|
||||
->getQuery()
|
||||
->getResult();
|
||||
}
|
||||
}
|
46
hesabixCore/src/Repository/PostalCodeInquiryRepository.php
Normal file
46
hesabixCore/src/Repository/PostalCodeInquiryRepository.php
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\PostalCodeInquiry;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<PostalCodeInquiry>
|
||||
*
|
||||
* @method PostalCodeInquiry|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method PostalCodeInquiry|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method PostalCodeInquiry[] findAll()
|
||||
* @method PostalCodeInquiry[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class PostalCodeInquiryRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, PostalCodeInquiry::class);
|
||||
}
|
||||
|
||||
public function findByPostalCode(string $postalCode): ?PostalCodeInquiry
|
||||
{
|
||||
return $this->findOneBy(['postalCode' => $postalCode]);
|
||||
}
|
||||
|
||||
public function save(PostalCodeInquiry $entity, bool $flush = false): void
|
||||
{
|
||||
$this->getEntityManager()->persist($entity);
|
||||
|
||||
if ($flush) {
|
||||
$this->getEntityManager()->flush();
|
||||
}
|
||||
}
|
||||
|
||||
public function remove(PostalCodeInquiry $entity, bool $flush = false): void
|
||||
{
|
||||
$this->getEntityManager()->remove($entity);
|
||||
|
||||
if ($flush) {
|
||||
$this->getEntityManager()->flush();
|
||||
}
|
||||
}
|
||||
}
|
448
hesabixCore/src/Service/Inquiry.php
Normal file
448
hesabixCore/src/Service/Inquiry.php
Normal file
|
@ -0,0 +1,448 @@
|
|||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use App\Entity\PostalCodeInquiry;
|
||||
use App\Entity\CardToShebaInquiry;
|
||||
use App\Entity\AccountToShebaInquiry;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
class Inquiry
|
||||
{
|
||||
public function __construct(private EntityManagerInterface $entityManager)
|
||||
{
|
||||
}
|
||||
|
||||
public function postalCodeToAddress($postalCode)
|
||||
{
|
||||
// ابتدا بررسی دیتابیس
|
||||
$existingInquiry = $this->entityManager->getRepository(PostalCodeInquiry::class)->findByPostalCode($postalCode);
|
||||
|
||||
if ($existingInquiry) {
|
||||
// اگر در دیتابیس موجود است، از آن استفاده کن
|
||||
$addressData = $existingInquiry->getAddressData();
|
||||
return [
|
||||
'result' => 1,
|
||||
'response_body' => [
|
||||
'data' => [
|
||||
'address' => $addressData
|
||||
],
|
||||
'message' => 'موفق (از کش)',
|
||||
'error_code' => null
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
// اگر در دیتابیس موجود نیست، از API استفاده کن
|
||||
$registryMGR = new RegistryMGR($this->entityManager);
|
||||
$inquiryPanel = $registryMGR->get('system', key: 'inquiryPanel');
|
||||
if($inquiryPanel == 'zohal'){
|
||||
$inquiryZohalAPIKey = $registryMGR->get('system', key: 'inquiryZohalAPIKey');
|
||||
|
||||
// بررسی وجود API Key
|
||||
if (empty($inquiryZohalAPIKey)) {
|
||||
return [
|
||||
'result' => 0,
|
||||
'message' => 'API Key تنظیم نشده است',
|
||||
'error_code' => 'API_KEY_MISSING'
|
||||
];
|
||||
}
|
||||
|
||||
// استفاده از API جدید زحل
|
||||
$url = "https://service.zohal.io/api/v0/services/inquiry/postal_code_inquiry";
|
||||
|
||||
// آمادهسازی دادههای JSON
|
||||
$postData = json_encode([
|
||||
'postal_code' => $postalCode
|
||||
]);
|
||||
|
||||
// تنظیمات cURL
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'Content-Type: application/json',
|
||||
'Content-Length: ' . strlen($postData),
|
||||
'Authorization: Bearer ' . $inquiryZohalAPIKey,
|
||||
'X-API-Key: ' . $inquiryZohalAPIKey
|
||||
]);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$curlError = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
// بررسی خطای cURL
|
||||
if ($curlError) {
|
||||
return [
|
||||
'result' => 0,
|
||||
'message' => 'خطا در ارتباط با سرور: ' . $curlError,
|
||||
'error_code' => 'CURL_ERROR'
|
||||
];
|
||||
}
|
||||
|
||||
if ($httpCode === 200) {
|
||||
$data = json_decode($response, true);
|
||||
|
||||
// بررسی کدهای result
|
||||
if (isset($data['result'])) {
|
||||
switch ($data['result']) {
|
||||
case 1:
|
||||
// موفق - ذخیره در دیتابیس
|
||||
if (isset($data['response_body']['data']['address'])) {
|
||||
$this->saveToDatabase($postalCode, $data['response_body']['data']['address']);
|
||||
}
|
||||
return $data;
|
||||
case 4:
|
||||
return [
|
||||
'result' => 4,
|
||||
'message' => 'توکن غیر فعال شده است',
|
||||
'error_code' => 'TOKEN_INACTIVE'
|
||||
];
|
||||
case 5:
|
||||
return [
|
||||
'result' => 5,
|
||||
'message' => 'سرویس در دسترسی نمیباشد',
|
||||
'error_code' => 'SERVICE_UNAVAILABLE'
|
||||
];
|
||||
case 6:
|
||||
return [
|
||||
'result' => 6,
|
||||
'message' => 'فراخوانی وبسرویس با پارامترهای ورودی صحیح نمیباشد',
|
||||
'error_code' => 'INVALID_PARAMETERS'
|
||||
];
|
||||
default:
|
||||
return [
|
||||
'result' => $data['result'],
|
||||
'message' => $data['message'] ?? 'خطای نامشخص',
|
||||
'error_code' => $data['error_code'] ?? 'UNKNOWN_ERROR'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
} else {
|
||||
return [
|
||||
'result' => 0,
|
||||
'message' => 'خطا در ارتباط با سرویس استعلام کد پستی (کد خطا: ' . $httpCode . ')',
|
||||
'error_code' => 'HTTP_ERROR_' . $httpCode
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'result' => 0,
|
||||
'message' => 'سرویس استعلام کد پستی فعال نیست',
|
||||
'error_code' => 'SERVICE_NOT_ACTIVE'
|
||||
];
|
||||
}
|
||||
|
||||
public function cardToSheba($cardNumber)
|
||||
{
|
||||
// بررسی دیتابیس برای کش
|
||||
$existingInquiry = $this->entityManager->getRepository(CardToShebaInquiry::class)->findByCardNumber($cardNumber);
|
||||
|
||||
if ($existingInquiry) {
|
||||
// اگر در دیتابیس موجود است، از آن استفاده کن
|
||||
$shebaData = $existingInquiry->getShebaData();
|
||||
return [
|
||||
'result' => 1,
|
||||
'response_body' => [
|
||||
'data' => $shebaData,
|
||||
'message' => 'موفق (از حافظه موقت)',
|
||||
'error_code' => null
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
// اگر در دیتابیس موجود نیست، از API استفاده کن
|
||||
$registryMGR = new RegistryMGR($this->entityManager);
|
||||
$inquiryPanel = $registryMGR->get('system', key: 'inquiryPanel');
|
||||
if($inquiryPanel == 'zohal'){
|
||||
$inquiryZohalAPIKey = $registryMGR->get('system', key: 'inquiryZohalAPIKey');
|
||||
|
||||
// بررسی وجود API Key
|
||||
if (empty($inquiryZohalAPIKey)) {
|
||||
return [
|
||||
'result' => 0,
|
||||
'message' => 'API Key تنظیم نشده است',
|
||||
'error_code' => 'API_KEY_MISSING'
|
||||
];
|
||||
}
|
||||
|
||||
// استفاده از API زحل برای تبدیل کارت به شبا
|
||||
$url = "https://service.zohal.io/api/v0/services/inquiry/card_to_iban";
|
||||
|
||||
// آمادهسازی دادههای JSON
|
||||
$postData = json_encode([
|
||||
'card_number' => $cardNumber
|
||||
]);
|
||||
|
||||
// تنظیمات cURL
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'Content-Type: application/json',
|
||||
'Content-Length: ' . strlen($postData),
|
||||
'Authorization: Bearer ' . $inquiryZohalAPIKey,
|
||||
'X-API-Key: ' . $inquiryZohalAPIKey
|
||||
]);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$curlError = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
// بررسی خطای cURL
|
||||
if ($curlError) {
|
||||
return [
|
||||
'result' => 0,
|
||||
'message' => 'خطا در ارتباط با سرور: ' . $curlError,
|
||||
'error_code' => 'CURL_ERROR'
|
||||
];
|
||||
}
|
||||
|
||||
if ($httpCode === 200) {
|
||||
$data = json_decode($response, true);
|
||||
|
||||
// بررسی کدهای result
|
||||
if (isset($data['result'])) {
|
||||
switch ($data['result']) {
|
||||
case 1:
|
||||
// موفق - ذخیره در دیتابیس
|
||||
if (isset($data['response_body']['data'])) {
|
||||
$this->saveCardToShebaToDatabase($cardNumber, $data['response_body']['data']);
|
||||
}
|
||||
return $data;
|
||||
case 4:
|
||||
return [
|
||||
'result' => 4,
|
||||
'message' => 'توکن غیر فعال شده است',
|
||||
'error_code' => 'TOKEN_INACTIVE'
|
||||
];
|
||||
case 5:
|
||||
return [
|
||||
'result' => 5,
|
||||
'message' => 'سرویس در دسترسی نمیباشد',
|
||||
'error_code' => 'SERVICE_UNAVAILABLE'
|
||||
];
|
||||
case 6:
|
||||
return [
|
||||
'result' => 6,
|
||||
'message' => 'فراخوانی وبسرویس با پارامترهای ورودی صحیح نمیباشد',
|
||||
'error_code' => 'INVALID_PARAMETERS'
|
||||
];
|
||||
default:
|
||||
return [
|
||||
'result' => $data['result'],
|
||||
'message' => $data['message'] ?? 'خطای نامشخص',
|
||||
'error_code' => $data['error_code'] ?? 'UNKNOWN_ERROR'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
} else {
|
||||
return [
|
||||
'result' => 0,
|
||||
'message' => 'خطا در ارتباط با سرویس تبدیل کارت به شبا (کد خطا: ' . $httpCode . ')',
|
||||
'error_code' => 'HTTP_ERROR_' . $httpCode
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'result' => 0,
|
||||
'message' => 'سرویس تبدیل کارت به شبا فعال نیست',
|
||||
'error_code' => 'SERVICE_NOT_ACTIVE'
|
||||
];
|
||||
}
|
||||
|
||||
private function saveToDatabase(string $postalCode, array $addressData): void
|
||||
{
|
||||
try {
|
||||
$inquiry = new PostalCodeInquiry();
|
||||
$inquiry->setPostalCode($postalCode);
|
||||
$inquiry->setAddressData($addressData);
|
||||
$inquiry->setUpdatedAt(new \DateTimeImmutable());
|
||||
|
||||
$this->entityManager->persist($inquiry);
|
||||
$this->entityManager->flush();
|
||||
|
||||
// ثبت لاگ ذخیره موفق در دیتابیس
|
||||
error_log("کد پستی {$postalCode} با موفقیت در کش ذخیره شد");
|
||||
} catch (\Exception $e) {
|
||||
// در صورت خطا در ذخیره، فقط لاگ کن و ادامه بده
|
||||
error_log('خطا در ذخیره استعلام کد پستی: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function accountToSheba($bankCode, $accountNumber)
|
||||
{
|
||||
// بررسی دیتابیس برای کش
|
||||
$cacheKey = $bankCode . '_' . $accountNumber;
|
||||
$existingInquiry = $this->entityManager->getRepository(AccountToShebaInquiry::class)->findByCacheKey($cacheKey);
|
||||
|
||||
if ($existingInquiry) {
|
||||
// اگر در دیتابیس موجود است، از آن استفاده کن
|
||||
$shebaData = $existingInquiry->getShebaData();
|
||||
return [
|
||||
'result' => 1,
|
||||
'response_body' => [
|
||||
'data' => $shebaData,
|
||||
'message' => 'موفق (از حافظه موقت)',
|
||||
'error_code' => null
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
// اگر در دیتابیس موجود نیست، از API استفاده کن
|
||||
$registryMGR = new RegistryMGR($this->entityManager);
|
||||
$inquiryPanel = $registryMGR->get('system', key: 'inquiryPanel');
|
||||
if($inquiryPanel == 'zohal'){
|
||||
$inquiryZohalAPIKey = $registryMGR->get('system', key: 'inquiryZohalAPIKey');
|
||||
|
||||
// بررسی وجود API Key
|
||||
if (empty($inquiryZohalAPIKey)) {
|
||||
return [
|
||||
'result' => 0,
|
||||
'message' => 'API Key تنظیم نشده است',
|
||||
'error_code' => 'API_KEY_MISSING'
|
||||
];
|
||||
}
|
||||
|
||||
// استفاده از API زحل برای تبدیل حساب به شبا
|
||||
$url = "https://service.zohal.io/api/v0/services/inquiry/account_to_iban";
|
||||
|
||||
// آمادهسازی دادههای JSON
|
||||
$postData = json_encode([
|
||||
'bank_code' => $bankCode,
|
||||
'bank_account' => $accountNumber
|
||||
]);
|
||||
|
||||
// تنظیمات cURL
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'Content-Type: application/json',
|
||||
'Content-Length: ' . strlen($postData),
|
||||
'Authorization: Bearer ' . $inquiryZohalAPIKey,
|
||||
'X-API-Key: ' . $inquiryZohalAPIKey
|
||||
]);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$curlError = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
// بررسی خطای cURL
|
||||
if ($curlError) {
|
||||
return [
|
||||
'result' => 0,
|
||||
'message' => 'خطا در ارتباط با سرور: ' . $curlError,
|
||||
'error_code' => 'CURL_ERROR'
|
||||
];
|
||||
}
|
||||
|
||||
if ($httpCode === 200) {
|
||||
$data = json_decode($response, true);
|
||||
|
||||
// بررسی کدهای result
|
||||
if (isset($data['result'])) {
|
||||
switch ($data['result']) {
|
||||
case 1:
|
||||
// موفق - ذخیره در دیتابیس
|
||||
if (isset($data['response_body']['data'])) {
|
||||
$this->saveAccountToShebaToDatabase($cacheKey, $data['response_body']['data']);
|
||||
}
|
||||
return $data;
|
||||
case 4:
|
||||
return [
|
||||
'result' => 4,
|
||||
'message' => 'توکن غیر فعال شده است',
|
||||
'error_code' => 'TOKEN_INACTIVE'
|
||||
];
|
||||
case 5:
|
||||
return [
|
||||
'result' => 5,
|
||||
'message' => 'سرویس در دسترسی نمیباشد',
|
||||
'error_code' => 'SERVICE_UNAVAILABLE'
|
||||
];
|
||||
case 6:
|
||||
return [
|
||||
'result' => 6,
|
||||
'message' => 'فراخوانی وبسرویس با پارامترهای ورودی صحیح نمیباشد',
|
||||
'error_code' => 'INVALID_PARAMETERS'
|
||||
];
|
||||
default:
|
||||
return [
|
||||
'result' => $data['result'],
|
||||
'message' => $data['message'] ?? 'خطای نامشخص',
|
||||
'error_code' => $data['error_code'] ?? 'UNKNOWN_ERROR'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
} else {
|
||||
return [
|
||||
'result' => 0,
|
||||
'message' => 'خطا در ارتباط با سرویس تبدیل حساب به شبا (کد خطا: ' . $httpCode . ')',
|
||||
'error_code' => 'HTTP_ERROR_' . $httpCode
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'result' => 0,
|
||||
'message' => 'سرویس تبدیل حساب به شبا فعال نیست',
|
||||
'error_code' => 'SERVICE_NOT_ACTIVE'
|
||||
];
|
||||
}
|
||||
|
||||
private function saveCardToShebaToDatabase(string $cardNumber, array $shebaData): void
|
||||
{
|
||||
try {
|
||||
$inquiry = new CardToShebaInquiry();
|
||||
$inquiry->setCardNumber($cardNumber);
|
||||
$inquiry->setShebaData($shebaData);
|
||||
$inquiry->setUpdatedAt(new \DateTimeImmutable());
|
||||
|
||||
$this->entityManager->persist($inquiry);
|
||||
$this->entityManager->flush();
|
||||
|
||||
// ثبت لاگ ذخیره موفق در دیتابیس
|
||||
error_log("شماره کارت {$cardNumber} با موفقیت در حافظه موقت ذخیره شد");
|
||||
} catch (\Exception $e) {
|
||||
// در صورت خطا در ذخیره، فقط لاگ کن و ادامه بده
|
||||
error_log('خطا در ذخیره استعلام کارت به شبا: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private function saveAccountToShebaToDatabase(string $cacheKey, array $shebaData): void
|
||||
{
|
||||
try {
|
||||
$inquiry = new AccountToShebaInquiry();
|
||||
$inquiry->setCacheKey($cacheKey);
|
||||
$inquiry->setShebaData($shebaData);
|
||||
$inquiry->setUpdatedAt(new \DateTimeImmutable());
|
||||
|
||||
$this->entityManager->persist($inquiry);
|
||||
$this->entityManager->flush();
|
||||
|
||||
// ثبت لاگ ذخیره موفق در دیتابیس
|
||||
error_log("حساب با کلید {$cacheKey} با موفقیت در حافظه موقت ذخیره شد");
|
||||
} catch (\Exception $e) {
|
||||
// در صورت خطا در ذخیره، فقط لاگ کن و ادامه بده
|
||||
error_log('خطا در ذخیره استعلام حساب به شبا: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,15 +8,6 @@
|
|||
"ref": "64d8583af5ea57b7afa4aba4b159907f3a148b05"
|
||||
}
|
||||
},
|
||||
"doctrine/deprecations": {
|
||||
"version": "1.1",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "1.0",
|
||||
"ref": "87424683adc81d7dc305eefec1fced883084aab9"
|
||||
}
|
||||
},
|
||||
"doctrine/doctrine-bundle": {
|
||||
"version": "2.10",
|
||||
"recipe": {
|
||||
|
|
|
@ -791,11 +791,11 @@ install_software() {
|
|||
# Check if remote origin exists
|
||||
if ! git remote get-url origin >/dev/null 2>&1; then
|
||||
# Add remote repository if it doesn't exist
|
||||
git remote add origin https://github.com/morrning/hesabixCore.git || \
|
||||
git remote add origin https://source.hesabix.ir/morrning/hesabixCore.git || \
|
||||
handle_error "Failed to add remote repository"
|
||||
else
|
||||
# Update remote URL if it exists
|
||||
git remote set-url origin https://github.com/morrning/hesabixCore.git || \
|
||||
git remote set-url origin https://source.hesabix.ir/morrning/hesabixCore.git || \
|
||||
handle_error "Failed to update remote repository"
|
||||
fi
|
||||
|
||||
|
|
0
webUI/.github/workflows/release.yml
vendored
Executable file → Normal file
0
webUI/.github/workflows/release.yml
vendored
Executable file → Normal file
0
webUI/.gitignore
vendored
Executable file → Normal file
0
webUI/.gitignore
vendored
Executable file → Normal file
0
webUI/LICENSE
Executable file → Normal file
0
webUI/LICENSE
Executable file → Normal file
0
webUI/env.d.ts
vendored
Executable file → Normal file
0
webUI/env.d.ts
vendored
Executable file → Normal file
0
webUI/index.html
Executable file → Normal file
0
webUI/index.html
Executable file → Normal file
0
webUI/package.json
Executable file → Normal file
0
webUI/package.json
Executable file → Normal file
0
webUI/public/.htaccess
Executable file → Normal file
0
webUI/public/.htaccess
Executable file → Normal file
0
webUI/public/dashmix/dashmix.app.min.js
vendored
Executable file → Normal file
0
webUI/public/dashmix/dashmix.app.min.js
vendored
Executable file → Normal file
0
webUI/public/dashmix/dashmix.min.css
vendored
Executable file → Normal file
0
webUI/public/dashmix/dashmix.min.css
vendored
Executable file → Normal file
0
webUI/public/favicon.ico
Executable file → Normal file
0
webUI/public/favicon.ico
Executable file → Normal file
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
0
webUI/public/fonts/fontawesome/fa-brands-400.ttf
Executable file → Normal file
0
webUI/public/fonts/fontawesome/fa-brands-400.ttf
Executable file → Normal file
0
webUI/public/fonts/fontawesome/fa-brands-400.woff2
Executable file → Normal file
0
webUI/public/fonts/fontawesome/fa-brands-400.woff2
Executable file → Normal file
0
webUI/public/fonts/fontawesome/fa-regular-400.ttf
Executable file → Normal file
0
webUI/public/fonts/fontawesome/fa-regular-400.ttf
Executable file → Normal file
0
webUI/public/fonts/fontawesome/fa-regular-400.woff2
Executable file → Normal file
0
webUI/public/fonts/fontawesome/fa-regular-400.woff2
Executable file → Normal file
0
webUI/public/fonts/fontawesome/fa-solid-900.ttf
Executable file → Normal file
0
webUI/public/fonts/fontawesome/fa-solid-900.ttf
Executable file → Normal file
0
webUI/public/fonts/fontawesome/fa-solid-900.woff2
Executable file → Normal file
0
webUI/public/fonts/fontawesome/fa-solid-900.woff2
Executable file → Normal file
0
webUI/public/fonts/fontawesome/fa-v4compatibility.ttf
Executable file → Normal file
0
webUI/public/fonts/fontawesome/fa-v4compatibility.ttf
Executable file → Normal file
0
webUI/public/fonts/fontawesome/fa-v4compatibility.woff2
Executable file → Normal file
0
webUI/public/fonts/fontawesome/fa-v4compatibility.woff2
Executable file → Normal file
0
webUI/public/fonts/inter/inter-v11-latin-300.woff2
Executable file → Normal file
0
webUI/public/fonts/inter/inter-v11-latin-300.woff2
Executable file → Normal file
0
webUI/public/fonts/inter/inter-v11-latin-500.woff2
Executable file → Normal file
0
webUI/public/fonts/inter/inter-v11-latin-500.woff2
Executable file → Normal file
0
webUI/public/fonts/inter/inter-v11-latin-600.woff2
Executable file → Normal file
0
webUI/public/fonts/inter/inter-v11-latin-600.woff2
Executable file → Normal file
0
webUI/public/fonts/inter/inter-v11-latin-700.woff2
Executable file → Normal file
0
webUI/public/fonts/inter/inter-v11-latin-700.woff2
Executable file → Normal file
0
webUI/public/fonts/inter/inter-v11-latin-800.woff2
Executable file → Normal file
0
webUI/public/fonts/inter/inter-v11-latin-800.woff2
Executable file → Normal file
0
webUI/public/fonts/inter/inter-v11-latin-900.woff2
Executable file → Normal file
0
webUI/public/fonts/inter/inter-v11-latin-900.woff2
Executable file → Normal file
0
webUI/public/fonts/inter/inter-v11-latin-regular.woff2
Executable file → Normal file
0
webUI/public/fonts/inter/inter-v11-latin-regular.woff2
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-Black-FD.eot
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-Black-FD.eot
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-Black-FD.ttf
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-Black-FD.ttf
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-Black-FD.woff
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-Black-FD.woff
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-Black-FD.woff2
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-Black-FD.woff2
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-Bold-FD.eot
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-Bold-FD.eot
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-Bold-FD.ttf
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-Bold-FD.ttf
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-Bold-FD.woff
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-Bold-FD.woff
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-Bold-FD.woff2
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-Bold-FD.woff2
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-FD.eot
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-FD.eot
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-FD.ttf
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-FD.ttf
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-FD.woff
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-FD.woff
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-FD.woff2
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-FD.woff2
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-Light-FD.eot
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-Light-FD.eot
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-Light-FD.ttf
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-Light-FD.ttf
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-Light-FD.woff
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-Light-FD.woff
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-Light-FD.woff2
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-Light-FD.woff2
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-SemiBold-FD.eot
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-SemiBold-FD.eot
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-SemiBold-FD.ttf
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-SemiBold-FD.ttf
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-SemiBold-FD.woff
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-SemiBold-FD.woff
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-SemiBold-FD.woff2
Executable file → Normal file
0
webUI/public/fonts/sahel/Sahel-SemiBold-FD.woff2
Executable file → Normal file
0
webUI/public/fonts/sahel/sahel.css
Executable file → Normal file
0
webUI/public/fonts/sahel/sahel.css
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Bold-FD.eot
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Bold-FD.eot
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Bold-FD.ttf
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Bold-FD.ttf
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Bold-FD.woff
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Bold-FD.woff
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Bold-FD.woff2
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Bold-FD.woff2
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-FD.eot
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-FD.eot
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-FD.ttf
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-FD.ttf
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-FD.woff
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-FD.woff
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-FD.woff2
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-FD.woff2
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Light-FD.eot
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Light-FD.eot
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Light-FD.ttf
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Light-FD.ttf
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Light-FD.woff
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Light-FD.woff
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Light-FD.woff2
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Light-FD.woff2
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Medium-FD.eot
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Medium-FD.eot
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Medium-FD.ttf
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Medium-FD.ttf
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Medium-FD.woff
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Medium-FD.woff
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Medium-FD.woff2
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Medium-FD.woff2
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Thin-FD.eot
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Thin-FD.eot
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Thin-FD.ttf
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Thin-FD.ttf
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Thin-FD.woff
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Thin-FD.woff
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Thin-FD.woff2
Executable file → Normal file
0
webUI/public/fonts/shabnam/Shabnam-Thin-FD.woff2
Executable file → Normal file
0
webUI/public/fonts/shabnam/shabnam.css
Executable file → Normal file
0
webUI/public/fonts/shabnam/shabnam.css
Executable file → Normal file
0
webUI/public/fonts/simple-line-icons/Simple-Line-Icons.eot
Executable file → Normal file
0
webUI/public/fonts/simple-line-icons/Simple-Line-Icons.eot
Executable file → Normal file
0
webUI/public/fonts/simple-line-icons/Simple-Line-Icons.svg
Executable file → Normal file
0
webUI/public/fonts/simple-line-icons/Simple-Line-Icons.svg
Executable file → Normal file
Before Width: | Height: | Size: 235 KiB After Width: | Height: | Size: 235 KiB |
0
webUI/public/fonts/simple-line-icons/Simple-Line-Icons.ttf
Executable file → Normal file
0
webUI/public/fonts/simple-line-icons/Simple-Line-Icons.ttf
Executable file → Normal file
0
webUI/public/fonts/simple-line-icons/Simple-Line-Icons.woff
Executable file → Normal file
0
webUI/public/fonts/simple-line-icons/Simple-Line-Icons.woff
Executable file → Normal file
0
webUI/public/fonts/simple-line-icons/Simple-Line-Icons.woff2
Executable file → Normal file
0
webUI/public/fonts/simple-line-icons/Simple-Line-Icons.woff2
Executable file → Normal file
0
webUI/public/fonts/vazir/ttf/Vazirmatn-Black.ttf
Executable file → Normal file
0
webUI/public/fonts/vazir/ttf/Vazirmatn-Black.ttf
Executable file → Normal file
0
webUI/public/fonts/vazir/ttf/Vazirmatn-Bold.ttf
Executable file → Normal file
0
webUI/public/fonts/vazir/ttf/Vazirmatn-Bold.ttf
Executable file → Normal file
0
webUI/public/fonts/vazir/ttf/Vazirmatn-ExtraBold.ttf
Executable file → Normal file
0
webUI/public/fonts/vazir/ttf/Vazirmatn-ExtraBold.ttf
Executable file → Normal file
0
webUI/public/fonts/vazir/ttf/Vazirmatn-ExtraLight.ttf
Executable file → Normal file
0
webUI/public/fonts/vazir/ttf/Vazirmatn-ExtraLight.ttf
Executable file → Normal file
0
webUI/public/fonts/vazir/ttf/Vazirmatn-Light.ttf
Executable file → Normal file
0
webUI/public/fonts/vazir/ttf/Vazirmatn-Light.ttf
Executable file → Normal file
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue