From 5470b82951b5c7ce4a344e693a667f878c5803fe Mon Sep 17 00:00:00 2001 From: Babak Alizadeh Date: Tue, 18 Mar 2025 12:16:01 +0000 Subject: [PATCH] bug fix in lists --- .../src/Controller/AdminController.php | 109 ++++- hesabixCore/src/Controller/CostController.php | 151 +++++++ hesabixCore/src/Controller/SellController.php | 425 ++++++++++-------- hesabixCore/src/Entity/HesabdariDoc.php | 12 +- 4 files changed, 496 insertions(+), 201 deletions(-) diff --git a/hesabixCore/src/Controller/AdminController.php b/hesabixCore/src/Controller/AdminController.php index 7b0d575..bc834d3 100644 --- a/hesabixCore/src/Controller/AdminController.php +++ b/hesabixCore/src/Controller/AdminController.php @@ -172,27 +172,104 @@ class AdminController extends AbstractController return $this->json($extractor->operationSuccess($resp)); } - #[Route('/api/admin/users/search', name: 'admin_users_list_search')] - public function admin_users_list_search(Extractor $extractor, Jdate $jdate, #[CurrentUser] ?User $user, UserPasswordHasherInterface $userPasswordHasher, EntityManagerInterface $entityManager, Request $request): Response - { - $params = []; - if ($content = $request->getContent()) { - $params = json_decode($content, true); + #[Route('/api/admin/users/search', name: 'admin_users_list_search', methods: ['POST'])] + public function admin_users_list_search( + Extractor $extractor, + Jdate $jdate, + #[CurrentUser] ?User $user, + EntityManagerInterface $entityManager, + Request $request + ): Response { + $params = json_decode($request->getContent(), true) ?? []; + + // پارامترهای صفحه‌بندی و مرتب‌سازی + $pagination = $params['pagination'] ?? ['page' => 1, 'limit' => 10]; + $sort = $params['sort'] ?? ['sortBy' => 'id', 'sortDesc' => true]; + $filters = $params['filters'] ?? []; + + $page = max(1, $pagination['page'] ?? 1); + $limit = max(1, min(100, $pagination['limit'] ?? 10)); + $offset = ($page - 1) * $limit; + + // ساخت کوئری پایه + $queryBuilder = $entityManager->createQueryBuilder() + ->select('u') + ->from(User::class, 'u'); + + // اعمال فیلترها و جستجو + if (!empty($filters['search'])) { + $searchTerm = $filters['search']; + $queryBuilder->andWhere( + $queryBuilder->expr()->orX( + 'u.email LIKE :search', + 'u.fullName LIKE :search', + 'u.mobile LIKE :search', + 'u.dateRegister LIKE :search', + 'u.invateCode LIKE :search' + ) + ) + ->setParameter('search', "%$searchTerm%"); } - $items = $entityManager->getRepository(User::class)->findByPage($params['options']['page'], $params['options']['rowsPerPage'], $params['search']); + + // اعمال فیلترهای وضعیت + if (isset($filters['status'])) { + $queryBuilder->andWhere('u.active = :status') + ->setParameter('status', $filters['status']); + } + + // اعمال مرتب‌سازی + $sortField = $sort['sortBy'] ?? 'id'; + $sortDirection = ($sort['sortDesc'] ?? true) ? 'DESC' : 'ASC'; + + // اطمینان از اینکه فیلد مرتب‌سازی معتبر است + $allowedSortFields = ['id', 'email', 'fullName', 'mobile', 'dateRegister', 'active']; + if (in_array($sortField, $allowedSortFields)) { + $queryBuilder->orderBy("u.$sortField", $sortDirection); + } else { + $queryBuilder->orderBy('u.id', 'DESC'); + } + + // محاسبه تعداد کل نتایج + $totalItemsQuery = clone $queryBuilder; + $totalItems = $totalItemsQuery->select('COUNT(u.id)') + ->getQuery() + ->getSingleScalarResult(); + + // اعمال صفحه‌بندی + $queryBuilder->setFirstResult($offset) + ->setMaxResults($limit); + + // دریافت نتایج + $items = $queryBuilder->getQuery()->getResult(); + + // تبدیل نتایج به فرمت مورد نظر $resp = []; foreach ($items as $item) { - $temp = []; - $temp['id'] = $item->getId(); - $temp['email'] = $item->getEmail(); - $temp['mobile'] = $item->getMobile(); - $temp['fullname'] = $item->getFullName(); - $temp['status'] = $item->isActive(); - $temp['dateRegister'] = $jdate->jdate('Y/n/d', $item->getDateRegister()); - $temp['bidCount'] = count($entityManager->getRepository(Business::class)->findBy(['owner' => $item])); + $temp = [ + 'id' => $item->getId(), + 'email' => $item->getEmail(), + 'mobile' => $item->getMobile(), + 'fullname' => $item->getFullName(), + 'status' => $item->isActive(), + 'dateRegister' => $jdate->jdate('Y/n/d', $item->getDateRegister()), + 'bidCount' => count($entityManager->getRepository(Business::class)->findBy(['owner' => $item])), + 'roles' => $item->getRoles(), + 'inviteCode' => $item->getInvateCode() + ]; $resp[] = $temp; } - return $this->json($extractor->operationSuccess($resp)); + + return $this->json([ + 'status' => 'success', + 'message' => 'عملیات با موفقیت انجام شد', + 'data' => [ + 'items' => $resp, + 'total' => (int) $totalItems, + 'page' => $page, + 'limit' => $limit, + 'totalPages' => ceil($totalItems / $limit) + ] + ]); } #[Route('/api/admin/settings/sms/info', name: 'admin_settings_sms_info')] diff --git a/hesabixCore/src/Controller/CostController.php b/hesabixCore/src/Controller/CostController.php index 858bc3b..5dca999 100644 --- a/hesabixCore/src/Controller/CostController.php +++ b/hesabixCore/src/Controller/CostController.php @@ -160,4 +160,155 @@ class CostController extends AbstractController 'series' => $series, ]); } + + #[Route('/api/cost/list/search', name: 'app_cost_list_search', methods: ['POST'])] + public function searchCostList( + Request $request, + Access $access, + EntityManagerInterface $entityManager, + Jdate $jdate + ): JsonResponse { + $acc = $access->hasRole('cost'); + if (!$acc) { + throw $this->createAccessDeniedException(); + } + + $params = json_decode($request->getContent(), true) ?? []; + + // پارامترهای ورودی + $filters = $params['filters'] ?? []; + $pagination = $params['pagination'] ?? ['page' => 1, 'limit' => 10]; + $sort = $params['sort'] ?? ['sortBy' => 'id', 'sortDesc' => true]; + $type = $params['type'] ?? 'cost'; + + // تنظیم پارامترهای صفحه‌بندی + $page = max(1, $pagination['page'] ?? 1); + $limit = max(1, min(100, $pagination['limit'] ?? 10)); + + // ساخت کوئری پایه + $queryBuilder = $entityManager->createQueryBuilder() + ->select('DISTINCT d.id, d.dateSubmit, d.date, d.type, d.code, d.des, d.amount') + ->addSelect('u.fullName as submitter') + ->from('App\Entity\HesabdariDoc', 'd') + ->leftJoin('d.submitter', 'u') + ->where('d.bid = :bid') + ->andWhere('d.year = :year') + ->andWhere('d.type = :type') + ->andWhere('d.money = :money') + ->setParameter('bid', $acc['bid']) + ->setParameter('year', $acc['year']) + ->setParameter('type', $type) + ->setParameter('money', $acc['money']); + + // اعمال فیلترها + if (!empty($filters)) { + if (isset($filters['search'])) { + $queryBuilder->leftJoin('d.hesabdariRows', 'r') + ->leftJoin('r.person', 'p') + ->leftJoin('r.ref', 't') + ->andWhere( + $queryBuilder->expr()->orX( + 'd.code LIKE :search', + 'd.des LIKE :search', + 'd.date LIKE :search', + 'd.amount LIKE :search', + 'p.nikename LIKE :search', + 't.name LIKE :search' + ) + ) + ->setParameter('search', "%{$filters['search']}%"); + } + + if (isset($filters['dateFrom'])) { + $queryBuilder->andWhere('d.date >= :dateFrom') + ->setParameter('dateFrom', $filters['dateFrom']); + } + + if (isset($filters['dateTo'])) { + $queryBuilder->andWhere('d.date <= :dateTo') + ->setParameter('dateTo', $filters['dateTo']); + } + + if (isset($filters['amount'])) { + $queryBuilder->andWhere('d.amount = :amount') + ->setParameter('amount', $filters['amount']); + } + } + + // اعمال مرتب‌سازی + $sortField = $sort['sortBy'] ?? 'id'; + $sortDirection = ($sort['sortDesc'] ?? true) ? 'DESC' : 'ASC'; + $queryBuilder->orderBy("d.$sortField", $sortDirection); + + // محاسبه تعداد کل نتایج + $totalItemsQuery = clone $queryBuilder; + $totalItems = $totalItemsQuery->select('COUNT(DISTINCT d.id)') + ->getQuery() + ->getSingleScalarResult(); + + // اعمال صفحه‌بندی + $queryBuilder->setFirstResult(($page - 1) * $limit) + ->setMaxResults($limit); + + $docs = $queryBuilder->getQuery()->getArrayResult(); + + $dataTemp = []; + foreach ($docs as $doc) { + $item = [ + 'id' => $doc['id'], + 'dateSubmit' => $doc['dateSubmit'], + 'date' => $doc['date'], + 'type' => $doc['type'], + 'code' => $doc['code'], + 'des' => $doc['des'], + 'amount' => $doc['amount'], + 'submitter' => $doc['submitter'] + ]; + + // دریافت اطلاعات مرکز هزینه و مبلغ + $costDetails = $entityManager->createQueryBuilder() + ->select('t.name as center_name, r.bd as amount') + ->from('App\Entity\HesabdariRow', 'r') + ->join('r.ref', 't') + ->where('r.doc = :docId') + ->andWhere('r.bd != 0') + ->setParameter('docId', $doc['id']) + ->getQuery() + ->getResult(); + + $item['costCenters'] = array_map(function($detail) { + return [ + 'name' => $detail['center_name'], + 'amount' => (int) $detail['amount'] + ]; + }, $costDetails); + + // دریافت اطلاعات شخص مرتبط + $personInfo = $entityManager->createQueryBuilder() + ->select('p.id, p.nikename, p.code') + ->from('App\Entity\HesabdariRow', 'r') + ->join('r.person', 'p') + ->where('r.doc = :docId') + ->andWhere('r.person IS NOT NULL') + ->setParameter('docId', $doc['id']) + ->setMaxResults(1) + ->getQuery() + ->getOneOrNullResult(); + + $item['person'] = $personInfo ? [ + 'id' => $personInfo['id'], + 'nikename' => $personInfo['nikename'], + 'code' => $personInfo['code'] + ] : null; + + $dataTemp[] = $item; + } + + return $this->json([ + 'items' => $dataTemp, + 'total' => (int) $totalItems, + 'page' => $page, + 'limit' => $limit + ]); + } } \ No newline at end of file diff --git a/hesabixCore/src/Controller/SellController.php b/hesabixCore/src/Controller/SellController.php index 0a320f4..ceb7815 100644 --- a/hesabixCore/src/Controller/SellController.php +++ b/hesabixCore/src/Controller/SellController.php @@ -358,201 +358,262 @@ class SellController extends AbstractController } #[Route('/api/sell/docs/search', name: 'app_sell_docs_search', methods: ['POST'])] - public function searchSellDocs( - Provider $provider, - Request $request, - Access $access, - Log $log, - EntityManagerInterface $entityManager, - Jdate $jdate - ): JsonResponse { - $acc = $access->hasRole('sell'); - if (!$acc) { - throw $this->createAccessDeniedException(); - } - - $params = json_decode($request->getContent(), true) ?? []; - $searchTerm = $params['search'] ?? ''; - $page = max(1, $params['page'] ?? 1); - $perPage = max(1, min(100, $params['perPage'] ?? 10)); - $types = $params['types'] ?? []; - $dateFilter = $params['dateFilter'] ?? 'all'; - - $queryBuilder = $entityManager->createQueryBuilder() - ->select('DISTINCT d.id, d.dateSubmit, d.date, d.type, d.code, d.des, d.amount') - ->addSelect('u.fullName as submitter') - ->addSelect('l.code as labelCode, l.label as labelLabel') - ->from(HesabdariDoc::class, 'd') - ->leftJoin('d.submitter', 'u') - ->leftJoin('d.InvoiceLabel', 'l') - ->where('d.bid = :bid') - ->andWhere('d.year = :year') - ->andWhere('d.type = :type') - ->andWhere('d.money = :money') - ->setParameter('bid', $acc['bid']) - ->setParameter('year', $acc['year']) - ->setParameter('type', 'sell') - ->setParameter('money', $acc['money']) - ->orderBy('d.id', 'DESC'); - - $today = $jdate->jdate('Y/m/d', time()); - if ($dateFilter === 'today') { - $queryBuilder->andWhere('d.date = :today') - ->setParameter('today', $today); - } elseif ($dateFilter === 'week') { - $weekStart = $jdate->jdate('Y/m/d', strtotime('-6 days')); - $queryBuilder->andWhere('d.date BETWEEN :weekStart AND :today') - ->setParameter('weekStart', $weekStart) - ->setParameter('today', $today); - } elseif ($dateFilter === 'month') { - $monthStart = $jdate->jdate('Y/m/01', time()); - $queryBuilder->andWhere('d.date BETWEEN :monthStart AND :today') - ->setParameter('monthStart', $monthStart) - ->setParameter('today', $today); - } - - if ($searchTerm) { - $queryBuilder->leftJoin('d.hesabdariRows', 'r') - ->leftJoin('r.person', 'p') - ->andWhere( - $queryBuilder->expr()->orX( - 'd.code LIKE :search', - 'd.des LIKE :search', - 'd.date LIKE :search', - 'd.amount LIKE :search', - 'p.nikename LIKE :search', - 'p.mobile LIKE :search' - ) - ) - ->setParameter('search', "%$searchTerm%"); - } - - if (!empty($types)) { - $queryBuilder->andWhere('l.code IN (:types)') - ->setParameter('types', $types); - } - - $totalItemsQuery = clone $queryBuilder; - $totalItems = $totalItemsQuery->select('COUNT(DISTINCT d.id)') - ->getQuery() - ->getSingleScalarResult(); - - $queryBuilder->setFirstResult(($page - 1) * $perPage) - ->setMaxResults($perPage); - - $docs = $queryBuilder->getQuery()->getArrayResult(); - - $dataTemp = []; - foreach ($docs as $doc) { - $item = [ - 'id' => $doc['id'], - 'dateSubmit' => $doc['dateSubmit'], - 'date' => $doc['date'], - 'type' => $doc['type'], - 'code' => $doc['code'], - 'des' => $doc['des'], - 'amount' => $doc['amount'], - 'submitter' => $doc['submitter'], - 'label' => $doc['labelCode'] ? [ - 'code' => $doc['labelCode'], - 'label' => $doc['labelLabel'] - ] : null, - ]; - - $mainRow = $entityManager->getRepository(HesabdariRow::class) - ->createQueryBuilder('r') - ->where('r.doc = :docId') - ->andWhere('r.person IS NOT NULL') - ->setParameter('docId', $doc['id']) - ->setMaxResults(1) - ->getQuery() - ->getOneOrNullResult(); - $item['person'] = $mainRow && $mainRow->getPerson() ? [ - 'id' => $mainRow->getPerson()->getId(), - 'nikename' => $mainRow->getPerson()->getNikename(), - 'code' => $mainRow->getPerson()->getCode() - ] : null; - - $relatedDocs = $entityManager->createQueryBuilder() - ->select('SUM(rd.amount)') - ->from(HesabdariDoc::class, 'rd') - ->join('rd.relatedDocs', 'r') - ->where('r.id = :docId') - ->setParameter('docId', $doc['id']) - ->getQuery() - ->getSingleScalarResult(); - $item['relatedDocsCount'] = $relatedDocs ? count($relatedDocs) : 0; - $item['relatedDocsPays'] = $relatedDocs ?: 0; - - $item['profit'] = $this->calculateProfit($doc['id'], $acc, $entityManager); - $item['discountAll'] = 0; - $item['transferCost'] = 0; - - $rows = $entityManager->getRepository(HesabdariRow::class)->findBy(['doc' => $doc]); - foreach ($rows as $row) { - if ($row->getRef()->getCode() == '104') - $item['discountAll'] = $row->getBd(); - elseif ($row->getRef()->getCode() == '61') - $item['transferCost'] = $row->getBs(); - } - - $dataTemp[] = $item; - } - - return $this->json([ - 'items' => $dataTemp, - 'total' => (int) $totalItems, - 'page' => $page, - 'perPage' => $perPage, - ]); +public function searchSellDocs( + Provider $provider, + Request $request, + Access $access, + Log $log, + EntityManagerInterface $entityManager, + Jdate $jdate +): JsonResponse { + $acc = $access->hasRole('sell'); + if (!$acc) { + throw $this->createAccessDeniedException(); } - private function calculateProfit(int $docId, array $acc, EntityManagerInterface $entityManager): int - { - $profit = 0; - $rows = $entityManager->getRepository(HesabdariRow::class)->findBy(['doc' => $docId]); - foreach ($rows as $item) { - if ($item->getCommdityCount() && $item->getBs()) { - $commodityId = $item->getCommodity() ? $item->getCommodity()->getId() : null; - if ($acc['bid']->getProfitCalctype() === 'lis') { - if ($commodityId) { - $last = $entityManager->getRepository(HesabdariRow::class) - ->findOneBy(['commodity' => $commodityId, 'bs' => 0], ['id' => 'DESC']); - if ($last) { - $price = $last->getBd() / $last->getCommdityCount(); - $profit += ((($item->getBs() / $item->getCommdityCount()) - $price) * $item->getCommdityCount()); - } else { - $profit += $item->getBs(); - } - } else { - $profit += $item->getBs(); - } - } elseif ($acc['bid']->getProfitCalctype() === 'simple') { - if ($item->getCommodity() && $item->getCommodity()->getPriceSell() !== null && $item->getCommodity()->getPriceBuy() !== null) { - $profit += (($item->getCommodity()->getPriceSell() - $item->getCommodity()->getPriceBuy()) * $item->getCommdityCount()); + $params = json_decode($request->getContent(), true) ?? []; + $searchTerm = $params['search'] ?? ''; + $page = max(1, $params['page'] ?? 1); + $perPage = max(1, min(100, $params['perPage'] ?? 10)); + $types = $params['types'] ?? []; + $dateFilter = $params['dateFilter'] ?? 'all'; + $sortBy = $params['sortBy'] ?? []; + + $queryBuilder = $entityManager->createQueryBuilder() + ->select('DISTINCT d.id, d.dateSubmit, d.date, d.type, d.code, d.des, d.amount') + ->addSelect('u.fullName as submitter') + ->addSelect('l.code as labelCode, l.label as labelLabel') + ->from(HesabdariDoc::class, 'd') + ->leftJoin('d.submitter', 'u') + ->leftJoin('d.InvoiceLabel', 'l') + ->leftJoin('d.hesabdariRows', 'r') + ->where('d.bid = :bid') + ->andWhere('d.year = :year') + ->andWhere('d.type = :type') + ->andWhere('d.money = :money') + ->setParameter('bid', $acc['bid']) + ->setParameter('year', $acc['year']) + ->setParameter('type', 'sell') + ->setParameter('money', $acc['money']); + + // اعمال فیلترهای تاریخ + $today = $jdate->jdate('Y/m/d', time()); + if ($dateFilter === 'today') { + $queryBuilder->andWhere('d.date = :today') + ->setParameter('today', $today); + } elseif ($dateFilter === 'week') { + $weekStart = $jdate->jdate('Y/m/d', strtotime('-6 days')); + $queryBuilder->andWhere('d.date BETWEEN :weekStart AND :today') + ->setParameter('weekStart', $weekStart) + ->setParameter('today', $today); + } elseif ($dateFilter === 'month') { + $monthStart = $jdate->jdate('Y/m/01', time()); + $queryBuilder->andWhere('d.date BETWEEN :monthStart AND :today') + ->setParameter('monthStart', $monthStart) + ->setParameter('today', $today); + } + + if ($searchTerm) { + $queryBuilder->leftJoin('r.person', 'p') + ->andWhere( + $queryBuilder->expr()->orX( + 'd.code LIKE :search', + 'd.des LIKE :search', + 'd.date LIKE :search', + 'd.amount LIKE :search', + 'p.nikename LIKE :search', + 'p.mobile LIKE :search' + ) + ) + ->setParameter('search', "%$searchTerm%"); + } + + if (!empty($types)) { + $queryBuilder->andWhere('l.code IN (:types)') + ->setParameter('types', $types); + } + + // فیلدهای معتبر برای مرتب‌سازی توی دیتابیس + $validDbFields = [ + 'id' => 'd.id', + 'dateSubmit' => 'd.dateSubmit', + 'date' => 'd.date', + 'type' => 'd.type', + 'code' => 'd.code', + 'des' => 'd.des', + 'amount' => 'd.amount', + 'mdate' => 'd.mdate', + 'plugin' => 'd.plugin', + 'refData' => 'd.refData', + 'shortlink' => 'd.shortlink', + 'status' => 'd.status', + 'submitter' => 'u.fullName', + 'label' => 'l.label', // از InvoiceLabel + ]; + + // اعمال مرتب‌سازی توی دیتابیس + if (!empty($sortBy)) { + foreach ($sortBy as $sort) { + $key = $sort['key'] ?? 'id'; + $direction = isset($sort['order']) && strtoupper($sort['order']) === 'DESC' ? 'DESC' : 'ASC'; + if ($key === 'profit' || $key === 'receivedAmount') { + continue; // این‌ها توی PHP مرتب می‌شن + } elseif (isset($validDbFields[$key])) { + $queryBuilder->addOrderBy($validDbFields[$key], $direction); + } + // اگه کلید معتبر نبود، نادیده گرفته می‌شه + } + } else { + $queryBuilder->orderBy('d.id', 'DESC'); + } + + $totalItemsQuery = clone $queryBuilder; + $totalItems = $totalItemsQuery->select('COUNT(DISTINCT d.id)') + ->getQuery() + ->getSingleScalarResult(); + + $queryBuilder->setFirstResult(($page - 1) * $perPage) + ->setMaxResults($perPage); + + $docs = $queryBuilder->getQuery()->getArrayResult(); + + $dataTemp = []; + foreach ($docs as $doc) { + $item = [ + 'id' => $doc['id'], + 'dateSubmit' => $doc['dateSubmit'], + 'date' => $doc['date'], + 'type' => $doc['type'], + 'code' => $doc['code'], + 'des' => $doc['des'], + 'amount' => $doc['amount'], + 'submitter' => $doc['submitter'], + 'label' => $doc['labelCode'] ? [ + 'code' => $doc['labelCode'], + 'label' => $doc['labelLabel'] + ] : null, + ]; + + $mainRow = $entityManager->getRepository(HesabdariRow::class) + ->createQueryBuilder('r') + ->where('r.doc = :docId') + ->andWhere('r.person IS NOT NULL') + ->setParameter('docId', $doc['id']) + ->setMaxResults(1) + ->getQuery() + ->getOneOrNullResult(); + $item['person'] = $mainRow && $mainRow->getPerson() ? [ + 'id' => $mainRow->getPerson()->getId(), + 'nikename' => $mainRow->getPerson()->getNikename(), + 'code' => $mainRow->getPerson()->getCode() + ] : null; + + // استفاده از SQL خام برای محاسبه پرداختی‌ها + $sql = " + SELECT SUM(rd.amount) as total_pays, COUNT(rd.id) as count_docs + FROM hesabdari_doc rd + JOIN hesabdari_doc_hesabdari_doc rel ON rel.hesabdari_doc_target = rd.id + WHERE rel.hesabdari_doc_source = :sourceDocId + AND rd.bid_id = :bidId + "; + $stmt = $entityManager->getConnection()->prepare($sql); + $stmt->bindValue('sourceDocId', $doc['id']); + $stmt->bindValue('bidId', $acc['bid']->getId()); + $result = $stmt->executeQuery()->fetchAssociative(); + + $relatedDocsPays = $result['total_pays'] ?? 0; + $relatedDocsCount = $result['count_docs'] ?? 0; + + $item['relatedDocsCount'] = (int) $relatedDocsCount; + $item['relatedDocsPays'] = $relatedDocsPays; + $item['profit'] = $this->calculateProfit($doc['id'], $acc, $entityManager); + $item['discountAll'] = 0; + $item['transferCost'] = 0; + + $rows = $entityManager->getRepository(HesabdariRow::class)->findBy(['doc' => $doc]); + foreach ($rows as $row) { + if ($row->getRef()->getCode() == '104') { + $item['discountAll'] = $row->getBd(); + } elseif ($row->getRef()->getCode() == '61') { + $item['transferCost'] = $row->getBs(); + } + } + + $dataTemp[] = $item; + } + + // مرتب‌سازی توی PHP برای profit و receivedAmount + if (!empty($sortBy)) { + foreach ($sortBy as $sort) { + $key = $sort['key'] ?? 'id'; + $direction = isset($sort['order']) && strtoupper($sort['order']) === 'DESC' ? SORT_DESC : SORT_ASC; + if ($key === 'profit') { + usort($dataTemp, function ($a, $b) use ($direction) { + return $direction === SORT_ASC ? $a['profit'] - $b['profit'] : $b['profit'] - $a['profit']; + }); + } elseif ($key === 'receivedAmount') { + usort($dataTemp, function ($a, $b) use ($direction) { + return $direction === SORT_ASC ? $a['relatedDocsPays'] - $b['relatedDocsPays'] : $b['relatedDocsPays'] - $a['relatedDocsPays']; + }); + } + } + } + + return $this->json([ + 'items' => $dataTemp, + 'total' => (int) $totalItems, + 'page' => $page, + 'perPage' => $perPage, + ]); +} + +// متد calculateProfit بدون تغییر +private function calculateProfit(int $docId, array $acc, EntityManagerInterface $entityManager): int +{ + $profit = 0; + $rows = $entityManager->getRepository(HesabdariRow::class)->findBy(['doc' => $docId]); + foreach ($rows as $item) { + if ($item->getCommdityCount() && $item->getBs()) { + $commodityId = $item->getCommodity() ? $item->getCommodity()->getId() : null; + if ($acc['bid']->getProfitCalctype() === 'lis') { + if ($commodityId) { + $last = $entityManager->getRepository(HesabdariRow::class) + ->findOneBy(['commodity' => $commodityId, 'bs' => 0], ['id' => 'DESC']); + if ($last) { + $price = $last->getBd() / $last->getCommdityCount(); + $profit += ((($item->getBs() / $item->getCommdityCount()) - $price) * $item->getCommdityCount()); } else { $profit += $item->getBs(); } } else { - if ($commodityId) { - $lasts = $entityManager->getRepository(HesabdariRow::class) - ->findBy(['commodity' => $commodityId, 'bs' => 0], ['id' => 'DESC']); - $avg = array_sum(array_map(fn($last) => $last->getBd(), $lasts)); - $count = array_sum(array_map(fn($last) => $last->getCommdityCount(), $lasts)); - if ($count != 0) { - $price = $avg / $count; - $profit += ((($item->getBs() / $item->getCommdityCount()) - $price) * $item->getCommdityCount()); - } else { - $profit += $item->getBs(); - } + $profit += $item->getBs(); + } + } elseif ($acc['bid']->getProfitCalctype() === 'simple') { + if ($item->getCommodity() && $item->getCommodity()->getPriceSell() !== null && $item->getCommodity()->getPriceBuy() !== null) { + $profit += (($item->getCommodity()->getPriceSell() - $item->getCommodity()->getPriceBuy()) * $item->getCommdityCount()); + } else { + $profit += $item->getBs(); + } + } else { + if ($commodityId) { + $lasts = $entityManager->getRepository(HesabdariRow::class) + ->findBy(['commodity' => $commodityId, 'bs' => 0], ['id' => 'DESC']); + $avg = array_sum(array_map(fn($last) => $last->getBd(), $lasts)); + $count = array_sum(array_map(fn($last) => $last->getCommdityCount(), $lasts)); + if ($count != 0) { + $price = $avg / $count; + $profit += ((($item->getBs() / $item->getCommdityCount()) - $price) * $item->getCommdityCount()); } else { $profit += $item->getBs(); } + } else { + $profit += $item->getBs(); } } } - return round($profit); } + return round($profit); +} #[Route('/api/sell/rows/{code}', name: 'app_sell_rows', methods: ['GET'])] public function getSellRows( diff --git a/hesabixCore/src/Entity/HesabdariDoc.php b/hesabixCore/src/Entity/HesabdariDoc.php index af194c8..9fe8a4c 100644 --- a/hesabixCore/src/Entity/HesabdariDoc.php +++ b/hesabixCore/src/Entity/HesabdariDoc.php @@ -50,7 +50,7 @@ class HesabdariDoc #[ORM\Column(length: 255, nullable: true)] private ?string $des = null; - #[ORM\Column(type: 'string', length: 255,nullable: true)] + #[ORM\Column(type: 'string', length: 255, nullable: true)] private int $amount = 0; #[ORM\ManyToOne] @@ -79,6 +79,11 @@ class HesabdariDoc private ?WalletTransaction $walletTransaction = null; #[ORM\ManyToMany(targetEntity: self::class)] + #[ORM\JoinTable( + name: 'hesabdari_doc_hesabdari_doc', + joinColumns: [new ORM\JoinColumn(name: 'hesabdari_doc_source', referencedColumnName: 'id')], + inverseJoinColumns: [new ORM\JoinColumn(name: 'hesabdari_doc_target', referencedColumnName: 'id')] + )] #[Ignore] private Collection $relatedDocs; @@ -89,7 +94,7 @@ class HesabdariDoc #[Ignore] private Collection $storeroomTickets; - #[ORM\Column(type: Types::ARRAY, nullable: true)] + #[ORM\Column(type: Types::ARRAY , nullable: true)] private ?array $tempStatus = null; #[ORM\OneToMany(mappedBy: 'doc', targetEntity: Log::class)] @@ -370,7 +375,7 @@ class HesabdariDoc return $this; } - /** + /** * @return Collection */ public function getRelatedDocs(): Collection @@ -394,6 +399,7 @@ class HesabdariDoc return $this; } + public function getStatus(): ?string { return $this->status;