diff --git a/hesabixCore/composer.json b/hesabixCore/composer.json index 0bc6e37..a2c5c6b 100644 --- a/hesabixCore/composer.json +++ b/hesabixCore/composer.json @@ -18,6 +18,7 @@ "gregwar/captcha-bundle": "^2.2", "melipayamak/php": "1.0.0", "mpdf/mpdf": "^8.2", + "nelmio/api-doc-bundle": "^4.34", "nelmio/cors-bundle": "^2.4", "phpdocumentor/reflection-docblock": "^5.3", "phpoffice/phpspreadsheet": "^1.29", diff --git a/hesabixCore/composer.lock b/hesabixCore/composer.lock index 2f9a686..6a19524 100644 --- a/hesabixCore/composer.lock +++ b/hesabixCore/composer.lock @@ -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": "0db24777fc7551965de7a3d68fdc1eb1", + "content-hash": "0000709f0d53a720475e13fa5dae69ab", "packages": [ { "name": "doctrine/annotations", @@ -2447,6 +2447,128 @@ ], "time": "2024-06-12T14:39:25+00:00" }, + { + "name": "nelmio/api-doc-bundle", + "version": "v4.34.0", + "source": { + "type": "git", + "url": "https://github.com/nelmio/NelmioApiDocBundle.git", + "reference": "ff9139576376695d2c3febc23a5e7eab91866d83" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nelmio/NelmioApiDocBundle/zipball/ff9139576376695d2c3febc23a5e7eab91866d83", + "reference": "ff9139576376695d2c3febc23a5e7eab91866d83", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=7.4", + "phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0", + "phpdocumentor/type-resolver": "^1.8.2", + "psr/cache": "^1.0 || ^2.0 || ^3.0", + "psr/container": "^1.0 || ^2.0", + "psr/log": "^1.0 || ^2.0 || ^3.0", + "symfony/config": "^5.4 || ^6.4 || ^7.1", + "symfony/console": "^5.4 || ^6.4 || ^7.1", + "symfony/dependency-injection": "^5.4 || ^6.4 || ^7.1", + "symfony/deprecation-contracts": "^2.1 || ^3", + "symfony/framework-bundle": "^5.4.24 || ^6.4 || ^7.1", + "symfony/http-foundation": "^5.4 || ^6.4 || ^7.1", + "symfony/http-kernel": "^5.4 || ^6.4 || ^7.1", + "symfony/options-resolver": "^5.4 || ^6.4 || ^7.1", + "symfony/property-info": "^5.4.10 || ^6.4 || ^7.1", + "symfony/routing": "^5.4 || ^6.4 || ^7.1", + "zircote/swagger-php": "^4.6.1" + }, + "conflict": { + "zircote/swagger-php": "4.8.7" + }, + "require-dev": { + "api-platform/core": "^2.7.0 || ^3", + "composer/package-versions-deprecated": "1.11.99.1", + "doctrine/annotations": "^2.0", + "friendsofphp/php-cs-fixer": "^3.52", + "friendsofsymfony/rest-bundle": "^2.8 || ^3.0", + "jms/serializer": "^1.14 || ^3.0", + "jms/serializer-bundle": "^2.3 || ^3.0 || ^4.0 || ^5.0", + "phpstan/phpstan": "^1.10", + "phpstan/phpstan-phpunit": "^1.3", + "phpstan/phpstan-strict-rules": "^1.5", + "phpstan/phpstan-symfony": "^1.3", + "phpunit/phpunit": "^9.6 || ^10.5", + "symfony/asset": "^5.4 || ^6.4 || ^7.1", + "symfony/browser-kit": "^5.4 || ^6.4 || ^7.1", + "symfony/cache": "^5.4 || ^6.4 || ^7.1", + "symfony/dom-crawler": "^5.4 || ^6.4 || ^7.1", + "symfony/expression-language": "^5.4 || ^6.4 || ^7.1", + "symfony/form": "^5.4 || ^6.4 || ^7.1", + "symfony/phpunit-bridge": "^6.4", + "symfony/property-access": "^5.4 || ^6.4 || ^7.1", + "symfony/security-csrf": "^5.4 || ^6.4 || ^7.1", + "symfony/serializer": "^5.4 || ^6.4 || ^7.1", + "symfony/stopwatch": "^5.4 || ^6.4 || ^7.1", + "symfony/templating": "^5.4 || ^6.4 || ^7.1", + "symfony/twig-bundle": "^5.4 || ^6.4 || ^7.1", + "symfony/uid": "^5.4 || ^6.4 || ^7.1", + "symfony/validator": "^5.4 || ^6.4 || ^7.1", + "willdurand/hateoas-bundle": "^1.0 || ^2.0" + }, + "suggest": { + "api-platform/core": "For using an API oriented framework.", + "doctrine/annotations": "For using doctrine annotations", + "friendsofsymfony/rest-bundle": "For using the parameters annotations.", + "jms/serializer-bundle": "For describing your models.", + "symfony/asset": "For using the Swagger UI.", + "symfony/cache": "For using a PSR-6 compatible cache implementation with the API doc generator.", + "symfony/form": "For describing your form type models.", + "symfony/monolog-bundle": "For using a PSR-3 compatible logger implementation with the API PHP describer.", + "symfony/security-csrf": "For using csrf protection tokens in forms.", + "symfony/serializer": "For describing your models.", + "symfony/twig-bundle": "For using the Swagger UI.", + "symfony/validator": "For describing the validation constraints in your models.", + "willdurand/hateoas-bundle": "For extracting HATEOAS metadata." + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, + "autoload": { + "psr-4": { + "Nelmio\\ApiDocBundle\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "https://github.com/nelmio/NelmioApiDocBundle/contributors" + } + ], + "description": "Generates documentation for your REST API from annotations and attributes", + "keywords": [ + "api", + "doc", + "documentation", + "rest" + ], + "support": { + "issues": "https://github.com/nelmio/NelmioApiDocBundle/issues", + "source": "https://github.com/nelmio/NelmioApiDocBundle/tree/v4.34.0" + }, + "funding": [ + { + "url": "https://github.com/DjordyKoert", + "type": "github" + } + ], + "time": "2025-01-08T11:43:02+00:00" + }, { "name": "nelmio/cors-bundle", "version": "2.5.0", @@ -8990,6 +9112,87 @@ "source": "https://github.com/webmozarts/assert/tree/1.11.0" }, "time": "2022-06-03T18:03:27+00:00" + }, + { + "name": "zircote/swagger-php", + "version": "4.11.1", + "source": { + "type": "git", + "url": "https://github.com/zircote/swagger-php.git", + "reference": "7df10e8ec47db07c031db317a25bef962b4e5de1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zircote/swagger-php/zipball/7df10e8ec47db07c031db317a25bef962b4e5de1", + "reference": "7df10e8ec47db07c031db317a25bef962b4e5de1", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=7.2", + "psr/log": "^1.1 || ^2.0 || ^3.0", + "symfony/deprecation-contracts": "^2 || ^3", + "symfony/finder": ">=2.2", + "symfony/yaml": ">=3.3" + }, + "require-dev": { + "composer/package-versions-deprecated": "^1.11", + "doctrine/annotations": "^1.7 || ^2.0", + "friendsofphp/php-cs-fixer": "^2.17 || 3.62.0", + "phpstan/phpstan": "^1.6", + "phpunit/phpunit": ">=8", + "vimeo/psalm": "^4.23" + }, + "suggest": { + "doctrine/annotations": "^1.7 || ^2.0" + }, + "bin": [ + "bin/openapi" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, + "autoload": { + "psr-4": { + "OpenApi\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Robert Allen", + "email": "zircote@gmail.com" + }, + { + "name": "Bob Fanger", + "email": "bfanger@gmail.com", + "homepage": "https://bfanger.nl" + }, + { + "name": "Martin Rademacher", + "email": "mano@radebatz.net", + "homepage": "https://radebatz.net" + } + ], + "description": "swagger-php - Generate interactive documentation for your RESTful API using phpdoc annotations", + "homepage": "https://github.com/zircote/swagger-php/", + "keywords": [ + "api", + "json", + "rest", + "service discovery" + ], + "support": { + "issues": "https://github.com/zircote/swagger-php/issues", + "source": "https://github.com/zircote/swagger-php/tree/4.11.1" + }, + "time": "2024-10-15T19:20:02+00:00" } ], "packages-dev": [ diff --git a/hesabixCore/config/bundles.php b/hesabixCore/config/bundles.php index 7b31924..a62124b 100644 --- a/hesabixCore/config/bundles.php +++ b/hesabixCore/config/bundles.php @@ -15,4 +15,5 @@ return [ Gregwar\CaptchaBundle\GregwarCaptchaBundle::class => ['all' => true], FOS\CKEditorBundle\FOSCKEditorBundle::class => ['all' => true], Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true], + Nelmio\ApiDocBundle\NelmioApiDocBundle::class => ['all' => true], ]; diff --git a/hesabixCore/config/packages/nelmio_api_doc.yaml b/hesabixCore/config/packages/nelmio_api_doc.yaml new file mode 100644 index 0000000..fa54c59 --- /dev/null +++ b/hesabixCore/config/packages/nelmio_api_doc.yaml @@ -0,0 +1,9 @@ +nelmio_api_doc: + documentation: + info: + title: Hesabix API document + description: Hesabix is first open source cloud base accounting platform + version: 0.43.2.1 + areas: # to filter documented areas + path_patterns: + - ^/api(?!/doc$) # Accepts routes under /api except /api/doc diff --git a/hesabixCore/config/routes/nelmio_api_doc.yaml b/hesabixCore/config/routes/nelmio_api_doc.yaml new file mode 100644 index 0000000..59a5756 --- /dev/null +++ b/hesabixCore/config/routes/nelmio_api_doc.yaml @@ -0,0 +1,12 @@ +# Expose your documentation as JSON swagger compliant +app.swagger: + path: /api/doc + methods: GET + defaults: { _controller: nelmio_api_doc.controller.swagger_ui } + +## Requires the Asset component and the Twig bundle +## $ composer require twig asset +#app.swagger_ui: +# path: /api/doc +# methods: GET +# defaults: { _controller: nelmio_api_doc.controller.swagger_ui } diff --git a/hesabixCore/src/Controller/PrintersController.php b/hesabixCore/src/Controller/PrintersController.php index aa890c0..8adeb2d 100644 --- a/hesabixCore/src/Controller/PrintersController.php +++ b/hesabixCore/src/Controller/PrintersController.php @@ -3,11 +3,13 @@ namespace App\Controller; use App\Entity\Printer; +use App\Entity\PrinterQueue; use App\Entity\PrintItem; use App\Entity\PrintOptions; use App\Service\Access; use App\Service\Explore; use App\Service\Extractor; +use App\Service\Jdate; use App\Service\Log; use App\Service\Provider; use Doctrine\ORM\EntityManagerInterface; @@ -55,7 +57,9 @@ class PrintersController extends AbstractController $temp['sell']['noteString'] = $settings->getSellNoteString(); $temp['sell']['pays'] = $settings->isSellPays(); $temp['sell']['paper'] = $settings->getSellPaper(); - if(!$temp['sell']['paper']) { $temp['sell']['paper'] = 'A4-L'; } + if (!$temp['sell']['paper']) { + $temp['sell']['paper'] = 'A4-L'; + } $temp['buy']['id'] = $settings->getId(); $temp['buy']['bidInfo'] = $settings->isBuyBidInfo(); @@ -65,7 +69,9 @@ class PrintersController extends AbstractController $temp['buy']['noteString'] = $settings->getBuyNoteString(); $temp['buy']['pays'] = $settings->isBuyPays(); $temp['buy']['paper'] = $settings->getBuyPaper(); - if(!$temp['buy']['paper']) { $temp['buy']['paper'] = 'A4-L'; } + if (!$temp['buy']['paper']) { + $temp['buy']['paper'] = 'A4-L'; + } $temp['rfbuy']['id'] = $settings->getId(); $temp['rfbuy']['bidInfo'] = $settings->isRfbuyBidInfo(); @@ -75,7 +81,9 @@ class PrintersController extends AbstractController $temp['rfbuy']['noteString'] = $settings->getRfbuyNoteString(); $temp['rfbuy']['pays'] = $settings->isRfbuyPays(); $temp['rfbuy']['paper'] = $settings->getRfbuyPaper(); - if(!$temp['rfbuy']['paper']) { $temp['rfbuy']['paper'] = 'A4-L'; } + if (!$temp['rfbuy']['paper']) { + $temp['rfbuy']['paper'] = 'A4-L'; + } $temp['rfsell']['id'] = $settings->getId(); $temp['rfsell']['bidInfo'] = $settings->isRfsellBidInfo(); @@ -92,7 +100,9 @@ class PrintersController extends AbstractController $temp['repservice']['noteString'] = $settings->getRepserviceNoteString(); $temp['repservice']['paper'] = $settings->getRepServicePaper(); - if(!$temp['rfsell']['paper']) { $temp['rfsell']['paper'] = 'A4-L'; } + if (!$temp['rfsell']['paper']) { + $temp['rfsell']['paper'] = 'A4-L'; + } return $this->json($temp); } @@ -122,13 +132,12 @@ class PrintersController extends AbstractController $settings->setSellNoteString($params['sell']['noteString']); $settings->setSellPays($params['sell']['pays']); $settings->setSellPaper($params['sell']['paper']); - if($params['buy']['bidInfo'] == null){ + if ($params['buy']['bidInfo'] == null) { $settings->setBuyBidInfo(false); - } - else{ + } else { $settings->setBuyBidInfo(true); } - + $settings->setBuyTaxInfo($params['buy']['taxInfo']); $settings->setBuyDiscountInfo($params['buy']['discountInfo']); $settings->setBuyNote($params['buy']['note']); @@ -212,9 +221,9 @@ class PrintersController extends AbstractController } if (!array_key_exists('name', $params)) return $this->json($extractor->paramsNotSend()); - $item = $entityManager->getRepository(Printer::class)->findOneBy(['bid' => $acc['bid'], 'name' => $params['name']]); - if($item) - return $this->json(['result'=>2]); + $item = $entityManager->getRepository(Printer::class)->findOneBy(['bid' => $acc['bid'], 'name' => $params['name']]); + if ($item) + return $this->json(['result' => 2]); $item = new Printer(); $item->setBid($acc['bid']); $item->setName($params['name']); @@ -234,16 +243,81 @@ class PrintersController extends AbstractController throw $this->createAccessDeniedException(); $printer = $entityManager->getRepository(Printer::class)->findBy([ 'bid' => $acc['bid'], - 'token'=>$request->headers->get('printer-key') + 'token' => $request->headers->get('printer-key') ]); $items = $entityManager->getRepository(PrintItem::class)->findBy([ 'printer' => $printer, 'printed' => false ]); - if(count($items) == 0) return new Response(''); + if (count($items) == 0) + return new Response(''); $items[count($items) - 1]->setPrinted(true); $entityManager->persist($items[count($items) - 1]); $entityManager->flush(); - return new Response($items[count($items) - 1]->getType() . ',' .$items[count($items) - 1]->getFile()); + return new Response($items[count($items) - 1]->getType() . ',' . $items[count($items) - 1]->getFile()); + } + + #[Route('/api/printers/exist/{code}', name: 'app_printers_exist')] + public function app_printers_exist(Extractor $extractor, Provider $provider, Request $request, Access $access, Log $log, EntityManagerInterface $entityManager, $code = 0): JsonResponse + { + $acc = $access->hasRole('join'); + if (!$acc) + throw $this->createAccessDeniedException(); + + $printer = $entityManager->getRepository(Printer::class)->findOneBy(['bid' => $acc['bid'], 'id' => $code]); + if ($printer) + return $this->json($extractor->operationSuccess()); + return $this->json($extractor->operationFail()); + } + + #[Route('/api/printers/queue/{code}', name: 'app_printers_queue')] + public function app_printers_queue(Jdate $jdate, Extractor $extractor, Provider $provider, Request $request, Access $access, Log $log, EntityManagerInterface $entityManager, $code = 0): JsonResponse + { + $acc = $access->hasRole('join'); + if (!$acc) + throw $this->createAccessDeniedException(); + + $queue = $entityManager->getRepository(PrinterQueue::class)->findBy(['bid' => $acc['bid']]); + $resp = []; + foreach ($queue as $item) { + $resp[] = [ + 'id' => $item->getId(), + 'submitter' => $item->getSubmitter()->getFullName(), + 'code' => $item->getPid(), + 'dateSubmit' => $jdate->jdate('Y/n/d H:i', $item->getDateSubmit()) + ]; + } + return $this->json($extractor->operationSuccess($resp)); + } + + #[Route('/api/printers/queue_doc_delete/{code}', name: 'app_printers_queuequeue_doc_delete')] + public function app_printers_queuequeue_doc_delete(Jdate $jdate, Extractor $extractor, Provider $provider, Request $request, Access $access, Log $log, EntityManagerInterface $entityManager, $code = 0): JsonResponse + { + $acc = $access->hasRole('join'); + if (!$acc) + throw $this->createAccessDeniedException(); + + $item = $entityManager->getRepository(PrinterQueue::class)->findOneBy(['bid' => $acc['bid'], 'pid' => $code]); + if (!$item) + throw $this->createNotFoundException(); + $log->insert('تنظیمات چاپ', ' برگه پرینت ابری با کد' . $item->getId() . ' حذف شد.', $this->getUser(), $acc['bid']->getId()); + $entityManager->remove($item); + $entityManager->flush(); + return $this->json($extractor->operationSuccess()); + } + + #[Route('/api/printers/queue_doc_delete_all', name: 'app_printers_queuequeue_doc_delete_all')] + public function app_printers_queuequeue_doc_delete_all(Jdate $jdate, Extractor $extractor, Provider $provider, Request $request, Access $access, Log $log, EntityManagerInterface $entityManager): JsonResponse + { + $acc = $access->hasRole('join'); + if (!$acc) + throw $this->createAccessDeniedException(); + + $items = $entityManager->getRepository(PrinterQueue::class)->findBy(['bid' => $acc['bid']]); + foreach ($items as $item) { + $entityManager->remove($item); + } + $log->insert('تنظیمات چاپ', 'لیست چاپگرهای ابری پاک شد.', $this->getUser(), $acc['bid']->getId()); + return $this->json($extractor->operationSuccess()); } } diff --git a/hesabixCore/src/Controller/ReportController.php b/hesabixCore/src/Controller/ReportController.php index 587b500..92c9871 100644 --- a/hesabixCore/src/Controller/ReportController.php +++ b/hesabixCore/src/Controller/ReportController.php @@ -2,6 +2,7 @@ namespace App\Controller; +use OpenApi\Annotations as OA; use App\Entity\BankAccount; use App\Entity\Cashdesk; use App\Entity\Commodity; @@ -344,6 +345,7 @@ class ReportController extends AbstractController $temp = [ 'id' => $item->getId(), 'account' => $item->getName(), + 'type' => $item->getType(), 'code' => $item->getCode(), ]; $childs = $entityManagerInterface->getRepository(HesabdariTable::class)->findBy([ @@ -353,7 +355,7 @@ class ReportController extends AbstractController if (count($childs) > 0 || $item->getType() != 'calc') { $temp['hasChild'] = true; } - $temp = array_merge($temp, $this->getBalance($acc, $item->getCode(), $rootNode->getType())); + $temp = array_merge($temp, $this->getBalaceTree($acc, $item)); $response[] = $temp; } } elseif ($rootNode->getType() == 'bank') { @@ -361,6 +363,7 @@ class ReportController extends AbstractController $temp = [ 'id' => $item->getId(), 'account' => $item->getName(), + 'type' => 'bank', 'code' => $item->getCode(), ]; $temp = array_merge($temp, $this->getBalance($acc, $item->getCode(), $rootNode->getType())); @@ -372,6 +375,7 @@ class ReportController extends AbstractController $temp = [ 'id' => $item->getId(), 'account' => $item->getName(), + 'type' => 'cashdesk', 'code' => $item->getCode(), ]; $temp = array_merge($temp, $this->getBalance($acc, $item->getCode(), $rootNode->getType())); @@ -383,6 +387,7 @@ class ReportController extends AbstractController $temp = [ 'id' => $item->getId(), 'account' => $item->getName(), + 'type' => 'salary', 'code' => $item->getCode(), ]; $temp = array_merge($temp, $this->getBalance($acc, $item->getCode(), $rootNode->getType())); @@ -394,6 +399,19 @@ class ReportController extends AbstractController $temp = [ 'id' => $item->getId(), 'account' => $item->getNikename(), + 'type' => 'person', + 'code' => $item->getCode(), + ]; + $temp = array_merge($temp, $this->getBalance($acc, $item->getCode(), $rootNode->getType())); + $temp['hasChild'] = false; + $response[] = $temp; + } + } elseif ($rootNode->getType() == 'commodity') { + foreach ($tableItems as $item) { + $temp = [ + 'id' => $item->getId(), + 'account' => $item->getName(), + 'type' => 'commodity', 'code' => $item->getCode(), ]; $temp = array_merge($temp, $this->getBalance($acc, $item->getCode(), $rootNode->getType())); @@ -445,18 +463,17 @@ class ReportController extends AbstractController $bd = 0; foreach ($faltItemsArray as $item) { - if ($item['type'] == 'calc') { + if ($item['type'] == 'commodity') { $items = $this->em->getRepository(HesabdariRow::class)->findBy([ 'money' => $acc['money'], 'bid' => $acc['bid'], - 'hesabdariTable' => $item['id'] + 'commodity' => $item['id'] ]); foreach ($items as $objItem) { $bs += $objItem->getBs(); $bd += $objItem->getBd(); } - } - elseif ($item['type'] == 'person') { + } elseif ($item['type'] == 'person') { $items = $this->em->getRepository(HesabdariRow::class)->findBy([ 'money' => $acc['money'], 'bid' => $acc['bid'], @@ -466,8 +483,7 @@ class ReportController extends AbstractController $bs += $objItem->getBs(); $bd += $objItem->getBd(); } - } - elseif ($item['type'] == 'cashdesk') { + } elseif ($item['type'] == 'cashdesk') { $items = $this->em->getRepository(HesabdariRow::class)->findBy([ 'money' => $acc['money'], 'bid' => $acc['bid'], @@ -477,8 +493,7 @@ class ReportController extends AbstractController $bs += $objItem->getBs(); $bd += $objItem->getBd(); } - } - elseif ($item['type'] == 'salary') { + } elseif ($item['type'] == 'salary') { $items = $this->em->getRepository(HesabdariRow::class)->findBy([ 'money' => $acc['money'], 'bid' => $acc['bid'], @@ -542,4 +557,179 @@ class ReportController extends AbstractController } return $res; } + + private function getBalaceTree(array $acc, HesabdariTable $table): array + { + $res = [ + 'bal_bd' => 0, + 'bal_bs' => 0, + 'his_bd' => 0, + 'his_bs' => 0, + ]; + if ($this->hasChild($table)) { + foreach ($this->getChilds($table) as $child) { + if ($this->hasChild($child)) { + $temp = $this->getBalaceTree($acc, $child); + $res['his_bd'] += $temp['his_bd']; + $res['his_bs'] += $temp['his_bs']; + } else { + $temp = $this->calcBalance($acc, $child); + $res['his_bd'] += $temp['his_bd']; + $res['his_bs'] += $temp['his_bs']; + } + } + } else { + $temp = $this->calcBalance($acc, $table); + $res['his_bd'] += $temp['his_bd']; + $res['his_bs'] += $temp['his_bs']; + } + + if ($res['his_bd'] > $res['his_bs']) { + $res['bal_bd'] = $res['his_bd'] - $res['his_bs']; + $res['bal_bs'] = 0; + } else { + $res['bal_bs'] = $res['his_bs'] - $res['his_bd']; + $res['bal_bd'] = 0; + } + return $res; + } + + private function calcBalance(array $acc, HesabdariTable $table): array + { + $res = [ + 'his_bd' => 0, + 'his_bs' => 0, + ]; + + $items = $this->em->getRepository(HesabdariRow::class)->findByJoinMoney([ + 'bid' => $acc['bid'], + 'ref' => $table + ], $acc['money']); + + foreach ($items as $objItem) { + $res['his_bs'] += $objItem->getBs(); + $res['his_bd'] += $objItem->getBd(); + } + return $res; + } + private function hasChild(HesabdariTable $table): bool + { + if ($this->em->getRepository(HesabdariTable::class)->findOneBy(['upper' => $table])) + return true; + return false; + } + + private function getChilds(HesabdariTable $table): array + { + return $this->em->getRepository(HesabdariTable::class)->findBy(['upper' => $table]); + } + + #[Route('/api/report/acc/get_details', name: 'app_report_acc_get_details')] + public function app_report_acc_get_details(Provider $provider, Jdate $jdate, Access $access, Request $request, EntityManagerInterface $entityManagerInterface): JsonResponse + { + $acc = $access->hasRole('report'); + if (!$acc) { + throw $this->createAccessDeniedException(); + } + + $params = []; + if ($content = $request->getContent()) { + $params = json_decode($content, true); + } + if (!array_key_exists('node', $params)) + throw $this->createNotFoundException(); + if ($params['type'] == 'calc') { + $rootNode = $entityManagerInterface->getRepository(HesabdariTable::class)->find($params['node']); + if (!$rootNode) + throw $this->createNotFoundException(); + } elseif ($params['type'] == 'bank') { + $rootNode = $entityManagerInterface->getRepository(BankAccount::class)->find($params['node']); + if (!$rootNode) + throw $this->createNotFoundException(); + } elseif ($params['type'] == 'cashdesk') { + $rootNode = $entityManagerInterface->getRepository(Cashdesk::class)->find($params['node']); + if (!$rootNode) + throw $this->createNotFoundException(); + } elseif ($params['type'] == 'salary') { + $rootNode = $entityManagerInterface->getRepository(Salary::class)->find($params['node']); + if (!$rootNode) + throw $this->createNotFoundException(); + } elseif ($params['type'] == 'person') { + $rootNode = $entityManagerInterface->getRepository(Person::class)->find($params['node']); + if (!$rootNode) + throw $this->createNotFoundException(); + } elseif ($params['type'] == 'commodity') { + $rootNode = $entityManagerInterface->getRepository(Commodity::class)->find($params['node']); + if (!$rootNode) + throw $this->createNotFoundException(); + } + $items = $this->tree2flat($rootNode, $acc); + return $this->json(Explore::ExploreHesabdariRows($items)); + } + + private function tree2flat(Person|HesabdariTable|BankAccount|Cashdesk $item, array $acc): array + { + $res = []; + if ($this->getEntityName($item) == 'App\Entity\HesabdariTable') { + if ($this->hasChild($item)) { + $temp = []; + foreach ($this->getChilds($item) as $child) { + $temp = array_merge($temp, $this->getTree($child)); + } + $res = array_merge($res, $temp); + } else { + $items = $this->em->getRepository(HesabdariRow::class)->findByJoinMoney([ + 'bid' => $acc['bid'], + 'ref' => $item + ], $acc['money']); + $res = array_merge($res, $items); + } + } elseif ($this->getEntityName($item) == 'App\Entity\BankAccount') { + $items = $this->em->getRepository(HesabdariRow::class)->findByJoinMoney([ + 'bid' => $acc['bid'], + 'bank' => $item + ], $acc['money']); + $res = array_merge($res, $items); + } elseif ($this->getEntityName($item) == 'App\Entity\Cashdesk') { + $items = $this->em->getRepository(HesabdariRow::class)->findByJoinMoney([ + 'bid' => $acc['bid'], + 'bank' => $item + ], $acc['money']); + $res = array_merge($res, $items); + } elseif ($this->getEntityName($item) == 'App\Entity\Salary') { + $items = $this->em->getRepository(HesabdariRow::class)->findByJoinMoney([ + 'bid' => $acc['bid'], + 'salary' => $item + ], $acc['money']); + $res = array_merge($res, $items); + } elseif ($this->getEntityName($item) == 'App\Entity\Person') { + $items = $this->em->getRepository(HesabdariRow::class)->findByJoinMoney([ + 'bid' => $acc['bid'], + 'person' => $item + ], $acc['money']); + $res = array_merge($res, $items); + } elseif ($this->getEntityName($item) == 'App\Entity\Commodity') { + $items = $this->em->getRepository(HesabdariRow::class)->findByJoinMoney([ + 'bid' => $acc['bid'], + 'commodity' => $item, + ], $acc['money']); + $res = array_merge($res, $items); + } + + return $res; + } + + /** + * Returns Doctrine entity name + * + * @param mixed $entity + * + * @return string + * @throws \Exception + */ + private function getEntityName($entity): string + { + $entityName = $this->em->getMetadataFactory()->getMetadataFor(get_class($entity))->getName(); + return $entityName; + } } diff --git a/hesabixCore/src/Controller/UserController.php b/hesabixCore/src/Controller/UserController.php index 0cb745e..89ad3ac 100644 --- a/hesabixCore/src/Controller/UserController.php +++ b/hesabixCore/src/Controller/UserController.php @@ -62,6 +62,17 @@ class UserController extends AbstractController $translatorInterface->trans('login_fail'), )); } + if ($user->isActive() == false) { + return $this->json($extractor->operationFail( + 'حساب کاربری شما فعال نیست. لطفا با پشتیبانی تماس بگیرید' + , + 506, + [ + 'user' => $user->getUserIdentifier(), + 'active' => $user->isActive(), + ] + )); + } $token = new UserToken(); $token->setUser($user); $token->setToken($this->RandomString(254)); @@ -71,7 +82,8 @@ class UserController extends AbstractController return $this->json($extractor->operationSuccess([ 'user' => $user->getUserIdentifier(), 'token' => $token->getToken(), - 'tokenID' => $token->getTokenID() + 'tokenID' => $token->getTokenID(), + 'active' => $user->isActive(), ])); } else { if (null === $user) { @@ -88,14 +100,15 @@ class UserController extends AbstractController return $this->json([ 'user' => $user->getUserIdentifier(), 'token' => $token->getToken(), - 'tokenID' => $token->getTokenID() + 'tokenID' => $token->getTokenID(), + 'active' => $user->isActive(), ]); } } #[Route('/api/user/has/role/{id}', name: 'api_user_has_role')] - public function api_user_has_role(Extractor $extractor,#[CurrentUser] ?User $user, EntityManagerInterface $entityManager, $id): Response + public function api_user_has_role(Extractor $extractor, #[CurrentUser] ?User $user, EntityManagerInterface $entityManager, $id): Response { if ($this->isGranted($id)) { return $this->json( @@ -244,7 +257,7 @@ class UserController extends AbstractController } #[Route('/api/user/change/password', name: 'api_user_change_password')] - public function api_user_change_password(Extractor $extractor,#[CurrentUser] ?User $user, UserPasswordHasherInterface $userPasswordHasher, EntityManagerInterface $entityManager, Request $request): Response + public function api_user_change_password(Extractor $extractor, #[CurrentUser] ?User $user, UserPasswordHasherInterface $userPasswordHasher, EntityManagerInterface $entityManager, Request $request): Response { $params = []; if ($content = $request->getContent()) { @@ -460,7 +473,7 @@ class UserController extends AbstractController $entityManager->persist($user); $entityManager->flush(); return $this->json($extractor->operationSuccess( - ['id'=>$user->getId()], + ['id' => $user->getId()], 'حساب کاربری شما فعال شد.هماکنون میتوانید با اطلاعات ثبت نام خود به حساب کاربری وارد شوید.' )); } diff --git a/hesabixCore/src/Repository/HesabdariRowRepository.php b/hesabixCore/src/Repository/HesabdariRowRepository.php index bf8dbbb..e45bcd6 100644 --- a/hesabixCore/src/Repository/HesabdariRowRepository.php +++ b/hesabixCore/src/Repository/HesabdariRowRepository.php @@ -4,6 +4,7 @@ namespace App\Repository; use App\Entity\Commodity; use App\Entity\HesabdariRow; +use App\Entity\Money; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\ORM\NonUniqueResultException; use Doctrine\Persistence\ManagerRegistry; @@ -51,8 +52,22 @@ class HesabdariRowRepository extends ServiceEntityRepository return $qb->select('t') ->where($qb->expr()->isNotNull('t.' . $notField)) ->andWhere('t.doc = :doc') - ->setParameter('doc',$doc) + ->setParameter('doc', $doc) ->getQuery() ->getOneOrNullResult(); } + + public function findByJoinMoney(array $params, Money $money): array + { + $query = $this->createQueryBuilder('t') + ->select('t') + ->innerJoin('t.doc', 'd') + ->where('d.money = :money') + ->setParameter('money', $money); + foreach ($params as $key => $value) { + $query->andWhere('t.' . $key . '= :' . $key); + $query->setParameter($key, $value); + } + return $query->getQuery()->getResult(); + } } diff --git a/hesabixCore/src/Service/Explore.php b/hesabixCore/src/Service/Explore.php index 224056f..9fdf201 100644 --- a/hesabixCore/src/Service/Explore.php +++ b/hesabixCore/src/Service/Explore.php @@ -160,8 +160,10 @@ class Explore } public static function ExploreHesabdariRow(HesabdariRow $row) { + $jdate = new Jdate(); $temp = [ 'id' => $row->getId(), + 'doc_code' => $row->getDoc()->getCode(), 'bid' => self::ExploreBid($row->getBid()), 'year' => self::ExploreYear($row->getYear()), 'ref' => self::ExploreHesabdariTable($row->getRef()), @@ -172,6 +174,8 @@ class Explore 'bs' => $row->getBs(), 'bd' => $row->getBd(), 'des' => $row->getDes(), + 'date' => $row->getDoc()->getDate(), + 'dateSubmit' => $jdate->jdate('Y/n/d', $row->getDoc()->getDateSubmit()), 'plugin' => $row->getPlugin(), 'commodity_count' => $row->getCommdityCount(), 'commodity' => self::ExploreCommodity($row->getCommodity(), $row->getCommdityCount(), $row->getDes()), @@ -563,26 +567,35 @@ class Explore public static function ExploreDashboardSettings(DashboardSettings $item) { - $result = [ + $result = [ 'banks' => $item->isBanks(), 'buys' => $item->isBuys(), 'sells' => $item->isSells(), 'wallet' => $item->isWallet(), - 'acc_docs'=> $item->isAccDocs(), - 'accounting_total'=>$item->isAccountingTotal(), - 'commodities'=>$item->isCommodities(), - 'persons'=>$item->isPersons(), - 'notif'=>$item->isNotif(), + 'acc_docs' => $item->isAccDocs(), + 'accounting_total' => $item->isAccountingTotal(), + 'commodities' => $item->isCommodities(), + 'persons' => $item->isPersons(), + 'notif' => $item->isNotif(), ]; - if($result['banks'] === null) $result['banks'] = true; - if($result['buys'] === null) $result['buys'] = true; - if($result['sells'] === null) $result['sells'] = true; - if($result['wallet'] === null) $result['wallet'] = true; - if($result['acc_docs'] === null) $result['acc_docs'] = true; - if($result['accounting_total'] ===null) $result['accounting_total'] = true; - if($result['commodities'] === null) $result['commodities'] = true; - if($result['persons'] === null) $result['persons'] = true; - if($result['notif'] === null) $result['notif'] = true; + if ($result['banks'] === null) + $result['banks'] = true; + if ($result['buys'] === null) + $result['buys'] = true; + if ($result['sells'] === null) + $result['sells'] = true; + if ($result['wallet'] === null) + $result['wallet'] = true; + if ($result['acc_docs'] === null) + $result['acc_docs'] = true; + if ($result['accounting_total'] === null) + $result['accounting_total'] = true; + if ($result['commodities'] === null) + $result['commodities'] = true; + if ($result['persons'] === null) + $result['persons'] = true; + if ($result['notif'] === null) + $result['notif'] = true; return $result; } diff --git a/hesabixCore/symfony.lock b/hesabixCore/symfony.lock index 657a246..3e51f72 100644 --- a/hesabixCore/symfony.lock +++ b/hesabixCore/symfony.lock @@ -50,6 +50,19 @@ "gregwar/captcha-bundle": { "version": "v2.2.0" }, + "nelmio/api-doc-bundle": { + "version": "4.34", + "recipe": { + "repo": "github.com/symfony/recipes-contrib", + "branch": "main", + "version": "3.0", + "ref": "c8e0c38e1a280ab9e37587a8fa32b251d5bc1c94" + }, + "files": [ + "config/packages/nelmio_api_doc.yaml", + "config/routes/nelmio_api_doc.yaml" + ] + }, "nelmio/cors-bundle": { "version": "2.4", "recipe": { diff --git a/hesabixCore/templates/user/email/confrim-forget-password.html.twig b/hesabixCore/templates/user/email/confrim-forget-password.html.twig new file mode 100644 index 0000000..2b0b555 --- /dev/null +++ b/hesabixCore/templates/user/email/confrim-forget-password.html.twig @@ -0,0 +1,155 @@ + + +
+
+
+
+
|
+
+
+
+
|
+
+
+
+
|
+
p&&(p=e.lineIndent),w(a))m++;else{if(e.lineIndent
0){for(i=a,o=0;i>0;i--)(a=E(s=e.input.charCodeAt(++e.position)))>=0?o=(o<<4)+a:R(e,"expected hexadecimal character");e.result+=A(o),e.position++}else R(e,"unknown escape sequence");n=r=e.position}else w(s)?(L(e,n,r,!0),B(e,z(e,!1,t)),n=r=e.position):e.position===e.lineStart&&U(e)?R(e,"unexpected end of the document within a double quoted scalar"):(e.position++,r=e.position)}R(e,"unexpected end of the stream within a double quoted scalar")}(e,_)?N=!0:function(e){var t,n,r;if(42!==(r=e.input.charCodeAt(e.position)))return!1;for(r=e.input.charCodeAt(++e.position),t=e.position;0!==r&&!S(r)&&!O(r);)r=e.input.charCodeAt(++e.position);return e.position===t&&R(e,"name of an alias node must contain at least one character"),n=e.input.slice(t,e.position),s.call(e.anchorMap,n)||R(e,'unidentified alias "'+n+'"'),e.result=e.anchorMap[n],z(e,!0,-1),!0}(e)?(N=!0,null===e.tag&&null===e.anchor||R(e,"alias node should not have any properties")):function(e,t,n){var r,i,o,a,s,l,c,u,p=e.kind,d=e.result;if(S(u=e.input.charCodeAt(e.position))||O(u)||35===u||38===u||42===u||33===u||124===u||62===u||39===u||34===u||37===u||64===u||96===u)return!1;if((63===u||45===u)&&(S(r=e.input.charCodeAt(e.position+1))||n&&O(r)))return!1;for(e.kind="scalar",e.result="",i=o=e.position,a=!1;0!==u;){if(58===u){if(S(r=e.input.charCodeAt(e.position+1))||n&&O(r))break}else if(35===u){if(S(e.input.charCodeAt(e.position-1)))break}else{if(e.position===e.lineStart&&U(e)||n&&O(u))break;if(w(u)){if(s=e.line,l=e.lineStart,c=e.lineIndent,z(e,!1,-1),e.lineIndent>=t){a=!0,u=e.input.charCodeAt(e.position);continue}e.position=o,e.line=s,e.lineStart=l,e.lineIndent=c;break}}a&&(L(e,i,o,!1),B(e,e.line-s),i=o=e.position,a=!1),k(u)||(o=e.position+1),u=e.input.charCodeAt(++e.position)}return L(e,i,o,!1),!!e.result||(e.kind=p,e.result=d,!1)}(e,_,l===n)&&(N=!0,null===e.tag&&(e.tag="?")),null!==e.anchor&&(e.anchorMap[e.anchor]=e.result)):0===T&&(N=g&&q(e,P))),null===e.tag)null!==e.anchor&&(e.anchorMap[e.anchor]=e.result);else if("?"===e.tag){for(null!==e.result&&"scalar"!==e.kind&&R(e,'unacceptable node kind for !> tag; it should be "scalar", not "'+e.kind+'"'),y=0,b=e.implicitTypes.length;y"),null!==e.result&&x.kind!==e.kind&&R(e,"unacceptable node kind for !<"+e.tag+'> tag; it should be "'+x.kind+'", not "'+e.kind+'"'),x.resolve(e.result,e.tag)?(e.result=x.construct(e.result,e.tag),null!==e.anchor&&(e.anchorMap[e.anchor]=e.result)):R(e,"cannot resolve a node with !<"+e.tag+"> explicit tag")}return null!==e.listener&&e.listener("close",e),null!==e.tag||null!==e.anchor||N}function Y(e){var t,n,r,i,o=e.position,a=!1;for(e.version=null,e.checkLineBreaks=e.legacy,e.tagMap=Object.create(null),e.anchorMap=Object.create(null);0!==(i=e.input.charCodeAt(e.position))&&(z(e,!0,-1),i=e.input.charCodeAt(e.position),!(e.lineIndent>0||37!==i));){for(a=!0,i=e.input.charCodeAt(++e.position),t=e.position;0!==i&&!S(i);)i=e.input.charCodeAt(++e.position);for(r=[],(n=e.input.slice(t,e.position)).length<1&&R(e,"directive name must not be less than one character in length");0!==i;){for(;k(i);)i=e.input.charCodeAt(++e.position);if(35===i){do{i=e.input.charCodeAt(++e.position)}while(0!==i&&!w(i));break}if(w(i))break;for(t=e.position;0!==i&&!S(i);)i=e.input.charCodeAt(++e.position);r.push(e.input.slice(t,e.position))}0!==i&&F(e),s.call($,n)?$[n](e,n,r):N(e,'unknown document directive "'+n+'"')}z(e,!0,-1),0===e.lineIndent&&45===e.input.charCodeAt(e.position)&&45===e.input.charCodeAt(e.position+1)&&45===e.input.charCodeAt(e.position+2)?(e.position+=3,z(e,!0,-1)):a&&R(e,"directives end mark is expected"),H(e,e.lineIndent-1,p,!1,!0),z(e,!0,-1),e.checkLineBreaks&&g.test(e.input.slice(o,e.position))&&N(e,"non-ASCII line breaks are interpreted as content"),e.documents.push(e.result),e.position===e.lineStart&&U(e)?46===e.input.charCodeAt(e.position)&&(e.position+=3,z(e,!0,-1)):e.position