bug fix in persons s/r

This commit is contained in:
Hesabix 2025-08-13 00:58:38 +00:00
parent 63472c1d13
commit 290b272872

View file

@ -897,10 +897,14 @@ class PersonsController extends AbstractController
$queryBuilder->orderBy('d.des', $sortDirection);
break;
case 'persons':
// برای سورت بر اساس اشخاص
if (empty($search)) {
$queryBuilder->leftJoin('d.hesabdariRows', 'hr_person')
->leftJoin('hr_person.person', 'p')
->groupBy('d.id, d.date, d.code, d.des, d.amount, p.nikename')
->orderBy('p.nikename', $sortDirection);
->leftJoin('hr_person.person', 'p');
}
// استفاده از MIN برای جلوگیری از مشکل GROUP BY
$queryBuilder->groupBy('d.id, d.date, d.code, d.des, d.amount')
->orderBy('MIN(p.nikename)', $sortDirection);
break;
case 'accounts':
// سورت بر اساس طرف حساب‌ها (بانک، صندوق، تنخواه)
@ -908,8 +912,8 @@ class PersonsController extends AbstractController
->leftJoin('hr_account.bank', 'ba')
->leftJoin('hr_account.cashdesk', 'cd')
->leftJoin('hr_account.salary', 's')
->groupBy('d.id, d.date, d.code, d.des, d.amount, ba.name, cd.name, s.name')
->orderBy('COALESCE(ba.name, cd.name, s.name)', $sortDirection);
->groupBy('d.id, d.date, d.code, d.des, d.amount')
->orderBy('CASE WHEN ba.name IS NOT NULL THEN ba.name WHEN cd.name IS NOT NULL THEN cd.name WHEN s.name IS NOT NULL THEN s.name ELSE \'\' END', $sortDirection);
break;
default:
$queryBuilder->orderBy('d.id', 'DESC');
@ -923,8 +927,67 @@ class PersonsController extends AbstractController
->setParameter('ids', $ids);
}
// دریافت تعداد کل رکوردها
$totalItems = $queryBuilder->select('COUNT(d.id)')
// دریافت تعداد کل رکوردها - ایجاد کوئری جدید بدون GROUP BY
$totalQueryBuilder = $entityManager->getRepository(HesabdariDoc::class)->createQueryBuilder('d')
->where('d.bid = :bid')
->andWhere('d.type = :type')
->andWhere('d.year = :year')
->andWhere('d.money = :money')
->setParameter('bid', $acc['bid'])
->setParameter('type', 'person_receive')
->setParameter('year', $acc['year'])
->setParameter('money', $acc['money']);
// اعمال فیلترهای جست‌وجو و تاریخ
if (isset($params['search']) && !empty($params['search'])) {
$totalQueryBuilder->leftJoin('d.hesabdariRows', 'hr')
->leftJoin('hr.person', 'p')
->andWhere(
$totalQueryBuilder->expr()->orX(
'd.code LIKE :search',
'd.des LIKE :search',
'p.nikename LIKE :search'
)
)->setParameter('search', "%{$params['search']}%");
}
// فیلتر تاریخ
if (isset($params['dateFilter']) && $params['dateFilter'] !== 'all') {
$today = $jdate->GetTodayDate();
switch ($params['dateFilter']) {
case 'today':
$totalQueryBuilder->andWhere('d.date = :today')
->setParameter('today', $today);
break;
case 'thisWeek':
$dayOfWeek = (int) $jdate->jdate('w', time());
$startOfWeek = $jdate->shamsiDate(0, 0, -$dayOfWeek);
$endOfWeek = $jdate->shamsiDate(0, 0, 6 - $dayOfWeek);
$totalQueryBuilder->andWhere('d.date BETWEEN :start AND :end')
->setParameter('start', $startOfWeek)
->setParameter('end', $endOfWeek);
break;
case 'thisMonth':
$currentYear = (int) $jdate->jdate('Y', time());
$currentMonth = (int) $jdate->jdate('n', time());
$daysInMonth = (int) $jdate->jdate('t', time());
$startOfMonth = sprintf('%d/%02d/01', $currentYear, $currentMonth);
$endOfMonth = sprintf('%d/%02d/%02d', $currentYear, $currentMonth, $daysInMonth);
$totalQueryBuilder->andWhere('d.date BETWEEN :start AND :end')
->setParameter('start', $startOfMonth)
->setParameter('end', $endOfMonth);
break;
}
}
// اگر آیتم‌های خاصی درخواست شده‌اند
if (array_key_exists('items', $params)) {
$ids = array_map(function($item) { return $item['id']; }, $params['items']);
$totalQueryBuilder->andWhere('d.id IN (:ids)')
->setParameter('ids', $ids);
}
$totalItems = (int) $totalQueryBuilder->select('COUNT(d.id)')
->getQuery()
->getSingleScalarResult();
@ -1089,6 +1152,60 @@ class PersonsController extends AbstractController
break;
}
// محاسبه تعداد کل قبل از اعمال GROUP BY
$totalQueryBuilder = $entityManager->getRepository(HesabdariDoc::class)->createQueryBuilder('d')
->where('d.bid = :bid')
->andWhere('d.type = :type')
->andWhere('d.year = :year')
->andWhere('d.money = :money')
->setParameter('bid', $acc['bid'])
->setParameter('type', 'person_receive')
->setParameter('year', $acc['year'])
->setParameter('money', $acc['money']);
// اعمال فیلترهای جست‌وجو و تاریخ برای کوئری تعداد
if (!empty($search)) {
$totalQueryBuilder->leftJoin('d.hesabdariRows', 'hr')
->leftJoin('hr.person', 'p')
->andWhere(
$totalQueryBuilder->expr()->orX(
'd.code LIKE :search',
'd.des LIKE :search',
'p.nikename LIKE :search'
)
)->setParameter('search', "%$search%");
}
// فیلتر تاریخ برای کوئری تعداد
switch ($dateFilter) {
case 'today':
$totalQueryBuilder->andWhere('d.date = :today')
->setParameter('today', $today);
break;
case 'thisWeek':
$dayOfWeek = (int) $jdate->jdate('w', time());
$startOfWeek = $jdate->shamsiDate(0, 0, -$dayOfWeek);
$endOfWeek = $jdate->shamsiDate(0, 0, 6 - $dayOfWeek);
$totalQueryBuilder->andWhere('d.date BETWEEN :start AND :end')
->setParameter('start', $startOfWeek)
->setParameter('end', $endOfWeek);
break;
case 'thisMonth':
$currentYear = (int) $jdate->jdate('Y', time());
$currentMonth = (int) $jdate->jdate('n', time());
$daysInMonth = (int) $jdate->jdate('t', time());
$startOfMonth = sprintf('%d/%02d/01', $currentYear, $currentMonth);
$endOfMonth = sprintf('%d/%02d/%02d', $currentYear, $currentMonth, $daysInMonth);
$totalQueryBuilder->andWhere('d.date BETWEEN :start AND :end')
->setParameter('start', $startOfMonth)
->setParameter('end', $endOfMonth);
break;
}
$total = (int) $totalQueryBuilder->select('COUNT(d.id)')
->getQuery()
->getSingleScalarResult();
// اعمال سورت
$sortDirection = $sortDesc ? 'DESC' : 'ASC';
switch ($sortBy) {
@ -1106,10 +1223,14 @@ class PersonsController extends AbstractController
$queryBuilder->orderBy('d.des', $sortDirection);
break;
case 'persons':
// برای سورت بر اساس اشخاص
if (empty($search)) {
$queryBuilder->leftJoin('d.hesabdariRows', 'hr_person')
->leftJoin('hr_person.person', 'p')
->groupBy('d.id, d.date, d.code, d.des, d.amount, p.nikename')
->orderBy('p.nikename', $sortDirection);
->leftJoin('hr_person.person', 'p');
}
// استفاده از MIN برای جلوگیری از مشکل GROUP BY
$queryBuilder->groupBy('d.id, d.date, d.code, d.des, d.amount')
->orderBy('MIN(p.nikename)', $sortDirection);
break;
case 'accounts':
// سورت بر اساس طرف حساب‌ها (بانک، صندوق، تنخواه)
@ -1117,21 +1238,14 @@ class PersonsController extends AbstractController
->leftJoin('hr_account.bank', 'ba')
->leftJoin('hr_account.cashdesk', 'cd')
->leftJoin('hr_account.salary', 's')
->groupBy('d.id, d.date, d.code, d.des, d.amount, ba.name, cd.name, s.name')
->orderBy('COALESCE(ba.name, cd.name, s.name)', $sortDirection);
->groupBy('d.id, d.date, d.code, d.des, d.amount')
->orderBy('CASE WHEN ba.name IS NOT NULL THEN ba.name WHEN cd.name IS NOT NULL THEN cd.name WHEN s.name IS NOT NULL THEN s.name ELSE \'\' END', $sortDirection);
break;
default:
$queryBuilder->orderBy('d.id', 'DESC');
break;
}
// محاسبه تعداد کل
$totalQuery = (clone $queryBuilder)
->select('COUNT(DISTINCT d.id) as total')
->getQuery()
->getSingleResult();
$total = (int) $totalQuery['total'];
// گرفتن اسناد با صفحه‌بندی
$docs = $queryBuilder
->setFirstResult(($page - 1) * $itemsPerPage)
@ -1754,10 +1868,14 @@ class PersonsController extends AbstractController
$queryBuilder->orderBy('d.des', $sortDirection);
break;
case 'persons':
// برای سورت بر اساس اشخاص
if (empty($search)) {
$queryBuilder->leftJoin('d.hesabdariRows', 'hr_person')
->leftJoin('hr_person.person', 'p')
->groupBy('d.id, d.date, d.code, d.des, d.amount, p.nikename')
->orderBy('p.nikename', $sortDirection);
->leftJoin('hr_person.person', 'p');
}
// استفاده از MIN برای جلوگیری از مشکل GROUP BY
$queryBuilder->groupBy('d.id, d.date, d.code, d.des, d.amount')
->orderBy('MIN(p.nikename)', $sortDirection);
break;
case 'accounts':
// سورت بر اساس طرف حساب‌ها (بانک، صندوق، تنخواه)
@ -1765,8 +1883,8 @@ class PersonsController extends AbstractController
->leftJoin('hr_account.bank', 'ba')
->leftJoin('hr_account.cashdesk', 'cd')
->leftJoin('hr_account.salary', 's')
->groupBy('d.id, d.date, d.code, d.des, d.amount, ba.name, cd.name, s.name')
->orderBy('COALESCE(ba.name, cd.name, s.name)', $sortDirection);
->groupBy('d.id, d.date, d.code, d.des, d.amount')
->orderBy('CASE WHEN ba.name IS NOT NULL THEN ba.name WHEN cd.name IS NOT NULL THEN cd.name WHEN s.name IS NOT NULL THEN s.name ELSE \'\' END', $sortDirection);
break;
default:
$queryBuilder->orderBy('d.id', 'DESC');
@ -1916,10 +2034,14 @@ class PersonsController extends AbstractController
$queryBuilder->orderBy('d.des', $sortDirection);
break;
case 'persons':
// برای سورت بر اساس اشخاص
if (empty($search)) {
$queryBuilder->leftJoin('d.hesabdariRows', 'hr_person')
->leftJoin('hr_person.person', 'p')
->groupBy('d.id, d.date, d.code, d.des, d.amount, p.nikename')
->orderBy('p.nikename', $sortDirection);
->leftJoin('hr_person.person', 'p');
}
// استفاده از MIN برای جلوگیری از مشکل GROUP BY
$queryBuilder->groupBy('d.id, d.date, d.code, d.des, d.amount')
->orderBy('MIN(p.nikename)', $sortDirection);
break;
case 'accounts':
// سورت بر اساس طرف حساب‌ها (بانک، صندوق، تنخواه)
@ -1927,8 +2049,8 @@ class PersonsController extends AbstractController
->leftJoin('hr_account.bank', 'ba')
->leftJoin('hr_account.cashdesk', 'cd')
->leftJoin('hr_account.salary', 's')
->groupBy('d.id, d.date, d.code, d.des, d.amount, ba.name, cd.name, s.name')
->orderBy('COALESCE(ba.name, cd.name, s.name)', $sortDirection);
->groupBy('d.id, d.date, d.code, d.des, d.amount')
->orderBy('CASE WHEN ba.name IS NOT NULL THEN ba.name WHEN cd.name IS NOT NULL THEN cd.name WHEN s.name IS NOT NULL THEN s.name ELSE \'\' END', $sortDirection);
break;
default:
$queryBuilder->orderBy('d.id', 'DESC');
@ -1942,8 +2064,67 @@ class PersonsController extends AbstractController
->setParameter('ids', $ids);
}
// دریافت تعداد کل رکوردها
$totalItems = $queryBuilder->select('COUNT(d.id)')
// دریافت تعداد کل رکوردها - ایجاد کوئری جدید بدون GROUP BY
$totalQueryBuilder = $entityManager->getRepository(HesabdariDoc::class)->createQueryBuilder('d')
->where('d.bid = :bid')
->andWhere('d.type = :type')
->andWhere('d.year = :year')
->andWhere('d.money = :money')
->setParameter('bid', $acc['bid'])
->setParameter('type', 'person_send')
->setParameter('year', $acc['year'])
->setParameter('money', $acc['money']);
// اعمال فیلترهای جست‌وجو و تاریخ
if (isset($params['search']) && !empty($params['search'])) {
$totalQueryBuilder->leftJoin('d.hesabdariRows', 'hr')
->leftJoin('hr.person', 'p')
->andWhere(
$totalQueryBuilder->expr()->orX(
'd.code LIKE :search',
'd.des LIKE :search',
'p.nikename LIKE :search'
)
)->setParameter('search', "%{$params['search']}%");
}
// فیلتر تاریخ
if (isset($params['dateFilter']) && $params['dateFilter'] !== 'all') {
$today = $jdate->GetTodayDate();
switch ($params['dateFilter']) {
case 'today':
$totalQueryBuilder->andWhere('d.date = :today')
->setParameter('today', $today);
break;
case 'thisWeek':
$dayOfWeek = (int) $jdate->jdate('w', time());
$startOfWeek = $jdate->shamsiDate(0, 0, -$dayOfWeek);
$endOfWeek = $jdate->shamsiDate(0, 0, 6 - $dayOfWeek);
$totalQueryBuilder->andWhere('d.date BETWEEN :start AND :end')
->setParameter('start', $startOfWeek)
->setParameter('end', $endOfWeek);
break;
case 'thisMonth':
$currentYear = (int) $jdate->jdate('Y', time());
$currentMonth = (int) $jdate->jdate('n', time());
$daysInMonth = (int) $jdate->jdate('t', time());
$startOfMonth = sprintf('%d/%02d/01', $currentYear, $currentMonth);
$endOfMonth = sprintf('%d/%02d/%02d', $currentYear, $currentMonth, $daysInMonth);
$totalQueryBuilder->andWhere('d.date BETWEEN :start AND :end')
->setParameter('start', $startOfMonth)
->setParameter('end', $endOfMonth);
break;
}
}
// اگر آیتم‌های خاصی درخواست شده‌اند
if (array_key_exists('items', $params)) {
$ids = array_map(function($item) { return $item['id']; }, $params['items']);
$totalQueryBuilder->andWhere('d.id IN (:ids)')
->setParameter('ids', $ids);
}
$totalItems = (int) $totalQueryBuilder->select('COUNT(d.id)')
->getQuery()
->getSingleScalarResult();
@ -2014,4 +2195,282 @@ class PersonsController extends AbstractController
]);
}
#[Route('/api/person/send/list/search', name: 'app_persons_send_list_search', methods: ['POST'])]
public function app_persons_send_list_search(
Request $request,
Access $access,
EntityManagerInterface $entityManager,
Jdate $jdate
): JsonResponse {
$acc = $access->hasRole('getpay');
if (!$acc) {
throw $this->createAccessDeniedException();
}
// دریافت پارامترها
$params = json_decode($request->getContent(), true) ?? [];
$page = (int) ($params['page'] ?? 1);
$itemsPerPage = (int) ($params['itemsPerPage'] ?? 10);
$search = $params['search'] ?? '';
$dateFilter = $params['dateFilter'] ?? 'all';
// پردازش پارامترهای سورت
$sortBy = 'id';
$sortDesc = true;
if (isset($params['sortBy'])) {
if (is_array($params['sortBy']) && !empty($params['sortBy'])) {
// فرمت جدید: [{"key":"date","order":"asc"}]
$sortBy = $params['sortBy'][0]['key'] ?? 'id';
$sortDesc = ($params['sortBy'][0]['order'] ?? 'desc') === 'desc';
} else {
// فرمت قدیمی: "date"
$sortBy = $params['sortBy'];
}
}
if (isset($params['sortDesc'])) {
$sortDesc = (bool) $params['sortDesc'];
}
// کوئری پایه برای اسناد
$queryBuilder = $entityManager->getRepository(HesabdariDoc::class)
->createQueryBuilder('d')
->select('DISTINCT d.id, d.date, d.code, d.des, d.amount')
->where('d.bid = :bid')
->andWhere('d.type = :type')
->andWhere('d.year = :year')
->andWhere('d.money = :money')
->setParameter('bid', $acc['bid'])
->setParameter('type', 'person_send')
->setParameter('year', $acc['year'])
->setParameter('money', $acc['money']);
// جست‌وجو
if (!empty($search)) {
$queryBuilder->leftJoin('d.hesabdariRows', 'hr')
->leftJoin('hr.person', 'p')
->andWhere(
$queryBuilder->expr()->orX(
'd.code LIKE :search',
'd.des LIKE :search',
'p.nikename LIKE :search'
)
)->setParameter('search', "%$search%");
}
// فیلتر تاریخ
$today = $jdate->GetTodayDate();
switch ($dateFilter) {
case 'today':
$queryBuilder->andWhere('d.date = :today')
->setParameter('today', $today);
break;
case 'thisWeek':
$dayOfWeek = (int) $jdate->jdate('w', time());
$startOfWeek = $jdate->shamsiDate(0, 0, -$dayOfWeek);
$endOfWeek = $jdate->shamsiDate(0, 0, 6 - $dayOfWeek);
$queryBuilder->andWhere('d.date BETWEEN :start AND :end')
->setParameter('start', $startOfWeek)
->setParameter('end', $endOfWeek);
break;
case 'thisMonth':
$currentYear = (int) $jdate->jdate('Y', time());
$currentMonth = (int) $jdate->jdate('n', time());
$daysInMonth = (int) $jdate->jdate('t', time());
$startOfMonth = sprintf('%d/%02d/01', $currentYear, $currentMonth);
$endOfMonth = sprintf('%d/%02d/%02d', $currentYear, $currentMonth, $daysInMonth);
$queryBuilder->andWhere('d.date BETWEEN :start AND :end')
->setParameter('start', $startOfMonth)
->setParameter('end', $endOfMonth);
break;
case 'all':
default:
break;
}
// محاسبه تعداد کل قبل از اعمال GROUP BY
$totalQueryBuilder = $entityManager->getRepository(HesabdariDoc::class)->createQueryBuilder('d')
->where('d.bid = :bid')
->andWhere('d.type = :type')
->andWhere('d.year = :year')
->andWhere('d.money = :money')
->setParameter('bid', $acc['bid'])
->setParameter('type', 'person_send')
->setParameter('year', $acc['year'])
->setParameter('money', $acc['money']);
// اعمال فیلترهای جست‌وجو و تاریخ برای کوئری تعداد
if (!empty($search)) {
$totalQueryBuilder->leftJoin('d.hesabdariRows', 'hr')
->leftJoin('hr.person', 'p')
->andWhere(
$totalQueryBuilder->expr()->orX(
'd.code LIKE :search',
'd.des LIKE :search',
'p.nikename LIKE :search'
)
)->setParameter('search', "%$search%");
}
// فیلتر تاریخ برای کوئری تعداد
switch ($dateFilter) {
case 'today':
$totalQueryBuilder->andWhere('d.date = :today')
->setParameter('today', $today);
break;
case 'thisWeek':
$dayOfWeek = (int) $jdate->jdate('w', time());
$startOfWeek = $jdate->shamsiDate(0, 0, -$dayOfWeek);
$endOfWeek = $jdate->shamsiDate(0, 0, 6 - $dayOfWeek);
$totalQueryBuilder->andWhere('d.date BETWEEN :start AND :end')
->setParameter('start', $startOfWeek)
->setParameter('end', $endOfWeek);
break;
case 'thisMonth':
$currentYear = (int) $jdate->jdate('Y', time());
$currentMonth = (int) $jdate->jdate('n', time());
$daysInMonth = (int) $jdate->jdate('t', time());
$startOfMonth = sprintf('%d/%02d/01', $currentYear, $currentMonth);
$endOfMonth = sprintf('%d/%02d/%02d', $currentYear, $currentMonth, $daysInMonth);
$totalQueryBuilder->andWhere('d.date BETWEEN :start AND :end')
->setParameter('start', $startOfMonth)
->setParameter('end', $endOfMonth);
break;
}
$total = (int) $totalQueryBuilder->select('COUNT(d.id)')
->getQuery()
->getSingleScalarResult();
// اعمال سورت
$sortDirection = $sortDesc ? 'DESC' : 'ASC';
switch ($sortBy) {
case 'code':
$queryBuilder->orderBy('d.code', $sortDirection);
break;
case 'date':
// تبدیل تاریخ شمسی به فرمت قابل مقایسه برای سورت
$queryBuilder->orderBy('CONCAT(SUBSTRING(d.date, 1, 4), SUBSTRING(d.date, 6, 2), SUBSTRING(d.date, 9, 2))', $sortDirection);
break;
case 'amount':
$queryBuilder->orderBy('CAST(d.amount AS DECIMAL)', $sortDirection);
break;
case 'des':
$queryBuilder->orderBy('d.des', $sortDirection);
break;
case 'persons':
// برای سورت بر اساس اشخاص
if (empty($search)) {
$queryBuilder->leftJoin('d.hesabdariRows', 'hr_person')
->leftJoin('hr_person.person', 'p');
}
// استفاده از MIN برای جلوگیری از مشکل GROUP BY
$queryBuilder->groupBy('d.id, d.date, d.code, d.des, d.amount')
->orderBy('MIN(p.nikename)', $sortDirection);
break;
case 'accounts':
// سورت بر اساس طرف حساب‌ها (بانک، صندوق، تنخواه)
$queryBuilder->leftJoin('d.hesabdariRows', 'hr_account')
->leftJoin('hr_account.bank', 'ba')
->leftJoin('hr_account.cashdesk', 'cd')
->leftJoin('hr_account.salary', 's')
->groupBy('d.id, d.date, d.code, d.des, d.amount')
->orderBy('CASE WHEN ba.name IS NOT NULL THEN ba.name WHEN cd.name IS NOT NULL THEN cd.name WHEN s.name IS NOT NULL THEN s.name ELSE \'\' END', $sortDirection);
break;
default:
$queryBuilder->orderBy('d.id', 'DESC');
break;
}
// گرفتن اسناد با صفحه‌بندی
$docs = $queryBuilder
->setFirstResult(($page - 1) * $itemsPerPage)
->setMaxResults($itemsPerPage)
->getQuery()
->getArrayResult();
// گرفتن اشخاص و طرف حساب‌ها مرتبط
$docIds = array_column($docs, 'id');
$persons = [];
$accounts = [];
if (!empty($docIds)) {
// کوئری برای اشخاص
$personQuery = $entityManager->createQueryBuilder()
->select('IDENTITY(hr.doc) as doc_id, p.code as person_code, p.nikename as person_nikename')
->from('App\Entity\HesabdariRow', 'hr')
->leftJoin('hr.person', 'p')
->where('hr.doc IN (:docIds)')
->andWhere('p.id IS NOT NULL')
->setParameter('docIds', $docIds)
->getQuery()
->getArrayResult();
foreach ($personQuery as $row) {
if (!empty($row['person_code'])) {
$persons[$row['doc_id']][] = [
'code' => $row['person_code'],
'nikename' => $row['person_nikename'],
];
}
}
// کوئری برای طرف حساب‌ها (بانک، صندوق، تنخواه گردان)
$accountQuery = $entityManager->createQueryBuilder()
->select('IDENTITY(hr.doc) as doc_id, hr.bs as amount,
CASE
WHEN hr.bank IS NOT NULL THEN CONCAT(\'بانک: \', ba.name)
WHEN hr.cashdesk IS NOT NULL THEN CONCAT(\'صندوق: \', cd.name)
WHEN hr.salary IS NOT NULL THEN CONCAT(\'تنخواه: \', s.name)
ELSE \'نامشخص\'
END as account_name,
CASE
WHEN hr.bank IS NOT NULL THEN \'bank\'
WHEN hr.cashdesk IS NOT NULL THEN \'cashdesk\'
WHEN hr.salary IS NOT NULL THEN \'salary\'
ELSE \'unknown\'
END as account_type')
->from('App\Entity\HesabdariRow', 'hr')
->leftJoin('hr.bank', 'ba')
->leftJoin('hr.cashdesk', 'cd')
->leftJoin('hr.salary', 's')
->where('hr.doc IN (:docIds)')
->andWhere('hr.bs > 0')
->andWhere('(hr.bank IS NOT NULL OR hr.cashdesk IS NOT NULL OR hr.salary IS NOT NULL)')
->setParameter('docIds', $docIds)
->getQuery()
->getArrayResult();
foreach ($accountQuery as $row) {
if (!empty($row['account_name']) && $row['account_name'] !== 'نامشخص') {
$accounts[$row['doc_id']][] = [
'name' => $row['account_name'],
'type' => $row['account_type'],
'amount' => $row['amount'],
'formattedAmount' => number_format($row['amount'], 0, '.', ','),
];
}
}
}
// ساختاردهی خروجی
$items = [];
foreach ($docs as $doc) {
$items[] = [
'id' => $doc['id'],
'date' => $doc['date'],
'code' => $doc['code'],
'des' => $doc['des'],
'amount' => $doc['amount'],
'persons' => $persons[$doc['id']] ?? [],
'accounts' => $accounts[$doc['id']] ?? [],
];
}
return $this->json([
'items' => $items,
'total' => $total,
]);
}
}