bug fix in lists
This commit is contained in:
parent
9df5a5864b
commit
5470b82951
|
@ -172,27 +172,104 @@ class AdminController extends AbstractController
|
||||||
return $this->json($extractor->operationSuccess($resp));
|
return $this->json($extractor->operationSuccess($resp));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/api/admin/users/search', name: 'admin_users_list_search')]
|
#[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, UserPasswordHasherInterface $userPasswordHasher, EntityManagerInterface $entityManager, Request $request): Response
|
public function admin_users_list_search(
|
||||||
{
|
Extractor $extractor,
|
||||||
$params = [];
|
Jdate $jdate,
|
||||||
if ($content = $request->getContent()) {
|
#[CurrentUser] ?User $user,
|
||||||
$params = json_decode($content, true);
|
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 = [];
|
$resp = [];
|
||||||
foreach ($items as $item) {
|
foreach ($items as $item) {
|
||||||
$temp = [];
|
$temp = [
|
||||||
$temp['id'] = $item->getId();
|
'id' => $item->getId(),
|
||||||
$temp['email'] = $item->getEmail();
|
'email' => $item->getEmail(),
|
||||||
$temp['mobile'] = $item->getMobile();
|
'mobile' => $item->getMobile(),
|
||||||
$temp['fullname'] = $item->getFullName();
|
'fullname' => $item->getFullName(),
|
||||||
$temp['status'] = $item->isActive();
|
'status' => $item->isActive(),
|
||||||
$temp['dateRegister'] = $jdate->jdate('Y/n/d', $item->getDateRegister());
|
'dateRegister' => $jdate->jdate('Y/n/d', $item->getDateRegister()),
|
||||||
$temp['bidCount'] = count($entityManager->getRepository(Business::class)->findBy(['owner' => $item]));
|
'bidCount' => count($entityManager->getRepository(Business::class)->findBy(['owner' => $item])),
|
||||||
|
'roles' => $item->getRoles(),
|
||||||
|
'inviteCode' => $item->getInvateCode()
|
||||||
|
];
|
||||||
$resp[] = $temp;
|
$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')]
|
#[Route('/api/admin/settings/sms/info', name: 'admin_settings_sms_info')]
|
||||||
|
|
|
@ -160,4 +160,155 @@ class CostController extends AbstractController
|
||||||
'series' => $series,
|
'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
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -358,201 +358,262 @@ class SellController extends AbstractController
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/api/sell/docs/search', name: 'app_sell_docs_search', methods: ['POST'])]
|
#[Route('/api/sell/docs/search', name: 'app_sell_docs_search', methods: ['POST'])]
|
||||||
public function searchSellDocs(
|
public function searchSellDocs(
|
||||||
Provider $provider,
|
Provider $provider,
|
||||||
Request $request,
|
Request $request,
|
||||||
Access $access,
|
Access $access,
|
||||||
Log $log,
|
Log $log,
|
||||||
EntityManagerInterface $entityManager,
|
EntityManagerInterface $entityManager,
|
||||||
Jdate $jdate
|
Jdate $jdate
|
||||||
): JsonResponse {
|
): JsonResponse {
|
||||||
$acc = $access->hasRole('sell');
|
$acc = $access->hasRole('sell');
|
||||||
if (!$acc) {
|
if (!$acc) {
|
||||||
throw $this->createAccessDeniedException();
|
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,
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function calculateProfit(int $docId, array $acc, EntityManagerInterface $entityManager): int
|
$params = json_decode($request->getContent(), true) ?? [];
|
||||||
{
|
$searchTerm = $params['search'] ?? '';
|
||||||
$profit = 0;
|
$page = max(1, $params['page'] ?? 1);
|
||||||
$rows = $entityManager->getRepository(HesabdariRow::class)->findBy(['doc' => $docId]);
|
$perPage = max(1, min(100, $params['perPage'] ?? 10));
|
||||||
foreach ($rows as $item) {
|
$types = $params['types'] ?? [];
|
||||||
if ($item->getCommdityCount() && $item->getBs()) {
|
$dateFilter = $params['dateFilter'] ?? 'all';
|
||||||
$commodityId = $item->getCommodity() ? $item->getCommodity()->getId() : null;
|
$sortBy = $params['sortBy'] ?? [];
|
||||||
if ($acc['bid']->getProfitCalctype() === 'lis') {
|
|
||||||
if ($commodityId) {
|
$queryBuilder = $entityManager->createQueryBuilder()
|
||||||
$last = $entityManager->getRepository(HesabdariRow::class)
|
->select('DISTINCT d.id, d.dateSubmit, d.date, d.type, d.code, d.des, d.amount')
|
||||||
->findOneBy(['commodity' => $commodityId, 'bs' => 0], ['id' => 'DESC']);
|
->addSelect('u.fullName as submitter')
|
||||||
if ($last) {
|
->addSelect('l.code as labelCode, l.label as labelLabel')
|
||||||
$price = $last->getBd() / $last->getCommdityCount();
|
->from(HesabdariDoc::class, 'd')
|
||||||
$profit += ((($item->getBs() / $item->getCommdityCount()) - $price) * $item->getCommdityCount());
|
->leftJoin('d.submitter', 'u')
|
||||||
} else {
|
->leftJoin('d.InvoiceLabel', 'l')
|
||||||
$profit += $item->getBs();
|
->leftJoin('d.hesabdariRows', 'r')
|
||||||
}
|
->where('d.bid = :bid')
|
||||||
} else {
|
->andWhere('d.year = :year')
|
||||||
$profit += $item->getBs();
|
->andWhere('d.type = :type')
|
||||||
}
|
->andWhere('d.money = :money')
|
||||||
} elseif ($acc['bid']->getProfitCalctype() === 'simple') {
|
->setParameter('bid', $acc['bid'])
|
||||||
if ($item->getCommodity() && $item->getCommodity()->getPriceSell() !== null && $item->getCommodity()->getPriceBuy() !== null) {
|
->setParameter('year', $acc['year'])
|
||||||
$profit += (($item->getCommodity()->getPriceSell() - $item->getCommodity()->getPriceBuy()) * $item->getCommdityCount());
|
->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 {
|
} else {
|
||||||
$profit += $item->getBs();
|
$profit += $item->getBs();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ($commodityId) {
|
$profit += $item->getBs();
|
||||||
$lasts = $entityManager->getRepository(HesabdariRow::class)
|
}
|
||||||
->findBy(['commodity' => $commodityId, 'bs' => 0], ['id' => 'DESC']);
|
} elseif ($acc['bid']->getProfitCalctype() === 'simple') {
|
||||||
$avg = array_sum(array_map(fn($last) => $last->getBd(), $lasts));
|
if ($item->getCommodity() && $item->getCommodity()->getPriceSell() !== null && $item->getCommodity()->getPriceBuy() !== null) {
|
||||||
$count = array_sum(array_map(fn($last) => $last->getCommdityCount(), $lasts));
|
$profit += (($item->getCommodity()->getPriceSell() - $item->getCommodity()->getPriceBuy()) * $item->getCommdityCount());
|
||||||
if ($count != 0) {
|
} else {
|
||||||
$price = $avg / $count;
|
$profit += $item->getBs();
|
||||||
$profit += ((($item->getBs() / $item->getCommdityCount()) - $price) * $item->getCommdityCount());
|
}
|
||||||
} else {
|
} else {
|
||||||
$profit += $item->getBs();
|
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 {
|
} else {
|
||||||
$profit += $item->getBs();
|
$profit += $item->getBs();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
$profit += $item->getBs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return round($profit);
|
|
||||||
}
|
}
|
||||||
|
return round($profit);
|
||||||
|
}
|
||||||
|
|
||||||
#[Route('/api/sell/rows/{code}', name: 'app_sell_rows', methods: ['GET'])]
|
#[Route('/api/sell/rows/{code}', name: 'app_sell_rows', methods: ['GET'])]
|
||||||
public function getSellRows(
|
public function getSellRows(
|
||||||
|
|
|
@ -50,7 +50,7 @@ class HesabdariDoc
|
||||||
#[ORM\Column(length: 255, nullable: true)]
|
#[ORM\Column(length: 255, nullable: true)]
|
||||||
private ?string $des = null;
|
private ?string $des = null;
|
||||||
|
|
||||||
#[ORM\Column(type: 'string', length: 255,nullable: true)]
|
#[ORM\Column(type: 'string', length: 255, nullable: true)]
|
||||||
private int $amount = 0;
|
private int $amount = 0;
|
||||||
|
|
||||||
#[ORM\ManyToOne]
|
#[ORM\ManyToOne]
|
||||||
|
@ -79,6 +79,11 @@ class HesabdariDoc
|
||||||
private ?WalletTransaction $walletTransaction = null;
|
private ?WalletTransaction $walletTransaction = null;
|
||||||
|
|
||||||
#[ORM\ManyToMany(targetEntity: self::class)]
|
#[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]
|
#[Ignore]
|
||||||
private Collection $relatedDocs;
|
private Collection $relatedDocs;
|
||||||
|
|
||||||
|
@ -89,7 +94,7 @@ class HesabdariDoc
|
||||||
#[Ignore]
|
#[Ignore]
|
||||||
private Collection $storeroomTickets;
|
private Collection $storeroomTickets;
|
||||||
|
|
||||||
#[ORM\Column(type: Types::ARRAY, nullable: true)]
|
#[ORM\Column(type: Types::ARRAY , nullable: true)]
|
||||||
private ?array $tempStatus = null;
|
private ?array $tempStatus = null;
|
||||||
|
|
||||||
#[ORM\OneToMany(mappedBy: 'doc', targetEntity: Log::class)]
|
#[ORM\OneToMany(mappedBy: 'doc', targetEntity: Log::class)]
|
||||||
|
@ -370,7 +375,7 @@ class HesabdariDoc
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Collection<int, self>
|
* @return Collection<int, self>
|
||||||
*/
|
*/
|
||||||
public function getRelatedDocs(): Collection
|
public function getRelatedDocs(): Collection
|
||||||
|
@ -394,6 +399,7 @@ class HesabdariDoc
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function getStatus(): ?string
|
public function getStatus(): ?string
|
||||||
{
|
{
|
||||||
return $this->status;
|
return $this->status;
|
||||||
|
|
Loading…
Reference in a new issue