From f609c4176fefd2b37645fec600cf13bf2f37c2d1 Mon Sep 17 00:00:00 2001 From: Babak Alizadeh Date: Thu, 21 Aug 2025 15:29:02 +0000 Subject: [PATCH] bug fix in open balance --- .../src/Controller/OpenbalanceController.php | 130 +++++++++- .../src/views/acc/accounting/openBalance.vue | 226 +++++++++++++++--- 2 files changed, 314 insertions(+), 42 deletions(-) diff --git a/hesabixCore/src/Controller/OpenbalanceController.php b/hesabixCore/src/Controller/OpenbalanceController.php index 1b12cff..bb0477c 100644 --- a/hesabixCore/src/Controller/OpenbalanceController.php +++ b/hesabixCore/src/Controller/OpenbalanceController.php @@ -136,6 +136,37 @@ class OpenbalanceController extends AbstractController if (!$acc) throw $this->createAccessDeniedException(); + // بررسی مجوز تغییر تراز افتتاحیه + $years = $entityManagerInterface->getRepository(\App\Entity\Year::class)->findBy([ + 'bid' => $acc['bid'] + ], ['start' => 'ASC']); + + $currentYear = $acc['year']; + $isFirstYear = false; + $hasMultipleYears = count($years) > 1; + + // بررسی اینکه آیا سال فعلی اولین سال مالی است + if (count($years) > 0) { + $firstYear = $years[0]; + $isFirstYear = ($currentYear->getId() === $firstYear->getId()); + } + + $canModify = $isFirstYear && !$hasMultipleYears; + + if (!$canModify) { + $message = ''; + if ($hasMultipleYears && !$isFirstYear) { + $message = 'تراز افتتاحیه فقط مختص سال مالی اول است. برای سال‌های بعدی از بستن سال مالی استفاده کنید.'; + } elseif ($hasMultipleYears && $isFirstYear) { + $message = 'این کسب و کار دارای چندین سال مالی است. تراز افتتاحیه فقط در سال اول قابل تغییر است.'; + } + + return $this->json([ + 'result' => 0, + 'message' => $message + ]); + } + $params = []; if ($content = $request->getContent()) { $params = json_decode($content, true); @@ -157,7 +188,7 @@ class OpenbalanceController extends AbstractController $doc->setSubmitter($this->getUser()); $doc->setYear($acc['year']); $doc->setDes('سند افتتاحیه'); - $doc->setDate($jdate->jdate('Y/n/d', time())); + $doc->setDate($jdate->jdate('Y/n/d', $acc['year']->getStart())); $doc->setType('open_balance'); $doc->setCode($provider->getAccountingCode($acc['bid'],'accounting')); $entityManagerInterface->persist($doc); @@ -233,7 +264,7 @@ class OpenbalanceController extends AbstractController $doc->setSubmitter($this->getUser()); $doc->setYear($acc['year']); $doc->setDes('سند افتتاحیه'); - $doc->setDate($jdate->jdate('Y/n/d', time())); + $doc->setDate($jdate->jdate('Y/n/d', $acc['year']->getStart())); $doc->setType('open_balance'); $doc->setCode($provider->getAccountingCode($acc['bid'],'accounting')); $entityManagerInterface->persist($doc); @@ -309,7 +340,7 @@ class OpenbalanceController extends AbstractController $doc->setSubmitter($this->getUser()); $doc->setYear($acc['year']); $doc->setDes('سند افتتاحیه'); - $doc->setDate($jdate->jdate('Y/n/d', time())); + $doc->setDate($jdate->jdate('Y/n/d', $acc['year']->getStart())); $doc->setType('open_balance'); $doc->setCode($provider->getAccountingCode($acc['bid'],'accounting')); $entityManagerInterface->persist($doc); @@ -385,7 +416,7 @@ class OpenbalanceController extends AbstractController $doc->setSubmitter($this->getUser()); $doc->setYear($acc['year']); $doc->setDes('سند افتتاحیه'); - $doc->setDate($jdate->jdate('Y/n/d', time())); + $doc->setDate($jdate->jdate('Y/n/d', $acc['year']->getStart())); $doc->setType('open_balance'); $doc->setCode($provider->getAccountingCode($acc['bid'],'accounting')); $entityManagerInterface->persist($doc); @@ -468,7 +499,7 @@ class OpenbalanceController extends AbstractController $doc->setSubmitter($this->getUser()); $doc->setYear($acc['year']); $doc->setDes('سند افتتاحیه'); - $doc->setDate($jdate->jdate('Y/n/d', time())); + $doc->setDate($jdate->jdate('Y/n/d', $acc['year']->getStart())); $doc->setType('open_balance'); $doc->setCode($provider->getAccountingCode($acc['bid'],'accounting')); $entityManagerInterface->persist($doc); @@ -533,4 +564,93 @@ class OpenbalanceController extends AbstractController $entityManagerInterface->flush(); return $this->json($extractor->operationSuccess()); } + + #[Route('/api/openbalance/check-permission', name: 'app_openbalance_check_permission')] + public function app_openbalance_check_permission(Access $access, EntityManagerInterface $entityManagerInterface, Extractor $extractor): Response + { + $acc = $access->hasRole('accounting'); + if (!$acc) + throw $this->createAccessDeniedException(); + + // بررسی تعداد سال‌های مالی کسب و کار + $years = $entityManagerInterface->getRepository(\App\Entity\Year::class)->findBy([ + 'bid' => $acc['bid'] + ], ['start' => 'ASC']); + + $currentYear = $acc['year']; + $isFirstYear = false; + $hasMultipleYears = count($years) > 1; + + // بررسی اینکه آیا سال فعلی اولین سال مالی است + if (count($years) > 0) { + $firstYear = $years[0]; + $isFirstYear = ($currentYear->getId() === $firstYear->getId()); + } + + // بررسی اینکه آیا سند افتتاحیه قبلاً ایجاد شده + $existingDoc = $entityManagerInterface->getRepository(HesabdariDoc::class)->findOneBy([ + 'year' => $currentYear, + 'bid' => $acc['bid'], + 'type' => 'open_balance', + 'money' => $acc['money'] + ]); + + $canModify = $isFirstYear && !$hasMultipleYears; + $message = ''; + + if ($hasMultipleYears && !$isFirstYear) { + $message = 'تراز افتتاحیه فقط مختص سال مالی اول است. برای سال‌های بعدی از بستن سال مالی استفاده کنید.'; + } elseif ($hasMultipleYears && $isFirstYear) { + $message = 'این کسب و کار دارای چندین سال مالی است. تراز افتتاحیه فقط در سال اول قابل تغییر است.'; + } elseif ($existingDoc) { + $message = 'سند افتتاحیه قبلاً ایجاد شده است.'; + } + + return $this->json([ + 'canModify' => $canModify, + 'isFirstYear' => $isFirstYear, + 'hasMultipleYears' => $hasMultipleYears, + 'existingDoc' => $existingDoc ? true : false, + 'message' => $message, + 'yearsCount' => count($years) + ]); + } + + /** + * بررسی مجوز تغییر تراز افتتاحیه + */ + private function checkOpeningBalancePermission(EntityManagerInterface $entityManagerInterface, array $acc): array + { + // بررسی تعداد سال‌های مالی کسب و کار + $years = $entityManagerInterface->getRepository(\App\Entity\Year::class)->findBy([ + 'bid' => $acc['bid'] + ], ['start' => 'ASC']); + + $currentYear = $acc['year']; + $isFirstYear = false; + $hasMultipleYears = count($years) > 1; + + // بررسی اینکه آیا سال فعلی اولین سال مالی است + if (count($years) > 0) { + $firstYear = $years[0]; + $isFirstYear = ($currentYear->getId() === $firstYear->getId()); + } + + $canModify = $isFirstYear && !$hasMultipleYears; + $message = ''; + + if ($hasMultipleYears && !$isFirstYear) { + $message = 'تراز افتتاحیه فقط مختص سال مالی اول است. برای سال‌های بعدی از بستن سال مالی استفاده کنید.'; + } elseif ($hasMultipleYears && $isFirstYear) { + $message = 'این کسب و کار دارای چندین سال مالی است. تراز افتتاحیه فقط در سال اول قابل تغییر است.'; + } + + return [ + 'canModify' => $canModify, + 'message' => $message, + 'isFirstYear' => $isFirstYear, + 'hasMultipleYears' => $hasMultipleYears, + 'yearsCount' => count($years) + ]; + } } diff --git a/webUI/src/views/acc/accounting/openBalance.vue b/webUI/src/views/acc/accounting/openBalance.vue index 36aeabb..cce3a9e 100755 --- a/webUI/src/views/acc/accounting/openBalance.vue +++ b/webUI/src/views/acc/accounting/openBalance.vue @@ -12,6 +12,9 @@ + + + @@ -82,7 +85,7 @@ - + @@ -92,7 +95,7 @@
- +
@@ -111,7 +114,7 @@ - + @@ -121,7 +124,7 @@
- +
@@ -140,7 +143,7 @@ - + @@ -150,7 +153,7 @@
- +
@@ -169,7 +172,7 @@ - + @@ -179,7 +182,7 @@
- +
@@ -204,6 +207,7 @@
{ + this.permission = response.data; + }).catch(error => { + console.error('Error checking permission:', error); + this.permission.canModify = false; + this.permission.message = 'خطا در بررسی مجوز'; + }); + }, loadData() { this.sums.banks = 0; this.sums.cashdesks = 0; @@ -509,35 +531,147 @@ export default { }, saveBanks() { this.loading = true; - axios.post('/api/openbalance/save/banks', this.data.banks).then((Response) => { + + // ابتدا بررسی مجوز + axios.post('/api/openbalance/check-permission').then((permissionResponse) => { + if (!permissionResponse.data.canModify) { + this.loading = false; + this.snackbar.text = permissionResponse.data.message; + this.snackbar.color = 'error'; + this.snackbar.show = true; + return; + } + + // اگر مجوز داشت، ذخیره کن + axios.post('/api/openbalance/save/banks', this.data.banks).then((Response) => { + this.loading = false; + this.loadData(); + this.sheet.banks = false; + this.snackbar.text = 'اطلاعات بانک‌ها با موفقیت ذخیره شد'; + this.snackbar.color = 'success'; + this.snackbar.show = true; + }).catch(error => { + this.loading = false; + this.snackbar.text = 'خطا در ذخیره اطلاعات'; + this.snackbar.color = 'error'; + this.snackbar.show = true; + console.error('Error saving banks:', error); + }); + }).catch(error => { this.loading = false; - this.loadData(); - this.sheet.banks = false; - }) + this.snackbar.text = 'خطا در بررسی مجوز'; + this.snackbar.color = 'error'; + this.snackbar.show = true; + console.error('Error checking permission:', error); + }); }, saveCashdesks() { this.loading = true; - axios.post('/api/openbalance/save/cashdesks', this.data.cashdesks).then((Response) => { + + // ابتدا بررسی مجوز + axios.post('/api/openbalance/check-permission').then((permissionResponse) => { + if (!permissionResponse.data.canModify) { + this.loading = false; + this.snackbar.text = permissionResponse.data.message; + this.snackbar.color = 'error'; + this.snackbar.show = true; + return; + } + + // اگر مجوز داشت، ذخیره کن + axios.post('/api/openbalance/save/cashdesks', this.data.cashdesks).then((Response) => { + this.loading = false; + this.loadData(); + this.sheet.cashdesks = false; + this.snackbar.text = 'اطلاعات صندوق‌ها با موفقیت ذخیره شد'; + this.snackbar.color = 'success'; + this.snackbar.show = true; + }).catch(error => { + this.loading = false; + this.snackbar.text = 'خطا در ذخیره اطلاعات'; + this.snackbar.color = 'error'; + this.snackbar.show = true; + console.error('Error saving cashdesks:', error); + }); + }).catch(error => { this.loading = false; - this.loadData(); - this.sheet.cashdesks = false; - }) + this.snackbar.text = 'خطا در بررسی مجوز'; + this.snackbar.color = 'error'; + this.snackbar.show = true; + console.error('Error checking permission:', error); + }); }, saveSalarys() { this.loading = true; - axios.post('/api/openbalance/save/salarys', this.data.salarys).then((Response) => { + + // ابتدا بررسی مجوز + axios.post('/api/openbalance/check-permission').then((permissionResponse) => { + if (!permissionResponse.data.canModify) { + this.loading = false; + this.snackbar.text = permissionResponse.data.message; + this.snackbar.color = 'error'; + this.snackbar.show = true; + return; + } + + // اگر مجوز داشت، ذخیره کن + axios.post('/api/openbalance/save/salarys', this.data.salarys).then((Response) => { + this.loading = false; + this.loadData(); + this.sheet.salarys = false; + this.snackbar.text = 'اطلاعات تنخواه‌گردان‌ها با موفقیت ذخیره شد'; + this.snackbar.color = 'success'; + this.snackbar.show = true; + }).catch(error => { + this.loading = false; + this.snackbar.text = 'خطا در ذخیره اطلاعات'; + this.snackbar.color = 'error'; + this.snackbar.show = true; + console.error('Error saving salarys:', error); + }); + }).catch(error => { this.loading = false; - this.loadData(); - this.sheet.salarys = false; - }) + this.snackbar.text = 'خطا در بررسی مجوز'; + this.snackbar.color = 'error'; + this.snackbar.show = true; + console.error('Error checking permission:', error); + }); }, saveShareholders() { this.loading = true; - axios.post('/api/openbalance/save/shareholders', this.data.shareholders).then((Response) => { + + // ابتدا بررسی مجوز + axios.post('/api/openbalance/check-permission').then((permissionResponse) => { + if (!permissionResponse.data.canModify) { + this.loading = false; + this.snackbar.text = permissionResponse.data.message; + this.snackbar.color = 'error'; + this.snackbar.show = true; + return; + } + + // اگر مجوز داشت، ذخیره کن + axios.post('/api/openbalance/save/shareholders', this.data.shareholders).then((Response) => { + this.loading = false; + this.loadData(); + this.sheet.shareholders = false; + this.snackbar.text = 'اطلاعات سهام‌داران با موفقیت ذخیره شد'; + this.snackbar.color = 'success'; + this.snackbar.show = true; + }).catch(error => { + this.loading = false; + this.snackbar.text = 'خطا در ذخیره اطلاعات'; + this.snackbar.color = 'error'; + this.snackbar.show = true; + console.error('Error saving shareholders:', error); + }); + }).catch(error => { this.loading = false; - this.loadData(); - this.sheet.shareholders = false; - }) + this.snackbar.text = 'خطا در بررسی مجوز'; + this.snackbar.color = 'error'; + this.snackbar.show = true; + console.error('Error checking permission:', error); + }); }, calculateTotalPrice(item) { item.totalPrice = parseFloat(item.count || 0) * parseFloat(item.price || 0); @@ -609,19 +743,37 @@ export default { totalPrice: parseFloat(item.totalPrice) })); - axios.post('/api/openbalance/save/commodities', commoditiesData).then((Response) => { - this.loading = false; - this.loadData(); - this.sheet.inventory = false; - this.snackbar.text = this.$t('dialog.inventory.save_success'); - this.snackbar.color = 'success'; - this.snackbar.show = true; + // ابتدا بررسی مجوز + axios.post('/api/openbalance/check-permission').then((permissionResponse) => { + if (!permissionResponse.data.canModify) { + this.loading = false; + this.snackbar.text = permissionResponse.data.message; + this.snackbar.color = 'error'; + this.snackbar.show = true; + return; + } + + // اگر مجوز داشت، ذخیره کن + axios.post('/api/openbalance/save/commodities', commoditiesData).then((Response) => { + this.loading = false; + this.loadData(); + this.sheet.inventory = false; + this.snackbar.text = 'اطلاعات موجودی کالا با موفقیت ذخیره شد'; + this.snackbar.color = 'success'; + this.snackbar.show = true; + }).catch(error => { + this.loading = false; + this.snackbar.text = 'خطا در ذخیره اطلاعات'; + this.snackbar.color = 'error'; + this.snackbar.show = true; + console.error('Error saving inventory:', error); + }); }).catch(error => { this.loading = false; - this.snackbar.text = this.$t('dialog.inventory.save_error'); + this.snackbar.text = 'خطا در بررسی مجوز'; this.snackbar.color = 'error'; this.snackbar.show = true; - console.error('Error saving inventory:', error); + console.error('Error checking permission:', error); }); }, validateInventory() {