almost finishe cheques

This commit is contained in:
Hesabix 2025-04-12 15:20:34 +00:00
parent d09149f916
commit 9bc3a27ce2
16 changed files with 1044 additions and 484 deletions

View file

@ -16,7 +16,7 @@ use App\Service\JsonResp;
use App\Service\Provider;
use App\Service\SMS;
use App\Service\PluginService;
use App\Service\RegistryMGR;
use App\Service\registryMGR;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
@ -34,14 +34,36 @@ class ChequeController extends AbstractController
$acc = $access->hasRole('cheque');
if (!$acc)
throw $this->createAccessDeniedException();
$chequesInput = $entityManager->getRepository(Cheque::class)->findBy([
'bid' => $acc['bid'],
'type' => 'input'
]);
$chequesOutput = $entityManager->getRepository(Cheque::class)->findBy([
'bid' => $acc['bid'],
'type' => 'output'
]);
$money = $acc['money'];
$defaultMoey = $acc['bid']->getMoney();
$defMoney = false;
if ($defaultMoey->getId() == $money->getId()) {
$defMoney = true;
}
$qb = $entityManager->createQueryBuilder();
$chequesInput = $qb->select('c')
->from(Cheque::class, 'c')
->where('c.bid = :bid')
->andWhere('c.type = :type')
->andWhere($defMoney ? '(c.money = :money OR c.money IS NULL)' : 'c.money = :money')
->setParameter('bid', $acc['bid'])
->setParameter('type', 'input')
->setParameter('money', $money)
->getQuery()
->getResult();
$qb = $entityManager->createQueryBuilder();
$chequesOutput = $qb->select('c')
->from(Cheque::class, 'c')
->where('c.bid = :bid')
->andWhere('c.type = :type')
->andWhere($defMoney ? '(c.money = :money OR c.money IS NULL)' : 'c.money = :money')
->setParameter('bid', $acc['bid'])
->setParameter('type', 'output')
->setParameter('money', $money)
->getQuery()
->getResult();
return $this->json([
'input' => Explore::SerializeCheques(array_reverse($chequesInput)),
'output' => Explore::SerializeCheques(array_reverse($chequesOutput))
@ -65,23 +87,8 @@ class ChequeController extends AbstractController
);
}
#[Route('/api/cheque/info/{id}', name: 'app_cheque_info')]
public function app_cheque_info(string $id, Provider $provider, Request $request, Access $access, Log $log, EntityManagerInterface $entityManager, Jdate $jdate): JsonResponse
{
$acc = $access->hasRole('cheque');
if (!$acc)
throw $this->createAccessDeniedException();
$cheque = $entityManager->getRepository(Cheque::class)->findOneBy([
'bid' => $acc['bid'],
'id' => $id
]);
if (!$cheque)
throw $this->createNotFoundException('cheque not found');
return $this->json(Explore::SerializeCheque($cheque));
}
#[Route('/api/cheque/reject/{id}', name: 'app_cheque_reject')]
public function app_cheque_reject(string $id, Provider $provider, Request $request, Access $access, Log $log, EntityManagerInterface $entityManager, Jdate $jdate): JsonResponse
public function app_cheque_reject(string $id, Provider $provider, Request $request, Access $access, Log $log, EntityManagerInterface $entityManager, Jdate $jdate, SMS $SMS, registryMGR $registryMGR, PluginService $pluginService): JsonResponse
{
$acc = $access->hasRole('cheque');
if (!$acc)
@ -94,14 +101,77 @@ class ChequeController extends AbstractController
throw $this->createNotFoundException('cheque not found');
$cheque->setStatus('برگشت خورده');
$cheque->setRejected(true);
$log->insert('بانکداری', 'چک شماره شماره ' . $cheque->getNumber() . ' به برگشت خورده تغییر یافت. ', $this->getUser(), $request->headers->get('activeBid'));
$cheque->setLocked(true);
$entityManager->persist($cheque);
$hesabdariDoc = new HesabdariDoc;
$hesabdariDoc->setBid($acc['bid']);
$hesabdariDoc->setSubmitter($this->getUser());
$hesabdariDoc->setYear($acc['year']);
$hesabdariDoc->setMoney($acc['money']);
$hesabdariDoc->setDateSubmit(time());
$hesabdariDoc->setType('reject_cheque');
$hesabdariDoc->setCode($provider->getAccountingCode($acc['bid'], 'accounting'));
$hesabdariDoc->setDate($cheque->getDate());
$hesabdariDoc->setDes('برگشت خورده چک شماره ' . $cheque->getNumber());
$hesabdariDoc->setAmount($cheque->getAmount());
$entityManager->persist($hesabdariDoc);
$hesabdariRow1 = new HesabdariRow;
$hesabdariRow1->setDoc($hesabdariDoc);
$hesabdariRow1->setCheque($cheque);
$hesabdariRow1->setPerson($cheque->getPerson());
$hesabdariRow1->setYear($acc['year']);
$hesabdariRow1->setBs(0);
$hesabdariRow1->setRef($entityManager->getRepository(HesabdariTable::class)->findOneBy(['code' => 126]));
$hesabdariRow1->setBd($cheque->getAmount());
$hesabdariRow1->setBid($acc['bid']);
$hesabdariRow1->setDes('برگشت خورده چک شماره ' . $cheque->getNumber());
$entityManager->persist($hesabdariRow1);
$hesabdariRow2 = new HesabdariRow;
$hesabdariRow2->setDoc($hesabdariDoc);
$hesabdariRow2->setCheque($cheque);
$hesabdariRow2->setYear($acc['year']);
$hesabdariRow2->setBs($cheque->getAmount());
$hesabdariRow2->setRef($entityManager->getRepository(HesabdariTable::class)->findOneBy(['code' => 125]));
$hesabdariRow2->setBd(0);
$hesabdariRow2->setBid($acc['bid']);
$hesabdariRow2->setDes('برگشت خورده چک شماره ' . $cheque->getNumber());
$entityManager->persist($hesabdariRow2);
//send sms
$params = $request->getPayload()->all();
if (array_key_exists('sendSms', $params) && $params['sendSms'] == true && $registryMGR->get('sms', 'chequeReject') != '' && $registryMGR->get('sms', 'plugAccproChequeReject') != '') {
$person = $cheque->getPerson();
if ($person && $person->getMobile() && !$pluginService->isActive('accpro', $acc['bid'])) {
$SMS->sendByBalance(
[$person->getNikename(), $cheque->getNumber(), number_format($cheque->getAmount()), $cheque->getBankoncheque(), $cheque->getDate(), $acc['bid']->getName(), $acc['bid']->getName()],
$registryMGR->get('sms', 'chequeReject'),
$person->getMobile(),
$acc['bid'],
$this->getUser(),
3
);
} elseif ($person && $person->getMobile() && $pluginService->isActive('accpro', $acc['bid'])) {
$SMS->sendByBalance(
[$person->getNikename(), $cheque->getNumber(), number_format($cheque->getAmount()), $cheque->getBankoncheque(), $cheque->getDate(), $acc['bid']->getName(), $acc['bid']->getName()],
$registryMGR->get('sms', 'plugAccproChequeReject'),
$person->getMobile(),
$acc['bid'],
$this->getUser(),
2
);
}
}
$entityManager->flush();
$log->insert('بانکداری', 'چک شماره ' . $cheque->getNumber() . ' به برگشت خورده تغییر یافت. ', $this->getUser(), $request->headers->get('activeBid'), $hesabdariDoc);
return $this->json(['result' => 'ok']);
}
#[Route('/api/cheque/pass/{id}', name: 'app_cheque_pass')]
public function app_cheque_pass(string $id, Provider $provider, Request $request, Access $access, Log $log, EntityManagerInterface $entityManager, Jdate $jdate): JsonResponse
#[Route('/api/cheque/pass/input/{id}', name: 'app_cheque_pass_input')]
public function app_cheque_pass_input(string $id, Provider $provider, Request $request, Access $access, Log $log, EntityManagerInterface $entityManager, Jdate $jdate): JsonResponse
{
$acc = $access->hasRole('cheque');
if (!$acc)
@ -119,7 +189,7 @@ class ChequeController extends AbstractController
]);
$bank = $entityManager->getRepository(BankAccount::class)->findOneBy([
'bid' => $acc['bid'],
'code' => $params['bank']['code']
'id' => $params['bank']
]);
if (!$cheque || !$bank)
throw $this->createNotFoundException();
@ -128,8 +198,8 @@ class ChequeController extends AbstractController
//edit cheque info
$cheque->setBank($bank);
$cheque->setStatus('پاس شده');
$cheque->setDate($params['date']);
$cheque->setStatus('وصول');
$cheque->setPayDate($params['date']);
$cheque->setLocked(true);
$entityManager->persist($cheque);
@ -151,13 +221,12 @@ class ChequeController extends AbstractController
$hesabdariRow1 = new HesabdariRow();
$hesabdariRow1->setDoc($hesabdariDoc);
$hesabdariRow1->setCheque($cheque);
$hesabdariRow1->setPerson($cheque->getPerson());
$hesabdariRow1->setYear($acc['year']);
$hesabdariRow1->setBs($cheque->getAmount());
$hesabdariRow1->setRef($entityManager->getRepository(HesabdariTable::class)->findOneBy(['code' => 3]));
$hesabdariRow1->setRef($entityManager->getRepository(HesabdariTable::class)->findOneBy(['code' => 126]));
$hesabdariRow1->setBd(0);
$hesabdariRow1->setBid($acc['bid']);
$hesabdariRow1->setDes('پاس شدن چک و انتقال به بانک');
$hesabdariRow1->setDes('وصول چک و انتقال به بانک');
$entityManager->persist($hesabdariRow1);
$hesabdariRow2 = new HesabdariRow();
@ -166,15 +235,15 @@ class ChequeController extends AbstractController
$hesabdariRow2->setBank($bank);
$hesabdariRow2->setYear($acc['year']);
$hesabdariRow2->setBs(0);
$hesabdariRow2->setRef($entityManager->getRepository(HesabdariTable::class)->findOneBy(['code' => 5]));
$hesabdariRow2->setRef($entityManager->getRepository(HesabdariTable::class)->findOneBy(['code' => 125]));
$hesabdariRow2->setBd($cheque->getAmount());
$hesabdariRow2->setBid($acc['bid']);
$hesabdariRow2->setDes('پاس شدن چک و انتقال به بانک');
$hesabdariRow2->setDes('وصول چک و انتقال به بانک');
$entityManager->persist($hesabdariRow2);
$entityManager->flush();
$log->insert(
'حسابداری',
'ثبت چک پاس شده شماره ' . $cheque->getNumber() . ' و ثبت واریز به بانک ' . $bank->getName(),
'ثبت چک وصول شماره ' . $cheque->getNumber() . ' و ثبت واریز به بانک ' . $bank->getName(),
$this->getUser(),
$acc['bid']->getId(),
$hesabdariDoc
@ -186,7 +255,7 @@ class ChequeController extends AbstractController
}
#[Route('/api/cheque/modify/input/{id}', name: 'app_cheque_modify_input')]
public function app_cheque_modify_input(Provider $provider, Request $request, Access $access, Log $log, EntityManagerInterface $entityManager, Jdate $jdate, SMS $SMS, PluginService $pluginService, RegistryMGR $registryMGR, string $id = '0'): JsonResponse
public function app_cheque_modify_input(Provider $provider, Request $request, Access $access, Log $log, EntityManagerInterface $entityManager, Jdate $jdate, SMS $SMS, PluginService $pluginService, \App\Service\registryMGR $registryMGR, string $id = '0'): JsonResponse
{
$acc = $access->hasRole('cheque');
if (!$acc)
@ -202,13 +271,14 @@ class ChequeController extends AbstractController
$cheque->setDateStamp(time());
$cheque->setSubmitter($this->getUser());
$cheque->setBid($acc['bid']);
$cheque->setStatus('پاس نشده');
$cheque->setMoney($acc['money']);
$cheque->setStatus('وصول نشده');
$cheque->setRef($entityManager->getRepository(HesabdariTable::class)->findOneBy(['code' => 125]));
} else {
$cheque = $entityManager->getRepository(Cheque::class)->findOneBy(['id' => $id, 'bid' => $acc['bid']]);
if (!$cheque)
throw $this->createNotFoundException('cheque not found');
if ($cheque->isRejected() || $cheque->getStatus() === 'پاس شده')
if ($cheque->isRejected() || $cheque->getStatus() === 'وصول شده')
throw $this->createAccessDeniedException('امکان ویرایش این چک وجود ندارد');
}
$cheque->setNumber($params['number']);
@ -345,33 +415,10 @@ class ChequeController extends AbstractController
if (!$cheque)
throw $this->createNotFoundException('چک مورد نظر یافت نشد');
if ($cheque->getType() !== 'input')
throw $this->createAccessDeniedException('این چک واریزی نیست');
$chequeData = [
'id' => $cheque->getId(),
'number' => $cheque->getNumber(),
'amount' => $cheque->getAmount(),
'type' => $cheque->getType(),
'status' => $cheque->getStatus(),
'bankoncheque' => $cheque->getBankoncheque(),
'sayadNumber' => $cheque->getSayadNum(),
'dueDate' => $cheque->getPayDate(),
'description' => $cheque->getDes(),
'locked' => $cheque->isLocked(),
'rejected' => $cheque->isRejected(),
'dateSubmit' => $cheque->getDateSubmit(),
'dateStamp' => $cheque->getDateStamp(),
'person' => [
'id' => $cheque->getPerson()->getId(),
'name' => $cheque->getPerson()->getNikename()
],
'bank' => $cheque->getBank() ? [
'id' => $cheque->getBank()->getId(),
'name' => $cheque->getBank()->getName(),
'code' => $cheque->getBank()->getCode()
] : null
];
return $this->json($chequeData);
return $this->json(Explore::SerializeCheque($cheque));
}
#[Route('/api/cheque/unreject/{id}', name: 'app_cheque_unreject')]
@ -392,19 +439,47 @@ class ChequeController extends AbstractController
if (!$cheque->isRejected())
throw $this->createAccessDeniedException('این چک برگشت نخورده است');
$cheque->setStatus('پاس نشده');
$cheque->setStatus('وصول نشده');
$cheque->setRejected(false);
$cheque->setLocked(false);
//حذف سند حسابداری
$hesabdariRow = $entityManager->getRepository(HesabdariRow::class)->findBy([
'cheque' => $cheque,
'bid' => $acc['bid'],
]);
$hesabdariDoc = null;
$code = null;
foreach ($hesabdariRow as $row) {
if ($row->getDoc()->getType() == 'reject_cheque') {
$hesabdariDoc = $row->getDoc();
$code = $hesabdariDoc->getCode();
break;
}
}
if ($hesabdariDoc) {
$oldRows = $hesabdariDoc->getHesabdariRows();
foreach ($oldRows as $row) {
$entityManager->remove($row);
}
//unlink log
$logs = $hesabdariDoc->getLogs();
foreach ($logs as $logItem) {
$logItem->setDoc(null);
$entityManager->persist($logItem);
}
}
$log->insert(
'بانکداری',
'رفع برگشت چک شماره ' . $cheque->getNumber() . ' از ' . $cheque->getPerson()->getNikename(),
'رفع برگشت چک شماره ' . $cheque->getNumber() . ' از ' . $cheque->getPerson()->getNikename() . ' و حذف سند حسابداری ' . $code,
$this->getUser(),
$acc['bid']->getId()
$acc['bid']->getId(),
$hesabdariDoc
);
$entityManager->persist($cheque);
$entityManager->flush();
$entityManager->remove($hesabdariDoc);
return $this->json(['result' => 'ok']);
}
@ -415,48 +490,380 @@ class ChequeController extends AbstractController
if (!$acc)
throw $this->createAccessDeniedException();
$cheque = $entityManager->getRepository(Cheque::class)->findOneBy(['bid' => $request->headers->get('activeBid'), 'id' => $id]);
$cheque = $entityManager->getRepository(Cheque::class)->findOneBy([
'bid' => $request->headers->get('activeBid'),
'id' => $id
]);
if (!$cheque) {
throw new NotFoundHttpException('چک مورد نظر یافت نشد');
}
if ($cheque->isLocked() || $cheque->isRejected()) {
throw new AccessDeniedException('امکان حذف این چک وجود ندارد');
}
$hesabdariRow = $entityManager->getRepository(HesabdariRow::class)->findOneBy([
// پیدا کردن تمام ردیف‌های حسابداری مرتبط با چک
$hesabdariRows = $entityManager->getRepository(HesabdariRow::class)->findBy([
'cheque' => $cheque,
'bid' => $acc['bid']
]);
$hesabdariDoc = $hesabdariRow ? $hesabdariRow->getDoc() : null;
if ($hesabdariDoc) {
// حذف سطرهای حسابداری
$oldRows = $entityManager->getRepository(HesabdariRow::class)->findBy(['doc' => $hesabdariDoc]);
foreach ($oldRows as $row) {
$entityManager->remove($row);
}
// به‌روزرسانی لاگ‌های مرتبط با سند
$logs = $entityManager->getRepository(\App\Entity\Log::class)->findBy(['doc' => $hesabdariDoc]);
foreach ($logs as $logEntry) {
$logEntry->setDoc(null);
$entityManager->persist($logEntry);
}
foreach ($hesabdariRows as $hesabdariRow) {
$hesabdariDoc = $hesabdariRow->getDoc();
if ($hesabdariDoc) {
// پیدا کردن و حذف تمام ردیف‌های مرتبط با این سند
$docRows = $entityManager->getRepository(HesabdariRow::class)->findBy(['doc' => $hesabdariDoc]);
foreach ($docRows as $row) {
$entityManager->remove($row);
}
// حذف سند حسابداری
$code = $hesabdariDoc->getCode();
$entityManager->remove($hesabdariDoc);
// به‌روزرسانی لاگ‌های مرتبط با سند
$logs = $entityManager->getRepository(\App\Entity\Log::class)->findBy(['doc' => $hesabdariDoc]);
foreach ($logs as $logEntry) {
$logEntry->setDoc(null);
$entityManager->persist($logEntry);
}
$code = $hesabdariDoc->getCode();
$entityManager->remove($hesabdariDoc);
$log->insert(
'حسابداری',
'حذف سند حسابداری مرتبط با چک با شماره سند ' . $code,
$this->getUser(),
$request->headers->get('activeBid')
);
}
}
// اعمال تغییرات برای حذف ردیف‌ها و اسناد
$entityManager->flush();
// حذف چک
$chequeNumber = $cheque->getNumber();
$personName = $cheque->getPerson()->getNikename();
$entityManager->remove($cheque);
$entityManager->flush();
$log->insert(
'بانکداری',
'حذف چک شماره ' . $cheque->getNumber() . ' از ' . $cheque->getPerson()->getNikename() . ' و سند حسابداری ' . $code,
'حذف چک شماره ' . $chequeNumber . ' از ' . $personName,
$this->getUser(),
$request->headers->get('activeBid')
);
return $this->json(['result' => 'ok']);
}
#[Route('/api/cheque/transfer/{id}', name: 'app_cheque_transfer')]
public function app_cheque_transfer(string $id, SMS $SMS, PluginService $pluginService, registryMGR $registryMGR, Provider $provider, Request $request, Access $access, Log $log, EntityManagerInterface $entityManager, Jdate $jdate): JsonResponse
{
$acc = $access->hasRole('cheque');
if (!$acc)
throw $this->createAccessDeniedException();
$params = [];
if ($content = $request->getContent()) {
$params = json_decode($content, true);
}
if (!array_key_exists('personId', $params) || !array_key_exists('date', $params))
throw $this->createNotFoundException('اطلاعات ناقص است');
$cheque = $entityManager->getRepository(Cheque::class)->findOneBy([
'bid' => $acc['bid'],
'id' => $id
]);
if (!$cheque)
throw $this->createNotFoundException('چک مورد نظر یافت نشد');
if ($cheque->isLocked())
throw $this->createAccessDeniedException('عملیات بر روی چک قفل شده امکان‌پذیر نیست');
$person = $entityManager->getRepository(Person::class)->findOneBy([
'bid' => $acc['bid'],
'id' => $params['personId']
]);
if (!$person)
throw $this->createNotFoundException('شخص گیرنده یافت نشد');
// به‌روزرسانی اطلاعات چک
$cheque->setTransferDate($params['date']);
$cheque->setTransfered(true);
$cheque->setStatus('واگذار شده');
$cheque->setLocked(true);
$entityManager->persist($cheque);
// ایجاد سند حسابداری
$hesabdariDoc = new HesabdariDoc;
$hesabdariDoc->setBid($acc['bid']);
$hesabdariDoc->setSubmitter($this->getUser());
$hesabdariDoc->setYear($acc['year']);
$hesabdariDoc->setMoney($acc['money']);
$hesabdariDoc->setDateSubmit(time());
$hesabdariDoc->setType('transfer_cheque');
$hesabdariDoc->setCode($provider->getAccountingCode($acc['bid'], 'accounting'));
$hesabdariDoc->setDate($params['date']);
$hesabdariDoc->setDes('واگذاری چک شماره ' . $cheque->getNumber() . ' به ' . $person->getNikename() . ' ' . $params['description']);
$hesabdariDoc->setAmount($cheque->getAmount());
$entityManager->persist($hesabdariDoc);
// ایجاد ردیف‌های حسابداری
$hesabdariRow1 = new HesabdariRow;
$hesabdariRow1->setDoc($hesabdariDoc);
$hesabdariRow1->setCheque($cheque);
$hesabdariRow1->setPerson($person);
$hesabdariRow1->setYear($acc['year']);
$hesabdariRow1->setBs(0);
$hesabdariRow1->setRef($entityManager->getRepository(HesabdariTable::class)->findOneBy(['code' => 125]));
$hesabdariRow1->setBd($cheque->getAmount());
$hesabdariRow1->setBid($acc['bid']);
$hesabdariRow1->setDes('واگذاری چک شماره ' . $cheque->getNumber() . ' به ' . $person->getNikename() . ' ' . $params['description']);
$entityManager->persist($hesabdariRow1);
$hesabdariRow2 = new HesabdariRow;
$hesabdariRow2->setDoc($hesabdariDoc);
$hesabdariRow2->setCheque($cheque);
$hesabdariRow2->setYear($acc['year']);
$hesabdariRow2->setBs($cheque->getAmount());
$hesabdariRow2->setRef($entityManager->getRepository(HesabdariTable::class)->findOneBy(['code' => 126]));
$hesabdariRow2->setBd(0);
$hesabdariRow2->setBid($acc['bid']);
$hesabdariRow2->setDes('واگذاری چک شماره ' . $cheque->getNumber() . ' به ' . $person->getNikename() . ' ' . $params['description']);
$entityManager->persist($hesabdariRow2);
$entityManager->flush();
$log->insert('بانکداری', 'چک شماره ' . $cheque->getNumber() . ' به ' . $person->getNikename() . ' واگذار شد.', $this->getUser(), $request->headers->get('activeBid'), $hesabdariDoc);
//send sms
$params = $request->getPayload()->all();
if (array_key_exists('sendSms', $params) && $params['sendSms'] == true && $registryMGR->get('sms', 'chequeTransfer') != '' && $registryMGR->get('sms', 'plugAccproChequeTransfer') != '') {
$person = $cheque->getPerson();
if ($person && $person->getMobile() && !$pluginService->isActive('accpro', $acc['bid'])) {
$SMS->sendByBalance(
[],
$registryMGR->get('sms', 'chequeTransfer'),
$person->getMobile(),
$acc['bid'],
$this->getUser(),
2
);
}
}
return $this->json(['result' => 'ok']);
}
#[Route('/api/cheque/modify/output/{id}', name: 'app_cheque_modify_output')]
public function app_cheque_modify_output(Provider $provider, Request $request, Access $access, Log $log, EntityManagerInterface $entityManager, Jdate $jdate, string $id = '0'): JsonResponse
{
$acc = $access->hasRole('cheque');
if (!$acc)
throw $this->createAccessDeniedException();
$params = [];
if ($content = $request->getContent()) {
$params = json_decode($content, true);
}
if ($id == '0') {
$cheque = new Cheque;
$cheque->setLocked(false);
$cheque->setDateSubmit(time());
$cheque->setDateStamp(time());
$cheque->setSubmitter($this->getUser());
$cheque->setBid($acc['bid']);
$cheque->setMoney($acc['money']);
$cheque->setStatus('وصول نشده');
$cheque->setRef($entityManager->getRepository(HesabdariTable::class)->findOneBy(['code' => 126]));
} else {
$cheque = $entityManager->getRepository(Cheque::class)->findOneBy(['id' => $id, 'bid' => $acc['bid']]);
if (!$cheque)
throw $this->createNotFoundException('cheque not found');
if ($cheque->isRejected() || $cheque->getStatus() === 'وصول شده')
throw $this->createAccessDeniedException('امکان ویرایش این چک وجود ندارد');
}
$cheque->setNumber($params['number']);
if (!is_numeric($params['amount'])) {
throw new \Exception('مبلغ باید عددی باشد');
}
$cheque->setAmount(strpos($params['amount'], '.') === false ? (int)$params['amount'] : (float)$params['amount']);
$cheque->setType('output');
$cheque->setBankoncheque($params['bankoncheque']);
$cheque->setPerson($entityManager->getRepository(Person::class)->findOneBy(['id' => $params['person']['code'], 'bid' => $acc['bid']]));
$cheque->setSayadNum($params['sayadNumber']);
$cheque->setDate($params['date']);
$cheque->setDes($params['description']);
$entityManager->persist($cheque);
// اگر چک موجود است، سند حسابداری قبلی را پیدا و به‌روزرسانی می‌کنیم
if ($id != '0') {
$hesabdariRow = $entityManager->getRepository(HesabdariRow::class)->findOneBy([
'cheque' => $cheque,
'bid' => $acc['bid']
]);
$hesabdariDoc = $hesabdariRow ? $hesabdariRow->getDoc() : null;
if ($hesabdariDoc) {
// حذف سطرهای حسابداری قبلی
$oldRows = $hesabdariDoc->getHesabdariRows();
foreach ($oldRows as $row) {
$entityManager->remove($row);
}
} else {
$hesabdariDoc = new HesabdariDoc;
}
} else {
$hesabdariDoc = new HesabdariDoc;
}
$hesabdariDoc->setBid($acc['bid']);
$hesabdariDoc->setSubmitter($this->getUser());
$hesabdariDoc->setYear($acc['year']);
$hesabdariDoc->setMoney($acc['money']);
$hesabdariDoc->setDateSubmit(time());
$hesabdariDoc->setType('modify_cheque_output');
$hesabdariDoc->setCode($provider->getAccountingCode($acc['bid'], 'accounting'));
$hesabdariDoc->setDate($params['date']);
$hesabdariDoc->setDes($params['description']);
$hesabdariDoc->setAmount($cheque->getAmount());
$entityManager->persist($hesabdariDoc);
// ایجاد سطرهای حسابداری جدید
$hesabdariRow1 = new HesabdariRow;
$hesabdariRow1->setDoc($hesabdariDoc);
$hesabdariRow1->setCheque($cheque);
$hesabdariRow1->setPerson($cheque->getPerson());
$hesabdariRow1->setYear($acc['year']);
$hesabdariRow1->setBs(0);
$hesabdariRow1->setRef($entityManager->getRepository(HesabdariTable::class)->findOneBy(['code' => 126]));
$hesabdariRow1->setBd($cheque->getAmount());
$hesabdariRow1->setBid($acc['bid']);
$hesabdariRow1->setCheque($cheque);
$hesabdariRow1->setDes('واگذاری چک شماره ' . $cheque->getNumber() . ' به ' . $cheque->getPerson()->getNikename());
$entityManager->persist($hesabdariRow1);
$hesabdariRow2 = new HesabdariRow;
$hesabdariRow2->setDoc($hesabdariDoc);
$hesabdariRow2->setCheque($cheque);
$hesabdariRow2->setYear($acc['year']);
$hesabdariRow2->setBs($cheque->getAmount());
$hesabdariRow2->setRef($entityManager->getRepository(HesabdariTable::class)->findOneBy(['code' => 125]));
$hesabdariRow2->setBd(0);
$hesabdariRow2->setBid($acc['bid']);
$hesabdariRow2->setCheque($cheque);
$hesabdariRow2->setDes('واگذاری چک شماره ' . $cheque->getNumber() . ' به ' . $cheque->getPerson()->getNikename());
$entityManager->persist($hesabdariRow2);
$entityManager->flush();
$log->insert(
'بانکداری',
'واگذاری چک شماره ' . $cheque->getNumber() . ' بانک ' . $cheque->getBankoncheque() . ' به ' . $cheque->getPerson()->getNikename(),
$this->getUser(),
$acc['bid']->getId(),
$hesabdariDoc
);
return $this->json(['result' => 'ok']);
}
#[Route('/api/cheque/output/get/{id}', name: 'app_cheque_output_get')]
public function app_cheque_output_get(string $id, Provider $provider, Request $request, Access $access, Log $log, EntityManagerInterface $entityManager, Jdate $jdate): JsonResponse
{
$acc = $access->hasRole('cheque');
if (!$acc)
throw $this->createAccessDeniedException();
$cheque = $entityManager->getRepository(Cheque::class)->findOneBy([
'bid' => $acc['bid'],
'id' => $id
]);
if (!$cheque)
throw $this->createNotFoundException('چک مورد نظر یافت نشد');
if ($cheque->getType() !== 'output')
throw $this->createAccessDeniedException('این چک واگذاری نشده است');
return $this->json(Explore::SerializeCheque($cheque));
}
#[Route('/api/cheque/pass/output/{id}', name: 'app_cheque_pass_output')]
public function app_cheque_pass_output(string $id, Provider $provider, Request $request, Access $access, Log $log, EntityManagerInterface $entityManager, Jdate $jdate): JsonResponse
{
$acc = $access->hasRole('cheque');
if (!$acc)
throw $this->createAccessDeniedException();
$params = [];
if ($content = $request->getContent()) {
$params = json_decode($content, true);
}
if (! array_key_exists('bank', $params) || ! array_key_exists('date', $params))
$this->createNotFoundException();
$cheque = $entityManager->getRepository(Cheque::class)->findOneBy([
'bid' => $acc['bid'],
'type' => 'output',
'id' => $id
]);
$bank = $entityManager->getRepository(BankAccount::class)->findOneBy([
'bid' => $acc['bid'],
'id' => $params['bank']
]);
if (!$cheque || !$bank)
throw $this->createNotFoundException();
if ($cheque->isLocked())
throw $this->createAccessDeniedException('cheque operation not permitted');
//edit cheque info
$cheque->setBank($bank);
$cheque->setStatus('وصول');
$cheque->setPayDate($params['date']);
$cheque->setLocked(true);
$entityManager->persist($cheque);
//create cheque document
$hesabdariDoc = new HesabdariDoc;
$hesabdariDoc->setBid($acc['bid']);
$hesabdariDoc->setSubmitter($this->getUser());
$hesabdariDoc->setYear($acc['year']);
$hesabdariDoc->setMoney($acc['money']);
$hesabdariDoc->setDateSubmit(time());
$hesabdariDoc->setDate($params['date']);
$hesabdariDoc->setType('pass_cheque');
$hesabdariDoc->setCode($provider->getAccountingCode($acc['bid'], 'accounting'));
$hesabdariDoc->setDes($params['des']);
$hesabdariDoc->setAmount($cheque->getAmount());
$entityManager->persist($hesabdariDoc);
//cheate hesabdari rows
$hesabdariRow1 = new HesabdariRow();
$hesabdariRow1->setDoc($hesabdariDoc);
$hesabdariRow1->setCheque($cheque);
$hesabdariRow1->setYear($acc['year']);
$hesabdariRow1->setBd($cheque->getAmount());
$hesabdariRow1->setRef($entityManager->getRepository(HesabdariTable::class)->findOneBy(['code' => 126]));
$hesabdariRow1->setBs(0);
$hesabdariRow1->setBid($acc['bid']);
$hesabdariRow1->setDes('وصول چک و برداشت از بانک');
$entityManager->persist($hesabdariRow1);
$hesabdariRow2 = new HesabdariRow();
$hesabdariRow2->setDoc($hesabdariDoc);
$hesabdariRow2->setCheque($cheque);
$hesabdariRow2->setBank($bank);
$hesabdariRow2->setYear($acc['year']);
$hesabdariRow2->setBd(0);
$hesabdariRow2->setRef($entityManager->getRepository(HesabdariTable::class)->findOneBy(['code' => 125]));
$hesabdariRow2->setBs($cheque->getAmount());
$hesabdariRow2->setBid($acc['bid']);
$hesabdariRow2->setDes('وصول چک و برداشت از بانک');
$entityManager->persist($hesabdariRow2);
$entityManager->flush();
$log->insert(
'حسابداری',
'ثبت چک وصول شماره ' . $cheque->getNumber() . ' و ثبت برداشت از بانک ' . $bank->getName(),
$this->getUser(),
$acc['bid']->getId(),
$hesabdariDoc
);
return $this->json([
'result' => 'ok'
]);
}
}

View file

@ -73,14 +73,23 @@ class PersonsController extends AbstractController
$types = $entityManager->getRepository(PersonType::class)->findAll();
$response = Explore::ExplorePerson($person, $types);
$rows = $entityManager->getRepository(HesabdariRow::class)->findBy([
'person' => $person
'person' => $person,
'bid' => $acc['bid']
]);
$bs = 0;
$bd = 0;
foreach ($rows as $row) {
if ($row->getDoc()->getMoney() == $acc['money']) {
$bs += $row->getBs();
$bd += $row->getBd();
try {
$doc = $row->getDoc();
if ($doc && $doc->getMoney() && $doc->getYear() &&
$doc->getMoney()->getId() == $acc['money']->getId() &&
$doc->getYear()->getId() == $acc['year']->getId()) {
$bs += (float) $row->getBs(); // بستانکار
$bd += (float) $row->getBd(); // بدهکار
}
} catch (\Exception $e) {
// در صورت بروز خطا، این ردیف را نادیده می‌گیریم و به ردیف بعدی می‌رویم
continue;
}
}
$response['bs'] = $bs;
@ -392,6 +401,7 @@ class PersonsController extends AbstractController
];
$rows = $entityManager->getRepository(HesabdariRow::class)->findBy([
'person' => $person,
'bid' => $acc['bid']
]);
$bs = 0;
$bd = 0;
@ -439,7 +449,8 @@ class PersonsController extends AbstractController
'mobile' => $person->getMobile()
];
$rows = $entityManager->getRepository(HesabdariRow::class)->findBy([
'person' => $person
'person' => $person,
'bid' => $acc['bid']
]);
$bs = 0;
$bd = 0;
@ -514,13 +525,15 @@ class PersonsController extends AbstractController
foreach ($persons as $person) {
$rows = $entityManager->getRepository(\App\Entity\HesabdariRow::class)->findBy([
'person' => $person,
'bid' => $acc['bid'],
'bid' => $acc['bid']
]);
$bs = 0; // بستانکار
$bd = 0; // بدهکار
foreach ($rows as $row) {
if ($row->getDoc()->getMoney()->getId() == $acc['money']->getId() &&
$row->getDoc()->getYear()->getId() == $acc['year']->getId()) {
$doc = $row->getDoc();
if ($doc && $doc->getMoney() && $doc->getYear() &&
$doc->getMoney()->getId() == $acc['money']->getId() &&
$doc->getYear()->getId() == $acc['year']->getId()) {
$bs += (float) $row->getBs(); // بستانکار
$bd += (float) $row->getBd(); // بدهکار
}
@ -585,7 +598,8 @@ class PersonsController extends AbstractController
$response = $provider->ArrayEntity2Array($persons, 0);
foreach ($persons as $key => $person) {
$rows = $entityManager->getRepository(HesabdariRow::class)->findBy([
'person' => $person
'person' => $person,
'bid' => $acc['bid']
]);
$bs = 0;
$bd = 0;
@ -618,7 +632,8 @@ class PersonsController extends AbstractController
$response = $provider->ArrayEntity2Array($persons, 0);
foreach ($persons as $key => $person) {
$rows = $entityManager->getRepository(HesabdariRow::class)->findBy([
'person' => $person
'person' => $person,
'bid' => $acc['bid']
]);
$bs = 0;
$bd = 0;
@ -672,7 +687,8 @@ class PersonsController extends AbstractController
$response = $provider->ArrayEntity2Array($persons, 0);
foreach ($persons as $key => $person) {
$rows = $entityManager->getRepository(HesabdariRow::class)->findBy([
'person' => $person
'person' => $person,
'bid' => $acc['bid']
]);
$bs = 0;
$bd = 0;
@ -717,7 +733,8 @@ class PersonsController extends AbstractController
$response = Explore::ExplorePersons($res, $entityManager->getRepository(PersonType::class)->findAll());
foreach ($res as $key => $person) {
$rows = $entityManager->getRepository(HesabdariRow::class)->findBy([
'person' => $person
'person' => $person,
'bid' => $acc['bid']
]);
$bs = 0;
$bd = 0;
@ -748,7 +765,8 @@ class PersonsController extends AbstractController
$response = $provider->ArrayEntity2Array($persons, 0);
foreach ($persons as $key => $person) {
$rows = $entityManager->getRepository(HesabdariRow::class)->findBy([
'person' => $person
'person' => $person,
'bid' => $acc['bid']
]);
$bs = 0;
$bd = 0;
@ -1429,11 +1447,17 @@ class PersonsController extends AbstractController
if (!$person)
throw $this->createNotFoundException();
//check accounting docs
$docs = $entityManager->getRepository(HesabdariRow::class)->findby(['bid' => $acc['bid'], 'person' => $person]);
if (count($docs) > 0)
$rows = $entityManager->getRepository(HesabdariRow::class)->findBy([
'person' => $person,
'bid' => $acc['bid']
]);
if (count($rows) > 0)
return $this->json(['result' => 2]);
//check for storeroom docs
$storeDocs = $entityManager->getRepository(StoreroomTicket::class)->findby(['bid' => $acc['bid'], 'Person' => $person]);
$storeDocs = $entityManager->getRepository(StoreroomTicket::class)->findBy([
'bid' => $acc['bid'],
'Person' => $person
]);
if (count($storeDocs) > 0)
return $this->json(['result' => 2]);
//check in repservice
@ -1499,14 +1523,20 @@ class PersonsController extends AbstractController
}
// بررسی اسناد حسابداری
$docs = $entityManager->getRepository(HesabdariRow::class)->findBy(['bid' => $acc['bid'], 'person' => $person]);
if (count($docs) > 0) {
$rows = $entityManager->getRepository(HesabdariRow::class)->findBy([
'person' => $person,
'bid' => $acc['bid']
]);
if (count($rows) > 0) {
$hasIgnored = true;
continue;
}
// بررسی اسناد انبار
$storeDocs = $entityManager->getRepository(StoreroomTicket::class)->findBy(['bid' => $acc['bid'], 'Person' => $person]);
$storeDocs = $entityManager->getRepository(StoreroomTicket::class)->findBy([
'bid' => $acc['bid'],
'Person' => $person
]);
if (count($storeDocs) > 0) {
$hasIgnored = true;
continue;

View file

@ -74,6 +74,15 @@ class Cheque
#[ORM\Column(nullable: true)]
private ?bool $rejected = null;
#[ORM\ManyToOne]
private ?Money $money = null;
#[ORM\Column(nullable: true)]
private ?bool $transfered = null;
#[ORM\Column(length: 25, nullable: true)]
private ?string $transferDate = null;
public function __construct()
{
$this->hesabdariRows = new ArrayCollection();
@ -330,4 +339,40 @@ class Cheque
return $this;
}
public function getMoney(): ?Money
{
return $this->money;
}
public function setMoney(?Money $money): static
{
$this->money = $money;
return $this;
}
public function isTransfered(): ?bool
{
return $this->transfered;
}
public function setTransfered(?bool $transfered): static
{
$this->transfered = $transfered;
return $this;
}
public function getTransferDate(): ?string
{
return $this->transferDate;
}
public function setTransferDate(?string $transferDate): static
{
$this->transferDate = $transferDate;
return $this;
}
}

View file

@ -454,7 +454,14 @@ class Explore
'date' => $cheque->getDate(),
'locked' => $cheque->isLocked(),
'rejected' => $cheque->isRejected(),
'label' => $label
'label' => $label,
'bankoncheque' => $cheque->getBankoncheque(),
'sayadNumber' => $cheque->getSayadNum(),
'dueDate' => $cheque->getPayDate(),
'description' => $cheque->getDes(),
'dateSubmit' => $cheque->getDateSubmit(),
'dateStamp' => $cheque->getDateStamp(),
];
}

View file

@ -4,9 +4,11 @@
v-bind="$attrs"
type="text"
:rules="combinedRules"
:error-messages="errorMessages"
@keypress="restrictToNumbers"
dir="ltr"
dense
hide-details="auto"
/>
</template>
@ -28,14 +30,15 @@ export default {
data() {
return {
inputValue: ''
inputValue: '',
errorMessages: []
}
},
computed: {
combinedRules() {
return [
v => !v || /^\d+$/.test(v.replace(/[^0-9]/g, '')) || 'فقط عدد انگلیسی مجاز است',
v => !v || /^\d+$/.test(v.replace(/[^0-9]/g, '')) || this.$t('numberinput.invalid_number'),
...this.rules
]
}
@ -55,11 +58,17 @@ export default {
},
inputValue(newVal) {
if (newVal === '' || newVal === null || newVal === undefined) {
this.$emit('update:modelValue', 0) // وقتی خالی است، صفر ارسال شود
this.$emit('update:modelValue', 0)
this.errorMessages = []
} else {
const cleaned = String(newVal).replace(/[^0-9]/g, '')
const numericValue = cleaned ? Number(cleaned) : 0
this.$emit('update:modelValue', numericValue)
if (/^\d+$/.test(cleaned)) {
const numericValue = cleaned ? Number(cleaned) : 0
this.$emit('update:modelValue', numericValue)
this.errorMessages = []
} else {
this.errorMessages = [this.$t('numberinput.invalid_number')]
}
}
}
},

View file

@ -6,8 +6,8 @@
v-bind="props"
v-model="displayValue"
variant="outlined"
hide-details
density="compact"
:error-messages="errorMessages"
:rules="combinedRules"
:label="label"
class=""
prepend-inner-icon="mdi-account"
@ -15,6 +15,7 @@
@click:clear="clearSelection"
:loading="loading"
@keydown.enter="handleEnter"
hide-details="auto"
>
<template v-slot:append-inner>
<v-icon>{{ menu ? 'mdi-chevron-up' : 'mdi-chevron-down' }}</v-icon>
@ -338,6 +339,10 @@ export default {
returnObject: {
type: Boolean,
default: false
},
rules: {
type: Array,
default: () => []
}
},
data() {
@ -360,6 +365,7 @@ export default {
text: '',
color: 'success'
},
errorMessages: [],
newPerson: {
nikename: '',
name: '',
@ -419,6 +425,12 @@ export default {
return ['شماره موبایل دوم باید با 09 شروع شود و 11 رقم باشد'];
}
return [];
},
combinedRules() {
return [
v => !!v || 'انتخاب شخص الزامی است',
...this.rules
]
}
},
watch: {
@ -583,11 +595,13 @@ export default {
this.searchQuery = item.nikename;
this.$emit('update:modelValue', this.returnObject ? item : item.id);
this.menu = false;
this.errorMessages = [];
},
clearSelection() {
this.selectedItem = null;
this.searchQuery = '';
this.$emit('update:modelValue', null);
this.errorMessages = ['انتخاب شخص الزامی است'];
},
handleEnter() {
if (!this.loading && this.filteredItems.length === 0) {

View file

@ -56,6 +56,7 @@ const fa_lang = {
fetch_data: "خطا در دریافت داده‌ها: ",
initial_load: "خطا در بارگذاری اولیه: ",
title: "خطا",
connection_error: "اتصال با سرویس دهنده برقرار نشد. لطفا اتصال اینترنت خود را بررسی نمایید."
},
"dashboard": {
"costs": {
@ -266,6 +267,11 @@ const fa_lang = {
wallet: "کیف پول",
deposit: "موجودی",
count: "تعداد",
site_name: "حسابیکس",
site_slogan: "حسابیکس سامانه جامع مدیریت کسب‌و‌کار",
dev_mode_message: "شما در حالت توسعه هستید و به آدرس زیر متصل می‌شوید:",
invalid_server_response: "پاسخ نامعتبر از سرور",
fetch_data_error: "خطا در گرفتن داده از {url}"
},
dialog: {
download: 'دانلود',
@ -398,7 +404,30 @@ const fa_lang = {
search_txt: "جست و جو ...",
prev_page: "صفحه قبل",
next_page: "صفحه بعد",
change_password: "تغییر کلمه عبور",
change_password: {
title: "تغییر کلمه عبور",
new_password: "کلمه عبور جدید",
confirm_password: "تکرار کلمه عبور",
notify_user: "اطلاع رسانی به کاربر",
save: "ذخیره",
cancel: "لغو",
close: "بستن",
validation: {
required: "کلمه عبور الزامی است",
min_length: "کلمه عبور باید حداقل ۶ کاراکتر باشد",
confirm_required: "تکرار کلمه عبور الزامی است",
match: "کلمه عبور و تکرار آن باید یکسان باشند"
},
error: {
title: "خطا",
message: "لطفاً تمام فیلدها را به درستی پر کنید",
change_error: "خطا در تغییر کلمه عبور"
},
success: {
title: "موفقیت",
message: "کلمه عبور با موفقیت تغییر یافت"
}
},
settings: "تنظیمات",
sms: "پیامک",
system: "سیستم",
@ -632,7 +661,11 @@ const fa_lang = {
"income": "درآمد",
"sell_receive": "دریافت فاکتور فروش",
"buy_send": "پرداخت فاکتور فروش",
"detail": "تفضیل"
"detail": "تفضیل",
"reject_cheque": "برگشت چک",
"modify_cheque": "ثبت چک",
"modify_cheque_output": "دریافت چک",
"pass_cheque": "واگذاری چک"
},
dashboard: {
admin_area: "ناحیه مدیریت",
@ -747,6 +780,23 @@ const fa_lang = {
credit: "بستانکار",
quantity: "تعداد"
}
}
},
editor: {
bold: "پررنگ",
italic: "ایتالیک",
bullet_list: "لیست نقطه‌ای",
ordered_list: "لیست شماره‌دار",
right_align: "راست‌چین",
center_align: "وسط‌چین",
left_align: "چپ‌چین"
},
datepicker: {
label: "تاریخ",
invalid_date: "تاریخ نامعتبر است",
fetch_error: "خطا در دریافت اطلاعات سال:"
},
numberinput: {
invalid_number: "فقط عدد انگلیسی مجاز است"
},
};
export default fa_lang

View file

@ -677,6 +677,12 @@ const router = createRouter({
component: () =>
import('../views/acc/rfsell/viewInvoice.vue'),
},
{
path: 'wizard/home',
name: 'wizard_home',
component: () =>
import('../views/wizard/home.vue'),
},
{
path: 'plugin-center/list',
name: 'plugin_center_list',

View file

@ -860,9 +860,13 @@ export default {
<span class="d-none d-sm-flex">{{ business.name }}</span>
</v-app-bar-title>
<v-spacer></v-spacer>
<v-btn class="d-none d-sm-flex" stacked @click="showShortcutsDialog = true; isEditingShortcuts = false">
<v-icon>mdi-help-circle</v-icon>
<v-tooltip text="جادوگر" location="bottom">
<template v-slot:activator="{ props }">
<v-btn class="d-none d-sm-flex" stacked v-bind="props" to="/acc/wizard/home">
<v-icon>mdi-wizard-hat</v-icon>
</v-btn>
</template>
</v-tooltip>
<CalculatorButton />
<SecretDialog />
<v-dialog v-model="showShortcutsDialog" max-width="800" scrollable>

View file

@ -17,7 +17,6 @@
<v-icon icon="mdi-message-text" :color="form.sendSms ? 'primary' : 'grey'"></v-icon>
</template>
</v-switch>
</div>
</template>
</v-tooltip>
@ -31,7 +30,7 @@
<v-container>
<v-row>
<v-col cols="12">
<v-form @submit.prevent="submitForm">
<v-form ref="form" @submit.prevent="submitForm" v-model="valid">
<v-row>
<v-col cols="12" md="6">
<Hpersonsearch v-model="form.personId" label="شخص" :rules="[v => !!v || 'شخص الزامی است']" required>
@ -48,8 +47,8 @@
</v-col>
<v-col cols="12" md="6">
<v-text-field v-model="form.amount" label="مبلغ" type="number" :rules="[v => !!v || 'مبلغ الزامی است']"
required></v-text-field>
<Hnumberinput v-model="form.amount" label="مبلغ" :rules="[v => !!v || 'مبلغ الزامی است']"
required></Hnumberinput>
</v-col>
<v-col cols="12" md="6">
@ -75,15 +74,18 @@
<script>
import Hdatepicker from '@/components/forms/Hdatepicker.vue'
import Hpersonsearch from '@/components/forms/Hpersonsearch.vue'
import Hnumberinput from '@/components/forms/Hnumberinput.vue'
import axios from 'axios'
export default {
components: {
Hdatepicker,
Hpersonsearch
Hpersonsearch,
Hnumberinput
},
data() {
return {
loading: false,
valid: false,
form: {
chequeNumber: '',
bankoncheque: '',
@ -99,6 +101,12 @@ export default {
methods: {
async submitForm() {
const { valid } = await this.$refs.form.validate()
if (!valid) {
return
}
try {
this.loading = true
// ذخیره تنظیمات در localStorage
@ -111,7 +119,6 @@ export default {
date: this.form.dueDate,
person: { code: this.form.personId },
sayadNumber: this.form.sayadNumber,
date: this.form.dueDate,
description: this.form.description,
bankoncheque: this.form.bankoncheque,
sendSms: this.form.sendSms
@ -124,7 +131,6 @@ export default {
date: this.form.dueDate,
person: { code: this.form.personId },
sayadNumber: this.form.sayadNumber,
date: this.form.dueDate,
description: this.form.description,
bankoncheque: this.form.bankoncheque,
sendSms: this.form.sendSms
@ -148,7 +154,7 @@ export default {
chequeNumber: chequeData.number,
bankoncheque: chequeData.bankoncheque,
amount: chequeData.amount,
dueDate: chequeData.dueDate,
dueDate: chequeData.date,
description: chequeData.description,
sayadNumber: chequeData.sayadNumber,
personId: chequeData.person.id,

View file

@ -77,13 +77,13 @@
</v-btn>
</template>
<v-list>
<v-list-item v-if="!item.rejected && item.status !== 'پاس شده'" @click="$router.push(`/acc/cheque/input/${item.id}`)">
<v-list-item v-if="!item.locked" @click="$router.push(`/acc/cheque/input/${item.id}`)">
<template v-slot:prepend>
<v-icon color="primary">mdi-pencil</v-icon>
</template>
<v-list-item-title>ویرایش چک</v-list-item-title>
</v-list-item>
<v-list-item v-if="!item.locked && !item.rejected" @click="deleteCheque(item)">
<v-list-item @click="deleteCheque(item)">
<template v-slot:prepend>
<v-icon color="error">mdi-delete</v-icon>
</template>
@ -93,7 +93,7 @@
<template v-slot:prepend>
<v-icon color="success">mdi-bank-check</v-icon>
</template>
<v-list-item-title>پاس کردن چک</v-list-item-title>
<v-list-item-title>وصول کردن چک</v-list-item-title>
</v-list-item>
<v-list-item v-if="item.rejected" @click="unrejectCheque(item)">
<template v-slot:prepend>
@ -101,13 +101,7 @@
</template>
<v-list-item-title>رفع برگشت</v-list-item-title>
</v-list-item>
<v-list-item v-else-if="!item.locked" @click="rejectCheque(item)">
<template v-slot:prepend>
<v-icon color="error">mdi-arrow-left</v-icon>
</template>
<v-list-item-title>برگشت چک</v-list-item-title>
</v-list-item>
<v-list-item v-if="!item.locked && !item.rejected" @click="$router.push(`/acc/cheque/transfer/${item.id}`)">
<v-list-item v-else-if="!item.locked" @click="$router.push(`/acc/cheque/transfer/${item.id}`)">
<template v-slot:prepend>
<v-icon color="info">mdi-account-arrow-right</v-icon>
</template>
@ -141,13 +135,13 @@
</v-btn>
</template>
<v-list>
<v-list-item v-if="!item.rejected && item.status !== 'پاس شده'" @click="$router.push(`/acc/cheque/input/${item.id}`)">
<v-list-item v-if="item.locked == false" @click="$router.push(`/acc/cheque/output/${item.id}`)">
<template v-slot:prepend>
<v-icon color="primary">mdi-pencil</v-icon>
</template>
<v-list-item-title>ویرایش چک</v-list-item-title>
</v-list-item>
<v-list-item v-if="!item.locked && !item.rejected" @click="deleteCheque(item)">
<v-list-item @click="deleteCheque(item)">
<template v-slot:prepend>
<v-icon color="error">mdi-delete</v-icon>
</template>
@ -157,25 +151,7 @@
<template v-slot:prepend>
<v-icon color="success">mdi-bank-check</v-icon>
</template>
<v-list-item-title>پاس کردن چک</v-list-item-title>
</v-list-item>
<v-list-item v-if="item.rejected" @click="unrejectCheque(item)">
<template v-slot:prepend>
<v-icon color="success">mdi-arrow-right</v-icon>
</template>
<v-list-item-title>رفع برگشت</v-list-item-title>
</v-list-item>
<v-list-item v-else-if="!item.locked" @click="rejectCheque(item)">
<template v-slot:prepend>
<v-icon color="error">mdi-arrow-left</v-icon>
</template>
<v-list-item-title>برگشت چک</v-list-item-title>
</v-list-item>
<v-list-item v-if="!item.locked && !item.rejected" @click="$router.push(`/acc/cheque/transfer/${item.id}`)">
<template v-slot:prepend>
<v-icon color="info">mdi-account-arrow-right</v-icon>
</template>
<v-list-item-title>واگذاری چک</v-list-item-title>
<v-list-item-title>وصول کردن چک</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
@ -191,10 +167,10 @@
</v-window-item>
</v-window>
<!-- دیالوگ پاس کردن چک -->
<!-- دیالوگ وصول کردن چک -->
<v-dialog v-model="passDialog" max-width="500px">
<v-card>
<v-toolbar color="toolbar" title="پاس کردن چک">
<v-toolbar color="toolbar" title="وصول کردن چک">
<template v-slot:append>
<v-tooltip text="ثبت" location="bottom">
<template v-slot:activator="{ props }">
@ -344,14 +320,14 @@ export default {
{ title: "شماره", key: "number", width: "100" },
{ title: "کد صیاد", key: "sayadNum", width: "120" },
{ title: "مبلغ(ریال)", key: "amount", width: "140" },
{ title: "تاریخ", key: "datePay", width: "150" },
{ title: "تاریخ", key: "date", width: "150" },
{ title: "پرداخت کننده", key: "person.nikename", width: "150" },
{ title: "بانک", key: "chequeBank", width: "150" },
{ title: "وضعیت", key: "status", width: "150", sortable: true },
{ title: "تاریخ وصول", key: "date", width: "150" },
{ title: "تاریخ وصول", key: "datePay", width: "150" },
{ title: "توضیحات", key: "des", width: "150" },
],
// متغیرهای مربوط به پاس کردن چک
// متغیرهای مربوط به وصول کردن چک
passDialog: false,
passLoading: false,
passDate: '',
@ -381,9 +357,9 @@ export default {
methods: {
getStatusColor(status) {
switch (status) {
case 'پاس شده':
case 'وصول شده':
return 'success';
case 'پاس نشده':
case 'وصول نشده':
return 'grey';
case 'برگشت خورده':
return 'error';
@ -456,7 +432,7 @@ export default {
this.loading = false;
}
},
// متدهای مربوط به پاس کردن چک
// متدهای مربوط به وصول کردن چک
async openPassDialog(id) {
this.selectedChequeId = id;
this.passDialog = true;
@ -497,11 +473,11 @@ export default {
try {
this.passLoading = true;
await axios.post(`/api/cheque/pass/${this.selectedChequeId}`, {
await axios.post(`/api/cheque/pass/${this.tab}/${this.selectedChequeId}`, {
bank: this.bankSelected,
date: this.passDate,
des: this.passDescription,
sendSms: this.sendPassSms
sendSms: this.sendPassSms,
});
this.snackbar = {

View file

@ -1,126 +1,166 @@
<template>
<v-card>
<v-card-title class="text-h5">
{{ $route.params.id ? 'ویرایش چک دریافتی' : 'ثبت چک دریافتی' }}
</v-card-title>
<v-card-text>
<v-form @submit.prevent="submitForm">
<v-toolbar color="toolbar" :title="$route.params.id ? 'ویرایش واگذاری چک' : 'ثبت واگذاری چک'">
<template v-slot:prepend>
<v-tooltip :text="$t('dialog.back')" location="bottom">
<template v-slot:activator="{ props }">
<v-btn v-bind="props" @click="$router.back()" class="d-none d-sm-flex" variant="text"
icon="mdi-arrow-right" />
</template>
</v-tooltip>
</template>
<template v-slot:append>
<v-tooltip :text="$route.params.id ? 'ویرایش' : 'ثبت'" location="bottom">
<template v-slot:activator="{ props }">
<v-btn v-bind="props" color="success" @click="submitForm" :loading="loading" icon="mdi-content-save" />
</template>
</v-tooltip>
</template>
</v-toolbar>
<v-container>
<v-row>
<v-col cols="12">
<v-form ref="form" @submit.prevent="submitForm">
<v-row>
<v-col cols="12" md="6">
<v-text-field
v-model="form.chequeNumber"
label="شماره چک"
:rules="[v => !!v || 'شماره چک الزامی است']"
required
></v-text-field>
<Hpersonsearch v-model="form.personId" label="شخص گیرنده" :rules="[v => !!v || 'شخص گیرنده الزامی است']" required>
</Hpersonsearch>
</v-col>
<v-col cols="12" md="6">
<v-text-field v-model="form.chequeNumber" label="شماره چک" :rules="[v => !!v || 'شماره چک الزامی است']"
required></v-text-field>
</v-col>
<v-col cols="12" md="6">
<v-text-field
v-model="form.bankName"
label="نام بانک"
:rules="[v => !!v || 'نام بانک الزامی است']"
required
></v-text-field>
<v-text-field v-model="form.bankoncheque" label="نام بانک" :rules="[v => !!v || 'نام بانک الزامی است']"
required></v-text-field>
</v-col>
<v-col cols="12" md="6">
<v-text-field
v-model="form.amount"
label="مبلغ"
type="number"
:rules="[v => !!v || 'مبلغ الزامی است']"
required
></v-text-field>
<Hnumberinput v-model="form.amount" label="مبلغ" :rules="[v => !!v || 'مبلغ الزامی است']"
required></Hnumberinput>
</v-col>
<v-col cols="12" md="6">
<v-text-field
v-model="form.dueDate"
label="تاریخ سررسید"
type="date"
:rules="[v => !!v || 'تاریخ سررسید الزامی است']"
required
></v-text-field>
<v-text-field v-model="form.sayadNumber" label="شماره صیاد" :rules="[v => !!v || 'شماره صیاد الزامی است']"
required></v-text-field>
</v-col>
<v-col cols="12" md="6">
<Hdatepicker v-model="form.dueDate" label="تاریخ سررسید" :rules="[v => !!v || 'تاریخ سررسید الزامی است']"
required format="YYYY/MM/DD"></Hdatepicker>
</v-col>
<v-col cols="12">
<v-textarea
v-model="form.description"
label="توضیحات"
rows="3"
></v-textarea>
<v-textarea v-model="form.description" label="توضیحات" rows="3"></v-textarea>
</v-col>
</v-row>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="error"
variant="text"
@click="$router.back()"
>
انصراف
</v-btn>
<v-btn
color="primary"
type="submit"
:loading="loading"
>
{{ $route.params.id ? 'ویرایش' : 'ثبت' }}
</v-btn>
</v-card-actions>
</v-form>
</v-card-text>
</v-card>
</template>
</v-col>
</v-row>
</v-container>
</template>
<script>
export default {
data() {
return {
loading: false,
form: {
chequeNumber: '',
bankName: '',
amount: '',
dueDate: '',
description: ''
}
<script>
import Hdatepicker from '@/components/forms/Hdatepicker.vue'
import Hpersonsearch from '@/components/forms/Hpersonsearch.vue'
import Hnumberinput from '@/components/forms/Hnumberinput.vue'
import axios from 'axios'
export default {
components: {
Hdatepicker,
Hpersonsearch,
Hnumberinput
},
data() {
return {
loading: false,
form: {
chequeNumber: '',
bankoncheque: '',
amount: '',
dueDate: '',
description: '',
sayadNumber: '',
personId: null
}
},
}
},
methods: {
async submitForm() {
try {
this.loading = true
if (this.$route.params.id) {
// ویرایش چک
await this.$axios.put(`/api/cheques/${this.$route.params.id}`, this.form)
} else {
// ثبت چک جدید
await this.$axios.post('/api/cheques', this.form)
}
this.$router.push('/acc/cheque/list')
} catch (error) {
console.error(error)
} finally {
this.loading = false
}
methods: {
async submitForm() {
const { valid } = await this.$refs.form.validate()
if (!valid) {
await Swal.fire({
text: 'لطفا تمام فیلدهای الزامی را پر کنید',
icon: 'warning',
confirmButtonText: 'قبول'
})
return
}
},
async created() {
if (this.$route.params.id) {
try {
const response = await this.$axios.get(`/api/cheques/${this.$route.params.id}`)
this.form = response.data
} catch (error) {
console.error(error)
try {
this.loading = true
if (this.$route.params.id) {
// ویرایش واگذاری چک
await axios.put(`/api/cheque/modify/output/${this.$route.params.id}`, {
number: this.form.chequeNumber,
amount: this.form.amount,
date: this.form.dueDate,
person: { code: this.form.personId },
sayadNumber: this.form.sayadNumber,
description: this.form.description,
bankoncheque: this.form.bankoncheque
})
} else {
// ثبت واگذاری چک جدید
await axios.post('/api/cheque/modify/output', {
number: this.form.chequeNumber,
amount: this.form.amount,
date: this.form.dueDate,
person: { code: this.form.personId },
sayadNumber: this.form.sayadNumber,
description: this.form.description,
bankoncheque: this.form.bankoncheque
})
}
this.$router.push('/acc/cheque/list')
} catch (error) {
console.error(error)
await Swal.fire({
text: 'خطا در ثبت/ویرایش چک',
icon: 'error',
confirmButtonText: 'قبول'
})
} finally {
this.loading = false
}
}
},
async created() {
if (this.$route.params.id) {
try {
const response = await axios.get(`/api/cheque/output/get/${this.$route.params.id}`)
const chequeData = response.data
this.form = {
chequeNumber: chequeData.number,
bankoncheque: chequeData.bankoncheque,
amount: chequeData.amount,
dueDate: chequeData.date,
description: chequeData.description,
sayadNumber: chequeData.sayadNumber,
personId: chequeData.person.id
}
} catch (error) {
await Swal.fire({
text: 'خطا در دریافت اطلاعات چک',
icon: 'error',
confirmButtonText: 'قبول'
})
this.$router.push('/acc/cheque/list')
}
}
}
</script>
}
</script>

View file

@ -60,8 +60,15 @@
<v-form @submit.prevent="submitForm" class="mt-4">
<v-row>
<v-col cols="12">
<v-select v-model="selectedPerson" :items="persons" item-title="name" item-value="id"
label="شخص گیرنده" :rules="[v => !!v || 'انتخاب شخص گیرنده الزامی است']" required />
<v-switch
v-model="sendSms"
label="ارسال پیامک به گیرنده"
color="primary"
hide-details
></v-switch>
</v-col>
<v-col cols="12">
<Hpersonsearch v-model="selectedPerson" label="شخص گیرنده" :rules="[v => !!v || 'انتخاب شخص گیرنده الزامی است']" required />
</v-col>
<v-col cols="12">
@ -91,17 +98,20 @@
<script>
import axios from "axios";
import Hdatepicker from '@/components/forms/Hdatepicker.vue';
import Hpersonsearch from '@/components/forms/Hpersonsearch.vue';
export default {
name: "cheque-transfer",
components: {
Hdatepicker
Hdatepicker,
Hpersonsearch
},
data: () => ({
loading: false,
selectedPerson: null,
transferDate: '',
description: '',
sendSms: false,
persons: [],
year: {
start: '',
@ -152,6 +162,10 @@ export default {
},
chequeBank: chequeResponse.data.bankoncheque
};
// Load SMS notification preference from localStorage
const smsPreference = localStorage.getItem('chequeTransferSmsNotification');
this.sendSms = smsPreference === 'true';
} catch (error) {
console.error('خطا در بارگذاری اطلاعات:', error);
this.snackbar = {
@ -175,10 +189,14 @@ export default {
try {
this.loading = true;
// Save SMS notification preference to localStorage
localStorage.setItem('chequeTransferSmsNotification', this.sendSms);
await axios.post(`/api/cheque/transfer/${this.$route.params.id}`, {
personId: this.selectedPerson,
date: this.transferDate,
description: this.description
description: this.description,
sendSms: this.sendSms
});
this.snackbar = {

View file

@ -1,193 +0,0 @@
<script lang="ts">
import { defineComponent, ref } from 'vue'
import axios from 'axios'
import Swal from 'sweetalert2'
import Hdatepicker from '@/components/forms/Hdatepicker.vue'
export default defineComponent({
name: 'PassCheck',
components: {
Hdatepicker
},
props: {
id: {
type: Number,
required: true
},
windowsState: {
type: Object,
required: false,
default: () => ({})
}
},
setup(props) {
const dialog = ref(false)
const loading = ref(false)
const banks = ref([])
const bankSelected = ref(null)
const des = ref('')
const passDate = ref('')
const year = ref({
start: '',
end: '',
now: ''
})
const loadData = async () => {
try {
loading.value = true
const [banksResponse, yearResponse] = await Promise.all([
axios.post('/api/bank/list'),
axios.post('/api/year/get')
])
banks.value = banksResponse.data
year.value = yearResponse.data
passDate.value = yearResponse.data.now
} catch (error) {
console.error('خطا در بارگذاری اطلاعات:', error)
} finally {
loading.value = false
}
}
const openDialog = () => {
dialog.value = true
loadData()
}
const closeDialog = () => {
dialog.value = false
bankSelected.value = null
des.value = ''
}
const save = async () => {
if (!bankSelected.value) {
await Swal.fire({
text: 'بانک انتخاب نشده است',
icon: 'error',
confirmButtonText: 'قبول'
})
return
}
try {
loading.value = true
await axios.post(`/api/cheque/pass/${props.id}`, {
bank: bankSelected.value,
date: passDate.value,
des: des.value
})
await Swal.fire({
text: 'ثبت وصول چک با موفقیت ثبت شد.',
icon: 'success',
confirmButtonText: 'قبول'
})
if (props.windowsState) {
props.windowsState.submited = true
}
closeDialog()
} catch (error) {
console.error('خطا در ثبت اطلاعات:', error)
await Swal.fire({
text: 'خطا در ثبت اطلاعات',
icon: 'error',
confirmButtonText: 'قبول'
})
} finally {
loading.value = false
}
}
return {
dialog,
loading,
banks,
bankSelected,
des,
passDate,
year,
save,
openDialog,
closeDialog
}
},
methods: {
openDialog() {
this.dialog = true
this.loadData()
},
closeDialog() {
this.dialog = false
this.bankSelected = null
this.des = ''
}
}
})
</script>
<template>
<v-dialog v-model="dialog" max-width="500px" @click:outside="closeDialog">
<v-card>
<v-toolbar color="toolbar" title="پاس کردن چک">
<template v-slot:append>
<v-tooltip text="ثبت" location="bottom">
<template v-slot:activator="{ props }">
<v-btn v-bind="props" color="success" :loading="loading" @click="save" icon="mdi-content-save" />
</template>
</v-tooltip>
<v-tooltip text="بستن" location="bottom">
<template v-slot:activator="{ props }">
<v-btn v-bind="props" icon="mdi-close" variant="text" @click="closeDialog" />
</template>
</v-tooltip>
</template>
</v-toolbar>
<v-card-text class="pt-4">
<v-form @submit.prevent="save">
<v-row>
<v-col cols="12">
<Hdatepicker
v-model="passDate"
label="تاریخ"
:min="year.start"
:max="year.end"
required
/>
</v-col>
<v-col cols="12">
<v-select
v-model="bankSelected"
:items="banks"
item-title="name"
item-value="id"
label="بانک"
:rules="[v => !!v || 'انتخاب بانک الزامی است']"
required
/>
</v-col>
<v-col cols="12">
<v-text-field
v-model="des"
label="توضیحات"
variant="outlined"
/>
</v-col>
</v-row>
</v-form>
</v-card-text>
</v-card>
</v-dialog>
</template>
<style scoped>
.bg-primary-light {
background-color: var(--v-primary-lighten1);
}
</style>

View file

@ -373,6 +373,10 @@ export default {
income: '/acc/accounting/view/',
sell_receive: '/acc/accounting/view/',
buy_send: '/acc/accounting/view/',
reject_cheque: '/acc/accounting/view/',
modify_cheque: '/acc/accounting/view/',
modify_cheque_output: '/acc/accounting/view/',
pass_cheque: '/acc/accounting/view/',
};
return routes[type] + code;
},
@ -388,6 +392,10 @@ export default {
income: this.$t('pages.person_card.income'),
sell_receive: this.$t('pages.person_card.sell_receive'),
buy_send: this.$t('pages.person_card.buy_send'),
reject_cheque: this.$t('pages.person_card.reject_cheque'),
modify_cheque: this.$t('pages.person_card.modify_cheque'),
pass_cheque: this.$t('pages.person_card.pass_cheque'),
modify_cheque_output: this.$t('pages.person_card.modify_cheque_output'),
};
return labels[type] || type;
},

View file

@ -0,0 +1,133 @@
<template>
<v-toolbar title="جادوگر">
<template v-slot:prepend>
<v-tooltip :text="$t('dialog.back')" location="bottom">
<template v-slot:activator="{ props }">
<v-btn v-bind="props" @click="$router.back()" class="d-none d-sm-flex" variant="text"
icon="mdi-arrow-right" />
</template>
</v-tooltip>
</template>
<v-spacer></v-spacer>
</v-toolbar>
<v-container class="mt-8 px-2">
<v-row justify="center" class="wizard-content">
<v-col cols="12" md="10">
<v-card class="elevation-0 main-card">
<v-card-title class="text-h4 text-center mb-4">
<v-icon color="primary" size="40" class="mr-2">mdi-wizard-hat</v-icon>
جادوگر هوش مصنوعی
</v-card-title>
<v-card-text class="text-body-1 text-center">
<p class="mb-4">
به زودی با جادوگر هوش مصنوعی آشنا خواهید شد! این ابزار قدرتمند به شما امکان میدهد تا با استفاده از هوش مصنوعی، ماژولهای جدید را به صورت پویا به نرمافزار اضافه کنید. دوران انحصار نرمافزارهای حسابداری به پایان رسیده است و شما میتوانید نرمافزار خود را بهروز کرده و آن را با نیازهای خاص کسبوکار خود تطبیق دهید، بدون نیاز به انتظار برای بهروزرسانیهای طولانی مدت یا پرداخت هزینههای گزاف برای سفارشیسازی.
</p>
</v-card-text>
<v-row class="mt-4">
<v-col cols="12" md="4">
<v-card class="elevation-0 pa-4 text-center feature-card">
<v-icon color="success" size="40" class="mb-2">mdi-robot</v-icon>
<h3 class="text-h6 mb-2">هوش مصنوعی پیشرفته</h3>
<p class="text-body-2">استفاده از آخرین تکنولوژیهای هوش مصنوعی برای ایجاد ماژولهای سفارشی</p>
</v-card>
</v-col>
<v-col cols="12" md="4">
<v-card class="elevation-0 pa-4 text-center feature-card">
<v-icon color="info" size="40" class="mb-2">mdi-puzzle</v-icon>
<h3 class="text-h6 mb-2">ماژولهای پویا</h3>
<p class="text-body-2">ایجاد و اضافه کردن ماژولهای جدید بدون نیاز به کدنویسی</p>
</v-card>
</v-col>
<v-col cols="12" md="4">
<v-card class="elevation-0 pa-4 text-center feature-card">
<v-icon color="warning" size="40" class="mb-2">mdi-lightning-bolt</v-icon>
<h3 class="text-h6 mb-2">سرعت بالا</h3>
<p class="text-body-2">توسعه سریع و کارآمد با استفاده از ابزارهای هوشمند</p>
</v-card>
</v-col>
</v-row>
<v-card-actions class="justify-center mt-6">
<v-btn color="primary" size="large" prepend-icon="mdi-clock-outline" disabled>
به زودی...
</v-btn>
</v-card-actions>
</v-card>
</v-col>
</v-row>
</v-container>
</template>
<script>
export default {
name: 'WizardHome',
data() {
return {
}
},
methods: {
}
}
</script>
<style scoped>
.fixed-toolbar {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 2000;
background-color: #ffffff !important;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1) !important;
}
.wizard-content {
position: relative;
z-index: 1;
}
.main-card {
background-color: #ffffff !important;
border-radius: 16px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05) !important;
}
.feature-card {
background-color: #f8f9fa !important;
border-radius: 12px;
transition: all 0.3s ease;
}
.feature-card:hover {
background-color: #ffffff !important;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1) !important;
transform: translateY(-4px);
}
.v-icon {
transition: transform 0.3s ease;
}
.feature-card:hover .v-icon {
transform: scale(1.1);
}
.v-card-title {
color: #2c3e50 !important;
}
.v-card-text {
color: #34495e !important;
}
.text-body-2 {
color: #7f8c8d !important;
}
</style>