some bug fixes

This commit is contained in:
Hesabix 2025-11-02 10:08:30 +00:00
parent a579a020bc
commit 9074059abd
4 changed files with 166 additions and 5 deletions

View file

@ -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 فیلد تاریخ ثبت ندارد

View file

@ -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
{

View file

@ -34,7 +34,7 @@
<td style="width:20%">
<h4>
<b>تاریخ:</b>
{{ "now"|date("Y/m/d H:i") }}</h4>
{{ Jdate.jdate('Y/m/d H:i', 'now') }}</h4>
<br/>
<h4>
<b>انبار:</b>
@ -96,9 +96,9 @@
<tr class="stimol">
<td class="center item">{{ loop.index }}</td>
<td class="center item">{{ item.commodity.code }}</td>
<td class="center item">{{ item.commodity.cat.name }}</td>
<td class="center item">{{ item.commodity.cat is defined and item.commodity.cat is not null ? item.commodity.cat.name : '' }}</td>
<td class="center item">{{ item.commodity.name }}</td>
<td class="center item">{{ item.commodity.unit.name }}</td>
<td class="center item">{{ item.commodity.unit is defined and item.commodity.unit is not null ? item.commodity.unit.name : '' }}</td>
<td class="center item">{{ item.input }}</td>
<td class="center item">{{ item.output }}</td>
<td class="center item {% if item.existCount < 0 %}text-danger{% endif %}">

View file

@ -98,6 +98,44 @@ export default defineComponent({
})
}
const exportExcel = async () => {
if (!storeroom.value) {
alert('لطفا ابتدا انبار را انتخاب کنید')
return
}
loading.value = true
try {
const res = await axios.post('/api/storeroom/exist/export', {
storeroom: storeroom.value,
items: items.value,
}, { responseType: 'blob' })
const blob = new Blob([res.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
const url = window.URL.createObjectURL(blob)
const link = document.createElement('a')
const disposition = res.headers['content-disposition'] || res.headers['Content-Disposition']
let filename = 'storeroom_exist.xlsx'
if (disposition) {
const match = disposition.match(/filename\*=UTF-8''([^;]+)|filename="?([^";]+)"?/)
const extracted = decodeURIComponent(match?.[1] || match?.[2] || '')
if (extracted) filename = extracted
}
link.href = url
link.setAttribute('download', filename)
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
window.URL.revokeObjectURL(url)
} catch (error) {
console.error('خطا در خروجی اکسل:', error)
alert('خطا در خروجی اکسل')
} finally {
loading.value = false
}
}
watch(searchValue, filterItems)
watch(showZeroTransactions, filterItems)
onMounted(loadData)
@ -111,7 +149,8 @@ export default defineComponent({
headers,
loadStoreItems,
showZeroTransactions,
print
print,
exportExcel
}
}
})
@ -145,6 +184,13 @@ export default defineComponent({
</v-btn>
</template>
</v-tooltip>
<v-tooltip text="خروجی اکسل" location="bottom">
<template v-slot:activator="{ props }">
<v-btn v-bind="props" icon @click="exportExcel()" color="success">
<v-icon>mdi-file-excel</v-icon>
</v-btn>
</template>
</v-tooltip>
</v-toolbar>
<v-container fluid>
<v-row>