add sort to person send and revive
This commit is contained in:
parent
5afd0236c6
commit
63472c1d13
|
@ -798,7 +798,7 @@ class PersonsController extends AbstractController
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/api/person/receive/list/print', name: 'app_persons_receive_list_print')]
|
#[Route('/api/person/receive/list/print', name: 'app_persons_receive_list_print')]
|
||||||
public function app_persons_receive_list_print(Provider $provider, Request $request, Access $access, Log $log, EntityManagerInterface $entityManager): JsonResponse
|
public function app_persons_receive_list_print(Provider $provider, Request $request, Access $access, Log $log, EntityManagerInterface $entityManager, Jdate $jdate): JsonResponse
|
||||||
{
|
{
|
||||||
$acc = $access->hasRole('getpay');
|
$acc = $access->hasRole('getpay');
|
||||||
if (!$acc)
|
if (!$acc)
|
||||||
|
@ -819,6 +819,103 @@ class PersonsController extends AbstractController
|
||||||
->setParameter('year', $acc['year'])
|
->setParameter('year', $acc['year'])
|
||||||
->setParameter('money', $acc['money']);
|
->setParameter('money', $acc['money']);
|
||||||
|
|
||||||
|
// اعمال فیلترهای جستوجو و تاریخ
|
||||||
|
if (isset($params['search']) && !empty($params['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', "%{$params['search']}%");
|
||||||
|
}
|
||||||
|
|
||||||
|
// فیلتر تاریخ
|
||||||
|
if (isset($params['dateFilter']) && $params['dateFilter'] !== 'all') {
|
||||||
|
$today = $jdate->GetTodayDate();
|
||||||
|
switch ($params['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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// پردازش پارامترهای سورت
|
||||||
|
$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'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// اعمال سورت
|
||||||
|
$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':
|
||||||
|
$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);
|
||||||
|
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, ba.name, cd.name, s.name')
|
||||||
|
->orderBy('COALESCE(ba.name, cd.name, s.name)', $sortDirection);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$queryBuilder->orderBy('d.id', 'DESC');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// اگر آیتمهای خاصی درخواست شدهاند
|
// اگر آیتمهای خاصی درخواست شدهاند
|
||||||
if (array_key_exists('items', $params)) {
|
if (array_key_exists('items', $params)) {
|
||||||
$ids = array_map(function($item) { return $item['id']; }, $params['items']);
|
$ids = array_map(function($item) { return $item['id']; }, $params['items']);
|
||||||
|
@ -849,15 +946,32 @@ class PersonsController extends AbstractController
|
||||||
->getResult();
|
->getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
// اضافه کردن اطلاعات اشخاص به هر آیتم
|
// اضافه کردن اطلاعات اشخاص و طرف حسابها به هر آیتم
|
||||||
foreach ($items as $item) {
|
foreach ($items as $item) {
|
||||||
$personNames = [];
|
$personNames = [];
|
||||||
|
$accountNames = [];
|
||||||
|
|
||||||
foreach ($item->getHesabdariRows() as $row) {
|
foreach ($item->getHesabdariRows() as $row) {
|
||||||
|
// اشخاص
|
||||||
if ($row->getPerson()) {
|
if ($row->getPerson()) {
|
||||||
$personNames[] = $row->getPerson()->getNikename();
|
$personNames[] = $row->getPerson()->getNikename();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// طرف حسابها
|
||||||
|
if ($row->getBd() > 0) {
|
||||||
|
$formattedAmount = number_format($row->getBd(), 0, '.', ',');
|
||||||
|
if ($row->getBank()) {
|
||||||
|
$accountNames[] = 'بانک: ' . $row->getBank()->getName() . ' (' . $formattedAmount . ')';
|
||||||
|
} elseif ($row->getCashdesk()) {
|
||||||
|
$accountNames[] = 'صندوق: ' . $row->getCashdesk()->getName() . ' (' . $formattedAmount . ')';
|
||||||
|
} elseif ($row->getSalary()) {
|
||||||
|
$accountNames[] = 'تنخواه: ' . $row->getSalary()->getName() . ' (' . $formattedAmount . ')';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$item->personNames = implode('، ', array_unique($personNames));
|
$item->personNames = implode('، ', array_unique($personNames));
|
||||||
|
$item->accountNames = implode('، ', array_unique($accountNames));
|
||||||
}
|
}
|
||||||
|
|
||||||
$pid = $provider->createPrint(
|
$pid = $provider->createPrint(
|
||||||
|
@ -880,7 +994,6 @@ class PersonsController extends AbstractController
|
||||||
'totalPages' => array_key_exists('limit', $params) ? ceil($totalItems / $params['limit']) : 1
|
'totalPages' => array_key_exists('limit', $params) ? ceil($totalItems / $params['limit']) : 1
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[Route('/api/person/receive/list/search', name: 'app_persons_receive_list_search', methods: ['POST'])]
|
#[Route('/api/person/receive/list/search', name: 'app_persons_receive_list_search', methods: ['POST'])]
|
||||||
public function app_persons_receive_list_search(
|
public function app_persons_receive_list_search(
|
||||||
|
@ -900,13 +1013,30 @@ class PersonsController extends AbstractController
|
||||||
$itemsPerPage = (int) ($params['itemsPerPage'] ?? 10);
|
$itemsPerPage = (int) ($params['itemsPerPage'] ?? 10);
|
||||||
$search = $params['search'] ?? '';
|
$search = $params['search'] ?? '';
|
||||||
$dateFilter = $params['dateFilter'] ?? 'all';
|
$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)
|
$queryBuilder = $entityManager->getRepository(HesabdariDoc::class)
|
||||||
->createQueryBuilder('d')
|
->createQueryBuilder('d')
|
||||||
->select('DISTINCT d.id, d.date, d.code, d.des, d.amount')
|
->select('DISTINCT d.id, d.date, d.code, d.des, d.amount')
|
||||||
->leftJoin('d.hesabdariRows', 'hr')
|
|
||||||
->leftJoin('hr.person', 'p')
|
|
||||||
->where('d.bid = :bid')
|
->where('d.bid = :bid')
|
||||||
->andWhere('d.type = :type')
|
->andWhere('d.type = :type')
|
||||||
->andWhere('d.year = :year')
|
->andWhere('d.year = :year')
|
||||||
|
@ -914,279 +1044,13 @@ class PersonsController extends AbstractController
|
||||||
->setParameter('bid', $acc['bid'])
|
->setParameter('bid', $acc['bid'])
|
||||||
->setParameter('type', 'person_receive')
|
->setParameter('type', 'person_receive')
|
||||||
->setParameter('year', $acc['year'])
|
->setParameter('year', $acc['year'])
|
||||||
->setParameter('money', $acc['money'])
|
|
||||||
->orderBy('d.id', 'DESC');
|
|
||||||
|
|
||||||
// جستوجو
|
|
||||||
if (!empty($search)) {
|
|
||||||
$queryBuilder->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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// محاسبه تعداد کل
|
|
||||||
$totalQuery = (clone $queryBuilder)
|
|
||||||
->select('COUNT(DISTINCT d.id) as total')
|
|
||||||
->getQuery()
|
|
||||||
->getSingleResult();
|
|
||||||
$total = (int) $totalQuery['total'];
|
|
||||||
|
|
||||||
// گرفتن اسناد با صفحهبندی
|
|
||||||
$docs = $queryBuilder
|
|
||||||
->setFirstResult(($page - 1) * $itemsPerPage)
|
|
||||||
->setMaxResults($itemsPerPage)
|
|
||||||
->getQuery()
|
|
||||||
->getArrayResult();
|
|
||||||
|
|
||||||
// گرفتن اشخاص مرتبط
|
|
||||||
$docIds = array_column($docs, 'id');
|
|
||||||
$persons = [];
|
|
||||||
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)')
|
|
||||||
->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'],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ساختاردهی خروجی
|
|
||||||
$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']] ?? [],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->json([
|
|
||||||
'items' => $items,
|
|
||||||
'total' => $total,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[Route('/api/person/receive/list/excel', name: 'app_persons_receive_list_excel', methods: ['POST'])]
|
|
||||||
public function app_persons_receive_list_excel(
|
|
||||||
Provider $provider,
|
|
||||||
Request $request,
|
|
||||||
Access $access,
|
|
||||||
Log $log,
|
|
||||||
EntityManagerInterface $entityManager
|
|
||||||
): BinaryFileResponse {
|
|
||||||
$acc = $access->hasRole('getpay');
|
|
||||||
if (!$acc) {
|
|
||||||
throw $this->createAccessDeniedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
$params = json_decode($request->getContent(), true) ?? [];
|
|
||||||
if (!array_key_exists('items', $params) || empty($params['items'])) {
|
|
||||||
$items = $entityManager->getRepository(HesabdariDoc::class)->findBy([
|
|
||||||
'bid' => $acc['bid'],
|
|
||||||
'type' => 'person_receive',
|
|
||||||
'year' => $acc['year'],
|
|
||||||
'money' => $acc['money'],
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
$items = [];
|
|
||||||
foreach ($params['items'] as $param) {
|
|
||||||
if (!is_array($param) || !isset($param['id'])) {
|
|
||||||
throw new \InvalidArgumentException('Invalid item format in request');
|
|
||||||
}
|
|
||||||
$doc = $entityManager->getRepository(HesabdariDoc::class)->findOneBy([
|
|
||||||
'id' => $param['id'],
|
|
||||||
'bid' => $acc['bid'],
|
|
||||||
'type' => 'person_receive',
|
|
||||||
'year' => $acc['year'],
|
|
||||||
'money' => $acc['money'],
|
|
||||||
]);
|
|
||||||
if ($doc) {
|
|
||||||
// اضافه کردن اطلاعات اشخاص
|
|
||||||
$personNames = [];
|
|
||||||
foreach ($doc->getHesabdariRows() as $row) {
|
|
||||||
if ($row->getPerson()) {
|
|
||||||
$personNames[] = $row->getPerson()->getNikename();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$doc->personNames = implode('، ', array_unique($personNames));
|
|
||||||
$items[] = $doc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new BinaryFileResponse($provider->createExcell($items, ['type', 'dateSubmit']));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[Route('/api/person/send/list/print', name: 'app_persons_send_list_print')]
|
|
||||||
public function app_persons_send_list_print(Provider $provider, Request $request, Access $access, Log $log, EntityManagerInterface $entityManager): JsonResponse
|
|
||||||
{
|
|
||||||
$acc = $access->hasRole('getpay');
|
|
||||||
if (!$acc)
|
|
||||||
throw $this->createAccessDeniedException();
|
|
||||||
|
|
||||||
$params = [];
|
|
||||||
if ($content = $request->getContent()) {
|
|
||||||
$params = json_decode($content, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
$queryBuilder = $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']);
|
->setParameter('money', $acc['money']);
|
||||||
|
|
||||||
// اگر آیتمهای خاصی درخواست شدهاند
|
|
||||||
if (array_key_exists('items', $params)) {
|
|
||||||
$ids = array_map(function($item) { return $item['id']; }, $params['items']);
|
|
||||||
$queryBuilder->andWhere('d.id IN (:ids)')
|
|
||||||
->setParameter('ids', $ids);
|
|
||||||
}
|
|
||||||
|
|
||||||
// دریافت تعداد کل رکوردها
|
|
||||||
$totalItems = $queryBuilder->select('COUNT(d.id)')
|
|
||||||
->getQuery()
|
|
||||||
->getSingleScalarResult();
|
|
||||||
|
|
||||||
// اگر درخواست با صفحهبندی است
|
|
||||||
if (array_key_exists('page', $params) && array_key_exists('limit', $params)) {
|
|
||||||
$page = $params['page'];
|
|
||||||
$limit = $params['limit'];
|
|
||||||
$offset = ($page - 1) * $limit;
|
|
||||||
|
|
||||||
$items = $queryBuilder->select('d')
|
|
||||||
->setFirstResult($offset)
|
|
||||||
->setMaxResults($limit)
|
|
||||||
->getQuery()
|
|
||||||
->getResult();
|
|
||||||
} else {
|
|
||||||
// دریافت همه آیتمها بدون صفحهبندی
|
|
||||||
$items = $queryBuilder->select('d')
|
|
||||||
->getQuery()
|
|
||||||
->getResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
// اضافه کردن اطلاعات اشخاص به هر آیتم
|
|
||||||
foreach ($items as $item) {
|
|
||||||
$personNames = [];
|
|
||||||
foreach ($item->getHesabdariRows() as $row) {
|
|
||||||
if ($row->getPerson()) {
|
|
||||||
$personNames[] = $row->getPerson()->getNikename();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$item->personNames = implode('، ', array_unique($personNames));
|
|
||||||
}
|
|
||||||
|
|
||||||
$pid = $provider->createPrint(
|
|
||||||
$acc['bid'],
|
|
||||||
$this->getUser(),
|
|
||||||
$this->renderView('pdf/persons_send.html.twig', [
|
|
||||||
'page_title' => 'لیست پرداختها',
|
|
||||||
'bid' => $acc['bid'],
|
|
||||||
'items' => $items,
|
|
||||||
'totalItems' => $totalItems,
|
|
||||||
'currentPage' => $params['page'] ?? 1,
|
|
||||||
'totalPages' => array_key_exists('limit', $params) ? ceil($totalItems / $params['limit']) : 1
|
|
||||||
])
|
|
||||||
);
|
|
||||||
|
|
||||||
return $this->json([
|
|
||||||
'id' => $pid,
|
|
||||||
'totalItems' => $totalItems,
|
|
||||||
'currentPage' => $params['page'] ?? 1,
|
|
||||||
'totalPages' => array_key_exists('limit', $params) ? ceil($totalItems / $params['limit']) : 1
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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';
|
|
||||||
|
|
||||||
// کوئری پایه برای اسناد
|
|
||||||
$queryBuilder = $entityManager->getRepository(HesabdariDoc::class)
|
|
||||||
->createQueryBuilder('d')
|
|
||||||
->select('DISTINCT d.id, d.date, d.code, d.des, d.amount')
|
|
||||||
->leftJoin('d.hesabdariRows', 'hr')
|
|
||||||
->leftJoin('hr.person', 'p')
|
|
||||||
->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'])
|
|
||||||
->orderBy('d.id', 'DESC');
|
|
||||||
|
|
||||||
// جستوجو
|
// جستوجو
|
||||||
if (!empty($search)) {
|
if (!empty($search)) {
|
||||||
$queryBuilder->andWhere(
|
$queryBuilder->leftJoin('d.hesabdariRows', 'hr')
|
||||||
|
->leftJoin('hr.person', 'p')
|
||||||
|
->andWhere(
|
||||||
$queryBuilder->expr()->orX(
|
$queryBuilder->expr()->orX(
|
||||||
'd.code LIKE :search',
|
'd.code LIKE :search',
|
||||||
'd.des LIKE :search',
|
'd.des LIKE :search',
|
||||||
|
@ -1225,6 +1089,42 @@ class PersonsController extends AbstractController
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// اعمال سورت
|
||||||
|
$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':
|
||||||
|
$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);
|
||||||
|
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, ba.name, cd.name, s.name')
|
||||||
|
->orderBy('COALESCE(ba.name, cd.name, s.name)', $sortDirection);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$queryBuilder->orderBy('d.id', 'DESC');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// محاسبه تعداد کل
|
// محاسبه تعداد کل
|
||||||
$totalQuery = (clone $queryBuilder)
|
$totalQuery = (clone $queryBuilder)
|
||||||
->select('COUNT(DISTINCT d.id) as total')
|
->select('COUNT(DISTINCT d.id) as total')
|
||||||
|
@ -1239,15 +1139,18 @@ class PersonsController extends AbstractController
|
||||||
->getQuery()
|
->getQuery()
|
||||||
->getArrayResult();
|
->getArrayResult();
|
||||||
|
|
||||||
// گرفتن اشخاص مرتبط
|
// گرفتن اشخاص و طرف حسابها مرتبط
|
||||||
$docIds = array_column($docs, 'id');
|
$docIds = array_column($docs, 'id');
|
||||||
$persons = [];
|
$persons = [];
|
||||||
|
$accounts = [];
|
||||||
if (!empty($docIds)) {
|
if (!empty($docIds)) {
|
||||||
|
// کوئری برای اشخاص
|
||||||
$personQuery = $entityManager->createQueryBuilder()
|
$personQuery = $entityManager->createQueryBuilder()
|
||||||
->select('IDENTITY(hr.doc) as doc_id, p.code as person_code, p.nikename as person_nikename')
|
->select('IDENTITY(hr.doc) as doc_id, p.code as person_code, p.nikename as person_nikename')
|
||||||
->from('App\Entity\HesabdariRow', 'hr')
|
->from('App\Entity\HesabdariRow', 'hr')
|
||||||
->leftJoin('hr.person', 'p')
|
->leftJoin('hr.person', 'p')
|
||||||
->where('hr.doc IN (:docIds)')
|
->where('hr.doc IN (:docIds)')
|
||||||
|
->andWhere('p.id IS NOT NULL')
|
||||||
->setParameter('docIds', $docIds)
|
->setParameter('docIds', $docIds)
|
||||||
->getQuery()
|
->getQuery()
|
||||||
->getArrayResult();
|
->getArrayResult();
|
||||||
|
@ -1260,6 +1163,43 @@ class PersonsController extends AbstractController
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// کوئری برای طرف حسابها (بانک، صندوق، تنخواه گردان)
|
||||||
|
$accountQuery = $entityManager->createQueryBuilder()
|
||||||
|
->select('IDENTITY(hr.doc) as doc_id, hr.bd 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.bd > 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, '.', ','),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ساختاردهی خروجی
|
// ساختاردهی خروجی
|
||||||
|
@ -1272,6 +1212,7 @@ class PersonsController extends AbstractController
|
||||||
'des' => $doc['des'],
|
'des' => $doc['des'],
|
||||||
'amount' => $doc['amount'],
|
'amount' => $doc['amount'],
|
||||||
'persons' => $persons[$doc['id']] ?? [],
|
'persons' => $persons[$doc['id']] ?? [],
|
||||||
|
'accounts' => $accounts[$doc['id']] ?? [],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1319,14 +1260,31 @@ class PersonsController extends AbstractController
|
||||||
'money' => $acc['money'],
|
'money' => $acc['money'],
|
||||||
]);
|
]);
|
||||||
if ($doc) {
|
if ($doc) {
|
||||||
// اضافه کردن اطلاعات اشخاص
|
// اضافه کردن اطلاعات اشخاص و طرف حسابها
|
||||||
$personNames = [];
|
$personNames = [];
|
||||||
|
$accountNames = [];
|
||||||
|
|
||||||
foreach ($doc->getHesabdariRows() as $row) {
|
foreach ($doc->getHesabdariRows() as $row) {
|
||||||
|
// اشخاص
|
||||||
if ($row->getPerson()) {
|
if ($row->getPerson()) {
|
||||||
$personNames[] = $row->getPerson()->getNikename();
|
$personNames[] = $row->getPerson()->getNikename();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// طرف حسابها
|
||||||
|
if ($row->getBs() > 0) {
|
||||||
|
$formattedAmount = number_format($row->getBs(), 0, '.', ',');
|
||||||
|
if ($row->getBank()) {
|
||||||
|
$accountNames[] = 'بانک: ' . $row->getBank()->getName() . ' (' . $formattedAmount . ')';
|
||||||
|
} elseif ($row->getCashdesk()) {
|
||||||
|
$accountNames[] = 'صندوق: ' . $row->getCashdesk()->getName() . ' (' . $formattedAmount . ')';
|
||||||
|
} elseif ($row->getSalary()) {
|
||||||
|
$accountNames[] = 'تنخواه: ' . $row->getSalary()->getName() . ' (' . $formattedAmount . ')';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$doc->personNames = implode('، ', array_unique($personNames));
|
$doc->personNames = implode('، ', array_unique($personNames));
|
||||||
|
$doc->accountNames = implode('، ', array_unique($accountNames));
|
||||||
$items[] = $doc;
|
$items[] = $doc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1690,4 +1648,370 @@ class PersonsController extends AbstractController
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[Route('/api/person/receive/list/excel', name: 'app_persons_receive_list_excel', methods: ['POST'])]
|
||||||
|
public function app_persons_receive_list_excel(
|
||||||
|
Provider $provider,
|
||||||
|
Request $request,
|
||||||
|
Access $access,
|
||||||
|
Log $log,
|
||||||
|
EntityManagerInterface $entityManager,
|
||||||
|
Jdate $jdate
|
||||||
|
): BinaryFileResponse|JsonResponse|StreamedResponse {
|
||||||
|
$acc = $access->hasRole('getpay');
|
||||||
|
if (!$acc)
|
||||||
|
throw $this->createAccessDeniedException();
|
||||||
|
|
||||||
|
$params = [];
|
||||||
|
if ($content = $request->getContent()) {
|
||||||
|
$params = json_decode($content, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$queryBuilder = $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'])) {
|
||||||
|
$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', "%{$params['search']}%");
|
||||||
|
}
|
||||||
|
|
||||||
|
// فیلتر تاریخ
|
||||||
|
if (isset($params['dateFilter']) && $params['dateFilter'] !== 'all') {
|
||||||
|
$today = $jdate->GetTodayDate();
|
||||||
|
switch ($params['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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// پردازش پارامترهای سورت
|
||||||
|
$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'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// اعمال سورت
|
||||||
|
$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':
|
||||||
|
$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);
|
||||||
|
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, ba.name, cd.name, s.name')
|
||||||
|
->orderBy('COALESCE(ba.name, cd.name, s.name)', $sortDirection);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$queryBuilder->orderBy('d.id', 'DESC');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// اگر آیتمهای خاصی درخواست شدهاند
|
||||||
|
if (array_key_exists('items', $params)) {
|
||||||
|
$ids = array_map(function($item) { return $item['id']; }, $params['items']);
|
||||||
|
$queryBuilder->andWhere('d.id IN (:ids)')
|
||||||
|
->setParameter('ids', $ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
// دریافت همه آیتمها برای Excel
|
||||||
|
$items = $queryBuilder->select('d')
|
||||||
|
->getQuery()
|
||||||
|
->getResult();
|
||||||
|
|
||||||
|
// اضافه کردن اطلاعات اشخاص و طرف حسابها به هر آیتم
|
||||||
|
foreach ($items as $item) {
|
||||||
|
$personNames = [];
|
||||||
|
$accountNames = [];
|
||||||
|
|
||||||
|
foreach ($item->getHesabdariRows() as $row) {
|
||||||
|
// اشخاص
|
||||||
|
if ($row->getPerson()) {
|
||||||
|
$personNames[] = $row->getPerson()->getNikename();
|
||||||
|
}
|
||||||
|
|
||||||
|
// طرف حسابها
|
||||||
|
if ($row->getBd() > 0) {
|
||||||
|
$formattedAmount = number_format($row->getBd(), 0, '.', ',');
|
||||||
|
if ($row->getBank()) {
|
||||||
|
$accountNames[] = 'بانک: ' . $row->getBank()->getName() . ' (' . $formattedAmount . ')';
|
||||||
|
} elseif ($row->getCashdesk()) {
|
||||||
|
$accountNames[] = 'صندوق: ' . $row->getCashdesk()->getName() . ' (' . $formattedAmount . ')';
|
||||||
|
} elseif ($row->getSalary()) {
|
||||||
|
$accountNames[] = 'تنخواه: ' . $row->getSalary()->getName() . ' (' . $formattedAmount . ')';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$item->personNames = implode('، ', array_unique($personNames));
|
||||||
|
$item->accountNames = implode('، ', array_unique($accountNames));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BinaryFileResponse($provider->createExcell($items, ['type', 'dateSubmit']));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Route('/api/person/send/list/print', name: 'app_persons_send_list_print')]
|
||||||
|
public function app_persons_send_list_print(Provider $provider, Request $request, Access $access, Log $log, EntityManagerInterface $entityManager, Jdate $jdate): JsonResponse
|
||||||
|
{
|
||||||
|
$acc = $access->hasRole('getpay');
|
||||||
|
if (!$acc)
|
||||||
|
throw $this->createAccessDeniedException();
|
||||||
|
|
||||||
|
$params = [];
|
||||||
|
if ($content = $request->getContent()) {
|
||||||
|
$params = json_decode($content, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$queryBuilder = $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'])) {
|
||||||
|
$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', "%{$params['search']}%");
|
||||||
|
}
|
||||||
|
|
||||||
|
// فیلتر تاریخ
|
||||||
|
if (isset($params['dateFilter']) && $params['dateFilter'] !== 'all') {
|
||||||
|
$today = $jdate->GetTodayDate();
|
||||||
|
switch ($params['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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// پردازش پارامترهای سورت
|
||||||
|
$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'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// اعمال سورت
|
||||||
|
$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':
|
||||||
|
$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);
|
||||||
|
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, ba.name, cd.name, s.name')
|
||||||
|
->orderBy('COALESCE(ba.name, cd.name, s.name)', $sortDirection);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$queryBuilder->orderBy('d.id', 'DESC');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// اگر آیتمهای خاصی درخواست شدهاند
|
||||||
|
if (array_key_exists('items', $params)) {
|
||||||
|
$ids = array_map(function($item) { return $item['id']; }, $params['items']);
|
||||||
|
$queryBuilder->andWhere('d.id IN (:ids)')
|
||||||
|
->setParameter('ids', $ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
// دریافت تعداد کل رکوردها
|
||||||
|
$totalItems = $queryBuilder->select('COUNT(d.id)')
|
||||||
|
->getQuery()
|
||||||
|
->getSingleScalarResult();
|
||||||
|
|
||||||
|
// اگر درخواست با صفحهبندی است
|
||||||
|
if (array_key_exists('page', $params) && array_key_exists('limit', $params)) {
|
||||||
|
$page = $params['page'];
|
||||||
|
$limit = $params['limit'];
|
||||||
|
$offset = ($page - 1) * $limit;
|
||||||
|
|
||||||
|
$items = $queryBuilder->select('d')
|
||||||
|
->setFirstResult($offset)
|
||||||
|
->setMaxResults($limit)
|
||||||
|
->getQuery()
|
||||||
|
->getResult();
|
||||||
|
} else {
|
||||||
|
// دریافت همه آیتمها بدون صفحهبندی
|
||||||
|
$items = $queryBuilder->select('d')
|
||||||
|
->getQuery()
|
||||||
|
->getResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
// اضافه کردن اطلاعات اشخاص و طرف حسابها به هر آیتم
|
||||||
|
foreach ($items as $item) {
|
||||||
|
$personNames = [];
|
||||||
|
$accountNames = [];
|
||||||
|
|
||||||
|
foreach ($item->getHesabdariRows() as $row) {
|
||||||
|
// اشخاص
|
||||||
|
if ($row->getPerson()) {
|
||||||
|
$personNames[] = $row->getPerson()->getNikename();
|
||||||
|
}
|
||||||
|
|
||||||
|
// طرف حسابها
|
||||||
|
if ($row->getBs() > 0) {
|
||||||
|
$formattedAmount = number_format($row->getBs(), 0, '.', ',');
|
||||||
|
if ($row->getBank()) {
|
||||||
|
$accountNames[] = 'بانک: ' . $row->getBank()->getName() . ' (' . $formattedAmount . ')';
|
||||||
|
} elseif ($row->getCashdesk()) {
|
||||||
|
$accountNames[] = 'صندوق: ' . $row->getCashdesk()->getName() . ' (' . $formattedAmount . ')';
|
||||||
|
} elseif ($row->getSalary()) {
|
||||||
|
$accountNames[] = 'تنخواه: ' . $row->getSalary()->getName() . ' (' . $formattedAmount . ')';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$item->personNames = implode('، ', array_unique($personNames));
|
||||||
|
$item->accountNames = implode('، ', array_unique($accountNames));
|
||||||
|
}
|
||||||
|
|
||||||
|
$pid = $provider->createPrint(
|
||||||
|
$acc['bid'],
|
||||||
|
$this->getUser(),
|
||||||
|
$this->renderView('pdf/persons_send.html.twig', [
|
||||||
|
'page_title' => 'لیست پرداختها',
|
||||||
|
'bid' => $acc['bid'],
|
||||||
|
'items' => $items,
|
||||||
|
'totalItems' => $totalItems,
|
||||||
|
'currentPage' => $params['page'] ?? 1,
|
||||||
|
'totalPages' => array_key_exists('limit', $params) ? ceil($totalItems / $params['limit']) : 1
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->json([
|
||||||
|
'id' => $pid,
|
||||||
|
'totalItems' => $totalItems,
|
||||||
|
'currentPage' => $params['page'] ?? 1,
|
||||||
|
'totalPages' => array_key_exists('limit', $params) ? ceil($totalItems / $params['limit']) : 1
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
<td class="center item">تاریخ</td>
|
<td class="center item">تاریخ</td>
|
||||||
<td class="center item">مبلغ</td>
|
<td class="center item">مبلغ</td>
|
||||||
<td class="center item">اشخاص</td>
|
<td class="center item">اشخاص</td>
|
||||||
|
<td class="center item">طرف حسابها</td>
|
||||||
<td class="center item">شرح</td>
|
<td class="center item">شرح</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% for item in items %}
|
{% for item in items %}
|
||||||
|
@ -18,6 +19,7 @@
|
||||||
<td class="center item">{{ item.date }}</td>
|
<td class="center item">{{ item.date }}</td>
|
||||||
<td class="center item">{{ item.amount | number_format }}</td>
|
<td class="center item">{{ item.amount | number_format }}</td>
|
||||||
<td class="center item">{{ item.personNames }}</td>
|
<td class="center item">{{ item.personNames }}</td>
|
||||||
|
<td class="center item">{{ item.accountNames }}</td>
|
||||||
<td class="center item">{{ item.des }}</td>
|
<td class="center item">{{ item.des }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
33
hesabixCore/templates/pdf/persons_send.html.twig
Normal file
33
hesabixCore/templates/pdf/persons_send.html.twig
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
{% extends "pdf/base.html.twig" %}
|
||||||
|
{% block body %}
|
||||||
|
<div style="width:100%;margin-top:5px;text-align:center;">
|
||||||
|
<table style="width:100%;">
|
||||||
|
<tbody>
|
||||||
|
<tr class="stimol" style="text-align: center; background-color: grey; text-color: white">
|
||||||
|
<td style="width: 35px;">ردیف</td>
|
||||||
|
<td class="center item">کد حسابداری</td>
|
||||||
|
<td class="center item">تاریخ</td>
|
||||||
|
<td class="center item">مبلغ</td>
|
||||||
|
<td class="center item">اشخاص</td>
|
||||||
|
<td class="center item">طرف حسابها</td>
|
||||||
|
<td class="center item">شرح</td>
|
||||||
|
</tr>
|
||||||
|
{% for item in items %}
|
||||||
|
<tr class="stimol {% if loop.index is even%}bg-dark text-light{% endif%}">
|
||||||
|
<td class="center item">{{ loop.index + ((currentPage - 1) * 10) }}</td>
|
||||||
|
<td class="center item">{{ item.code }}</td>
|
||||||
|
<td class="center item">{{ item.date }}</td>
|
||||||
|
<td class="center item">{{ item.amount | number_format }}</td>
|
||||||
|
<td class="center item">{{ item.personNames }}</td>
|
||||||
|
<td class="center item">{{ item.accountNames }}</td>
|
||||||
|
<td class="center item">{{ item.des }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div style="margin-top: 20px; text-align: left;">
|
||||||
|
<small>صفحه {{ currentPage }} از {{ totalPages }} - تعداد کل: {{ totalItems }}</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
|
@ -117,8 +117,12 @@
|
||||||
class="elevation-1"
|
class="elevation-1"
|
||||||
:header-props="{ class: 'custom-header' }"
|
:header-props="{ class: 'custom-header' }"
|
||||||
:items-per-page-options="[5, 10, 20, 50]"
|
:items-per-page-options="[5, 10, 20, 50]"
|
||||||
items-per-page-text="تعداد سطر در هر صفحه"
|
:items-per-page-text="$t('table.rows_per_page')"
|
||||||
|
:sort-by="[{ key: sortBy, order: sortDesc ? 'desc' : 'asc' }]"
|
||||||
|
:sort-desc="sortDesc"
|
||||||
@update:options="loadData"
|
@update:options="loadData"
|
||||||
|
@update:sort-by="(val) => handleSort(val, undefined)"
|
||||||
|
@update:sort-desc="(val) => handleSort(undefined, val)"
|
||||||
>
|
>
|
||||||
<template v-slot:header.select>
|
<template v-slot:header.select>
|
||||||
<v-checkbox
|
<v-checkbox
|
||||||
|
@ -175,6 +179,19 @@
|
||||||
{{ person.nikename }}
|
{{ person.nikename }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</template>
|
</template>
|
||||||
|
<template v-slot:item.accounts="{ item }">
|
||||||
|
<div v-for="account in item.accounts" :key="account.name" class="mb-1">
|
||||||
|
<v-chip
|
||||||
|
:color="getAccountColor(account.type)"
|
||||||
|
size="small"
|
||||||
|
variant="outlined"
|
||||||
|
class="me-1"
|
||||||
|
>
|
||||||
|
{{ account.name }}
|
||||||
|
<span class="ms-1">({{ account.formattedAmount }})</span>
|
||||||
|
</v-chip>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
<template v-slot:item.code="{ item }">
|
<template v-slot:item.code="{ item }">
|
||||||
<span class="text-left">{{ $filters.formatNumber(item.code) }}</span>
|
<span class="text-left">{{ $filters.formatNumber(item.code) }}</span>
|
||||||
</template>
|
</template>
|
||||||
|
@ -182,7 +199,7 @@
|
||||||
<span class="text-left">{{ $filters.formatNumber(item.amount) }}</span>
|
<span class="text-left">{{ $filters.formatNumber(item.amount) }}</span>
|
||||||
</template>
|
</template>
|
||||||
</v-data-table-server>
|
</v-data-table-server>
|
||||||
<v-card variant="" class="my-4">
|
<v-card class="my-4">
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col cols="12" sm="6">
|
<v-col cols="12" sm="6">
|
||||||
|
@ -259,15 +276,18 @@ const selectAll = ref(false);
|
||||||
const selectedItems = ref([]);
|
const selectedItems = ref([]);
|
||||||
const sumTotal = ref(0);
|
const sumTotal = ref(0);
|
||||||
const sumSelected = ref(0);
|
const sumSelected = ref(0);
|
||||||
|
const sortBy = ref('id');
|
||||||
|
const sortDesc = ref(true);
|
||||||
|
|
||||||
const allHeaders = reactive([
|
const allHeaders = reactive([
|
||||||
{ title: '', key: 'select', sortable: false, visible: true, customizable: false },
|
{ title: '', key: 'select', sortable: false, visible: true, customizable: false },
|
||||||
{ title: 'عملیات', key: 'operation', sortable: false, visible: true },
|
{ title: 'عملیات', key: 'operation', sortable: false, visible: true },
|
||||||
{ title: 'کد', key: 'code', visible: true },
|
{ title: 'کد', key: 'code', sortable: true, visible: true },
|
||||||
{ title: 'اشخاص', key: 'persons', sortable: true, visible: true },
|
{ title: 'اشخاص', key: 'persons', sortable: true, visible: true },
|
||||||
{ title: 'تاریخ', key: 'date', visible: true },
|
{ title: 'طرف حسابها', key: 'accounts', sortable: true, visible: true },
|
||||||
{ title: 'شرح', key: 'des', visible: true },
|
{ title: 'تاریخ', key: 'date', sortable: true, visible: true },
|
||||||
{ title: 'مبلغ', key: 'amount', visible: true },
|
{ title: 'شرح', key: 'des', sortable: true, visible: true },
|
||||||
|
{ title: 'مبلغ', key: 'amount', sortable: true, visible: true },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const customizableHeaders = computed(() =>
|
const customizableHeaders = computed(() =>
|
||||||
|
@ -284,6 +304,30 @@ const dateFilterOptions = [
|
||||||
{ title: 'این ماه', value: 'thisMonth' },
|
{ title: 'این ماه', value: 'thisMonth' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const handleSort = (newSortBy, newSortDesc) => {
|
||||||
|
console.log('handleSort called:', { newSortBy, newSortDesc });
|
||||||
|
|
||||||
|
// اگر newSortBy آرایه است، اولین عنصر را بگیر
|
||||||
|
if (Array.isArray(newSortBy) && newSortBy.length > 0) {
|
||||||
|
if (typeof newSortBy[0] === 'string') {
|
||||||
|
sortBy.value = newSortBy[0];
|
||||||
|
} else if (newSortBy[0] && typeof newSortBy[0] === 'object' && newSortBy[0].key) {
|
||||||
|
sortBy.value = newSortBy[0].key;
|
||||||
|
sortDesc.value = newSortBy[0].order === 'desc';
|
||||||
|
}
|
||||||
|
} else if (typeof newSortBy === 'string') {
|
||||||
|
sortBy.value = newSortBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
// اگر newSortDesc تعریف شده، آن را اعمال کن
|
||||||
|
if (newSortDesc !== undefined) {
|
||||||
|
sortDesc.value = newSortDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Updated sort values:', { sortBy: sortBy.value, sortDesc: sortDesc.value });
|
||||||
|
loadData();
|
||||||
|
};
|
||||||
|
|
||||||
const loadData = async (options = null) => {
|
const loadData = async (options = null) => {
|
||||||
if (loading.value) return;
|
if (loading.value) return;
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
@ -294,6 +338,11 @@ const loadData = async (options = null) => {
|
||||||
itemsPerPage: options?.itemsPerPage || itemsPerPage.value,
|
itemsPerPage: options?.itemsPerPage || itemsPerPage.value,
|
||||||
search: searchValue.value,
|
search: searchValue.value,
|
||||||
dateFilter: dateFilter.value,
|
dateFilter: dateFilter.value,
|
||||||
|
sortBy: [{
|
||||||
|
key: sortBy.value,
|
||||||
|
order: sortDesc.value ? 'desc' : 'asc'
|
||||||
|
}],
|
||||||
|
sortDesc: sortDesc.value,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -398,10 +447,25 @@ const print = async (allItems = true) => {
|
||||||
try {
|
try {
|
||||||
let response;
|
let response;
|
||||||
if (allItems) {
|
if (allItems) {
|
||||||
response = await axios.post('/api/person/receive/list/print');
|
response = await axios.post('/api/person/receive/list/print', {
|
||||||
|
search: searchValue.value,
|
||||||
|
dateFilter: dateFilter.value,
|
||||||
|
sortBy: [{
|
||||||
|
key: sortBy.value,
|
||||||
|
order: sortDesc.value ? 'desc' : 'asc'
|
||||||
|
}],
|
||||||
|
sortDesc: sortDesc.value,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
response = await axios.post('/api/person/receive/list/print', {
|
response = await axios.post('/api/person/receive/list/print', {
|
||||||
items: selectedItems.value
|
items: selectedItems.value,
|
||||||
|
search: searchValue.value,
|
||||||
|
dateFilter: dateFilter.value,
|
||||||
|
sortBy: [{
|
||||||
|
key: sortBy.value,
|
||||||
|
order: sortDesc.value ? 'desc' : 'asc'
|
||||||
|
}],
|
||||||
|
sortDesc: sortDesc.value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -433,14 +497,32 @@ const excellOutput = async (allItems = true) => {
|
||||||
response = await axios({
|
response = await axios({
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: '/api/person/receive/list/excel',
|
url: '/api/person/receive/list/excel',
|
||||||
responseType: 'arraybuffer'
|
responseType: 'arraybuffer',
|
||||||
|
data: {
|
||||||
|
search: searchValue.value,
|
||||||
|
dateFilter: dateFilter.value,
|
||||||
|
sortBy: [{
|
||||||
|
key: sortBy.value,
|
||||||
|
order: sortDesc.value ? 'desc' : 'asc'
|
||||||
|
}],
|
||||||
|
sortDesc: sortDesc.value,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
response = await axios({
|
response = await axios({
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: '/api/person/receive/list/excel',
|
url: '/api/person/receive/list/excel',
|
||||||
responseType: 'arraybuffer',
|
responseType: 'arraybuffer',
|
||||||
data: { items: selectedItems.value }
|
data: {
|
||||||
|
items: selectedItems.value,
|
||||||
|
search: searchValue.value,
|
||||||
|
dateFilter: dateFilter.value,
|
||||||
|
sortBy: [{
|
||||||
|
key: sortBy.value,
|
||||||
|
order: sortDesc.value ? 'desc' : 'asc'
|
||||||
|
}],
|
||||||
|
sortDesc: sortDesc.value,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,6 +544,19 @@ const excellOutput = async (allItems = true) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getAccountColor = (type) => {
|
||||||
|
switch (type) {
|
||||||
|
case 'bank':
|
||||||
|
return 'primary';
|
||||||
|
case 'cashdesk':
|
||||||
|
return 'success';
|
||||||
|
case 'salary':
|
||||||
|
return 'warning';
|
||||||
|
default:
|
||||||
|
return 'grey';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const updateColumnVisibility = () => {
|
const updateColumnVisibility = () => {
|
||||||
localStorage.setItem('receiveTableColumns', JSON.stringify(allHeaders));
|
localStorage.setItem('receiveTableColumns', JSON.stringify(allHeaders));
|
||||||
};
|
};
|
||||||
|
@ -479,7 +574,7 @@ const loadColumnSettings = () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
watch([searchValue, page, itemsPerPage, dateFilter], () => {
|
watch([searchValue, page, itemsPerPage, dateFilter, sortBy, sortDesc], () => {
|
||||||
loadData();
|
loadData();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -117,8 +117,12 @@
|
||||||
class="elevation-1"
|
class="elevation-1"
|
||||||
:header-props="{ class: 'custom-header' }"
|
:header-props="{ class: 'custom-header' }"
|
||||||
:items-per-page-options="[5, 10, 20, 50]"
|
:items-per-page-options="[5, 10, 20, 50]"
|
||||||
items-per-page-text="تعداد سطر در هر صفحه"
|
:items-per-page-text="$t('table.rows_per_page')"
|
||||||
|
:sort-by="[{ key: sortBy, order: sortDesc ? 'desc' : 'asc' }]"
|
||||||
|
:sort-desc="sortDesc"
|
||||||
@update:options="loadData"
|
@update:options="loadData"
|
||||||
|
@update:sort-by="(val) => handleSort(val, undefined)"
|
||||||
|
@update:sort-desc="(val) => handleSort(undefined, val)"
|
||||||
>
|
>
|
||||||
<template v-slot:header.select>
|
<template v-slot:header.select>
|
||||||
<v-checkbox
|
<v-checkbox
|
||||||
|
@ -175,6 +179,19 @@
|
||||||
{{ person.nikename }}
|
{{ person.nikename }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</template>
|
</template>
|
||||||
|
<template v-slot:item.accounts="{ item }">
|
||||||
|
<div v-for="account in item.accounts" :key="account.name" class="mb-1">
|
||||||
|
<v-chip
|
||||||
|
:color="getAccountColor(account.type)"
|
||||||
|
size="small"
|
||||||
|
variant="outlined"
|
||||||
|
class="me-1"
|
||||||
|
>
|
||||||
|
{{ account.name }}
|
||||||
|
<span class="ms-1">({{ account.formattedAmount }})</span>
|
||||||
|
</v-chip>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
<template v-slot:item.code="{ item }">
|
<template v-slot:item.code="{ item }">
|
||||||
<span class="text-left">{{ $filters.formatNumber(item.code) }}</span>
|
<span class="text-left">{{ $filters.formatNumber(item.code) }}</span>
|
||||||
</template>
|
</template>
|
||||||
|
@ -182,7 +199,7 @@
|
||||||
<span class="text-left">{{ $filters.formatNumber(item.amount) }}</span>
|
<span class="text-left">{{ $filters.formatNumber(item.amount) }}</span>
|
||||||
</template>
|
</template>
|
||||||
</v-data-table-server>
|
</v-data-table-server>
|
||||||
<v-card variant="" class="my-4">
|
<v-card class="my-4">
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col cols="12" sm="6">
|
<v-col cols="12" sm="6">
|
||||||
|
@ -259,15 +276,18 @@ const selectAll = ref(false);
|
||||||
const selectedItems = ref([]);
|
const selectedItems = ref([]);
|
||||||
const sumTotal = ref(0);
|
const sumTotal = ref(0);
|
||||||
const sumSelected = ref(0);
|
const sumSelected = ref(0);
|
||||||
|
const sortBy = ref('id');
|
||||||
|
const sortDesc = ref(true);
|
||||||
|
|
||||||
const allHeaders = reactive([
|
const allHeaders = reactive([
|
||||||
{ title: '', key: 'select', sortable: false, visible: true, customizable: false },
|
{ title: '', key: 'select', sortable: false, visible: true, customizable: false },
|
||||||
{ title: 'عملیات', key: 'operation', sortable: false, visible: true },
|
{ title: 'عملیات', key: 'operation', sortable: false, visible: true },
|
||||||
{ title: 'کد', key: 'code', visible: true },
|
{ title: 'کد', key: 'code', sortable: true, visible: true },
|
||||||
{ title: 'اشخاص', key: 'persons', sortable: true, visible: true },
|
{ title: 'اشخاص', key: 'persons', sortable: true, visible: true },
|
||||||
{ title: 'تاریخ', key: 'date', visible: true },
|
{ title: 'طرف حسابها', key: 'accounts', sortable: true, visible: true },
|
||||||
{ title: 'شرح', key: 'des', visible: true },
|
{ title: 'تاریخ', key: 'date', sortable: true, visible: true },
|
||||||
{ title: 'مبلغ', key: 'amount', visible: true },
|
{ title: 'شرح', key: 'des', sortable: true, visible: true },
|
||||||
|
{ title: 'مبلغ', key: 'amount', sortable: true, visible: true },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const customizableHeaders = computed(() =>
|
const customizableHeaders = computed(() =>
|
||||||
|
@ -284,6 +304,30 @@ const dateFilterOptions = [
|
||||||
{ title: 'این ماه', value: 'thisMonth' },
|
{ title: 'این ماه', value: 'thisMonth' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const handleSort = (newSortBy, newSortDesc) => {
|
||||||
|
console.log('handleSort called:', { newSortBy, newSortDesc });
|
||||||
|
|
||||||
|
// اگر newSortBy آرایه است، اولین عنصر را بگیر
|
||||||
|
if (Array.isArray(newSortBy) && newSortBy.length > 0) {
|
||||||
|
if (typeof newSortBy[0] === 'string') {
|
||||||
|
sortBy.value = newSortBy[0];
|
||||||
|
} else if (newSortBy[0] && typeof newSortBy[0] === 'object' && newSortBy[0].key) {
|
||||||
|
sortBy.value = newSortBy[0].key;
|
||||||
|
sortDesc.value = newSortBy[0].order === 'desc';
|
||||||
|
}
|
||||||
|
} else if (typeof newSortBy === 'string') {
|
||||||
|
sortBy.value = newSortBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
// اگر newSortDesc تعریف شده، آن را اعمال کن
|
||||||
|
if (newSortDesc !== undefined) {
|
||||||
|
sortDesc.value = newSortDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Updated sort values:', { sortBy: sortBy.value, sortDesc: sortDesc.value });
|
||||||
|
loadData();
|
||||||
|
};
|
||||||
|
|
||||||
const loadData = async (options = null) => {
|
const loadData = async (options = null) => {
|
||||||
if (loading.value) return;
|
if (loading.value) return;
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
@ -294,9 +338,16 @@ const loadData = async (options = null) => {
|
||||||
itemsPerPage: options?.itemsPerPage || itemsPerPage.value,
|
itemsPerPage: options?.itemsPerPage || itemsPerPage.value,
|
||||||
search: searchValue.value,
|
search: searchValue.value,
|
||||||
dateFilter: dateFilter.value,
|
dateFilter: dateFilter.value,
|
||||||
|
sortBy: [{
|
||||||
|
key: sortBy.value,
|
||||||
|
order: sortDesc.value ? 'desc' : 'asc'
|
||||||
|
}],
|
||||||
|
sortDesc: sortDesc.value,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const response = await axios.post('/api/person/send/list/search', params);
|
const response = await axios.post('/api/person/send/list/search', params);
|
||||||
|
|
||||||
|
|
||||||
if (response.data) {
|
if (response.data) {
|
||||||
if (Array.isArray(response.data)) {
|
if (Array.isArray(response.data)) {
|
||||||
|
@ -313,6 +364,8 @@ const loadData = async (options = null) => {
|
||||||
amount: parseFloat(item.amount)
|
amount: parseFloat(item.amount)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
sumTotal.value = items.value.reduce((acc, item) => acc + parseFloat(item.amount), 0);
|
sumTotal.value = items.value.reduce((acc, item) => acc + parseFloat(item.amount), 0);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -381,6 +434,19 @@ const updateSelectedSum = () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getAccountColor = (type) => {
|
||||||
|
switch (type) {
|
||||||
|
case 'bank':
|
||||||
|
return 'primary';
|
||||||
|
case 'cashdesk':
|
||||||
|
return 'success';
|
||||||
|
case 'salary':
|
||||||
|
return 'warning';
|
||||||
|
default:
|
||||||
|
return 'grey';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const print = async (allItems = true) => {
|
const print = async (allItems = true) => {
|
||||||
if (!allItems && selectedItems.value.length === 0) {
|
if (!allItems && selectedItems.value.length === 0) {
|
||||||
Swal.fire({
|
Swal.fire({
|
||||||
|
@ -394,10 +460,25 @@ const print = async (allItems = true) => {
|
||||||
try {
|
try {
|
||||||
let response;
|
let response;
|
||||||
if (allItems) {
|
if (allItems) {
|
||||||
response = await axios.post('/api/person/send/list/print');
|
response = await axios.post('/api/person/send/list/print', {
|
||||||
|
search: searchValue.value,
|
||||||
|
dateFilter: dateFilter.value,
|
||||||
|
sortBy: [{
|
||||||
|
key: sortBy.value,
|
||||||
|
order: sortDesc.value ? 'desc' : 'asc'
|
||||||
|
}],
|
||||||
|
sortDesc: sortDesc.value,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
response = await axios.post('/api/person/send/list/print', {
|
response = await axios.post('/api/person/send/list/print', {
|
||||||
items: selectedItems.value
|
items: selectedItems.value,
|
||||||
|
search: searchValue.value,
|
||||||
|
dateFilter: dateFilter.value,
|
||||||
|
sortBy: [{
|
||||||
|
key: sortBy.value,
|
||||||
|
order: sortDesc.value ? 'desc' : 'asc'
|
||||||
|
}],
|
||||||
|
sortDesc: sortDesc.value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,14 +510,32 @@ const excellOutput = async (allItems = true) => {
|
||||||
response = await axios({
|
response = await axios({
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: '/api/person/send/list/excel',
|
url: '/api/person/send/list/excel',
|
||||||
responseType: 'arraybuffer'
|
responseType: 'arraybuffer',
|
||||||
|
data: {
|
||||||
|
search: searchValue.value,
|
||||||
|
dateFilter: dateFilter.value,
|
||||||
|
sortBy: [{
|
||||||
|
key: sortBy.value,
|
||||||
|
order: sortDesc.value ? 'desc' : 'asc'
|
||||||
|
}],
|
||||||
|
sortDesc: sortDesc.value,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
response = await axios({
|
response = await axios({
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: '/api/person/send/list/excel',
|
url: '/api/person/send/list/excel',
|
||||||
responseType: 'arraybuffer',
|
responseType: 'arraybuffer',
|
||||||
data: { items: selectedItems.value }
|
data: {
|
||||||
|
items: selectedItems.value,
|
||||||
|
search: searchValue.value,
|
||||||
|
dateFilter: dateFilter.value,
|
||||||
|
sortBy: [{
|
||||||
|
key: sortBy.value,
|
||||||
|
order: sortDesc.value ? 'desc' : 'asc'
|
||||||
|
}],
|
||||||
|
sortDesc: sortDesc.value,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,7 +574,7 @@ const loadColumnSettings = () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
watch([searchValue, page, itemsPerPage, dateFilter], () => {
|
watch([searchValue, page, itemsPerPage, dateFilter, sortBy, sortDesc], () => {
|
||||||
loadData();
|
loadData();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue