diff --git a/hesabixCore/src/Controller/BackupController.php b/hesabixCore/src/Controller/BackupController.php index b495448..c7c1380 100644 --- a/hesabixCore/src/Controller/BackupController.php +++ b/hesabixCore/src/Controller/BackupController.php @@ -244,6 +244,7 @@ class BackupController extends AbstractController 'قیمت خرید', 'قیمت فروش', 'موجودی', + 'ارزش اسمی', 'حداقل سفارش', 'توضیحات', 'تاریخ ثبت' @@ -257,9 +258,38 @@ class BackupController extends AbstractController // دریافت کالاها $commodities = $entityManager->getRepository(\App\Entity\Commodity::class)->findBy(['bid' => $business]); + + // محاسبه تجمیعی موجودی کالا بر اساس ردیفهای حسابداری تاییدشده + $qb = $entityManager->createQueryBuilder(); + $qb->select('c.id AS cid, SUM(CASE WHEN d.type IN (:plusTypes) THEN COALESCE(r.commdityCount, 0) WHEN d.type IN (:minusTypes) THEN -COALESCE(r.commdityCount, 0) ELSE 0 END) AS stock') + ->from(\App\Entity\HesabdariRow::class, 'r') + ->join('r.doc', 'd') + ->join('r.commodity', 'c') + ->where('r.bid = :bid') + ->andWhere('d.isApproved = :approved') + ->groupBy('c.id') + ->setParameter('bid', $business) + ->setParameter('approved', true) + ->setParameter('plusTypes', ['buy', 'open_balance', 'rfsell']) + ->setParameter('minusTypes', ['sell', 'rfbuy']); + + $stockResults = $qb->getQuery()->getArrayResult(); + $stockMap = []; + foreach ($stockResults as $sr) { + $stockMap[(int)$sr['cid']] = (float)$sr['stock']; + } $row = 2; foreach ($commodities as $commodity) { + // محاسبه موجودی و ارزش اسمی + $count = 0.0; + if (!$commodity->isKhadamat()) { + $count = $stockMap[$commodity->getId()] ?? 0.0; + } + $priceSell = $commodity->getPriceSell(); + $priceSell = is_numeric($priceSell) ? (float)$priceSell : 0.0; + $nominalValue = $count * $priceSell; + $data = [ $commodity->getName(), $commodity->getCode(), @@ -267,7 +297,8 @@ class BackupController extends AbstractController $commodity->getUnit() ? $commodity->getUnit()->getName() : '', $commodity->getPriceBuy(), $commodity->getPriceSell(), - '', // Entity Commodity فیلد موجودی ندارد + $count, + $nominalValue, $commodity->getMinOrderCount(), // حداقل سفارش $commodity->getDes(), '' // Entity Commodity فیلد تاریخ ثبت ندارد diff --git a/hesabixCore/src/Controller/StoreroomController.php b/hesabixCore/src/Controller/StoreroomController.php index bf5f976..751c116 100644 --- a/hesabixCore/src/Controller/StoreroomController.php +++ b/hesabixCore/src/Controller/StoreroomController.php @@ -28,6 +28,9 @@ use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use PhpOffice\PhpSpreadsheet\Spreadsheet; +use PhpOffice\PhpSpreadsheet\Writer\Xlsx; +use Symfony\Component\HttpFoundation\StreamedResponse; class StoreroomController extends AbstractController { @@ -995,6 +998,87 @@ class StoreroomController extends AbstractController return $this->json(['id' => $pdfPid]); } + #[Route('/api/storeroom/exist/export', name: 'app_storeroom_exist_export', methods: ['POST'])] + public function app_storeroom_exist_export(Request $request, Access $access, EntityManagerInterface $entityManager): StreamedResponse + { + $params = []; + if ($content = $request->getContent()) { + $params = json_decode($content, true); + } + + $acc = $access->hasRole('store'); + if (!$acc) { + throw $this->createAccessDeniedException(); + } + + $storeroomId = $params['storeroom'] ?? null; + if (!$storeroomId) { + throw $this->createNotFoundException('انبار انتخاب نشده است'); + } + + $storeroom = $entityManager->getRepository(Storeroom::class)->find($storeroomId); + if (!$storeroom) { + throw $this->createNotFoundException('انبار مورد نظر یافت نشد'); + } + + $items = $params['items'] ?? []; + + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + $sheet->setRightToLeft(true); + + $headers = [ + 'کد', + 'دسته بندی', + 'نام', + 'واحد', + 'ورودی', + 'خروجی', + 'موجودی انبار', + 'نقطه سفارش', + 'وضعیت', + ]; + $sheet->fromArray($headers, null, 'A1'); + + $rowIndex = 2; + foreach ($items as $item) { + $commodity = $item['commodity'] ?? []; + $cat = $commodity['cat'] ?? []; + $unit = $commodity['unit'] ?? []; + $existCount = (int)($item['existCount'] ?? 0); + $orderPoint = (int)($commodity['orderPoint'] ?? 0); + $operation = $existCount < $orderPoint ? 'نیاز به شارژ انبار' : ''; + + $row = [ + $commodity['code'] ?? '', + $cat['name'] ?? '', + $commodity['name'] ?? '', + $unit['name'] ?? '', + $item['input'] ?? 0, + $item['output'] ?? 0, + $existCount, + $orderPoint, + $operation, + ]; + + $sheet->fromArray($row, null, 'A' . $rowIndex); + $rowIndex++; + } + + $fileName = 'موجودی_انبار_' . ($storeroom->getName() ?? 'store') . '.xlsx'; + + $response = new StreamedResponse(function () use ($spreadsheet) { + $writer = new Xlsx($spreadsheet); + $writer->save('php://output'); + }); + + $response->headers->set('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); + $response->headers->set('Content-Disposition', 'attachment;filename="' . $fileName . '"'); + $response->headers->set('Cache-Control', 'max-age=0'); + + return $response; + } + #[Route('/api/storeroom/ticket/complete/{id}', name: 'app_storeroom_ticket_complete', methods: ['POST'])] public function app_storeroom_ticket_complete(string $id, Request $request, Access $access, Log $log, EntityManagerInterface $entityManager, PluginService $pluginService): JsonResponse { diff --git a/hesabixCore/templates/pdf/printers/storeroom/exist.html.twig b/hesabixCore/templates/pdf/printers/storeroom/exist.html.twig index 9d37bca..eb280fe 100644 --- a/hesabixCore/templates/pdf/printers/storeroom/exist.html.twig +++ b/hesabixCore/templates/pdf/printers/storeroom/exist.html.twig @@ -34,7 +34,7 @@