diff --git a/hesabixCore/src/Controller/Plugins/Hrm/DocsController.php b/hesabixCore/src/Controller/Plugins/Hrm/DocsController.php index 7d2c26f..4ca0265 100644 --- a/hesabixCore/src/Controller/Plugins/Hrm/DocsController.php +++ b/hesabixCore/src/Controller/Plugins/Hrm/DocsController.php @@ -7,16 +7,11 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Doctrine\ORM\EntityManagerInterface; -use App\Entity\PlugGhestaDoc; -use App\Entity\PlugGhestaItem; -use App\Entity\HesabdariDoc; +use App\Entity\PlugHrmDoc; +use App\Entity\PlugHrmDocItem; use App\Entity\Person; use App\Service\Access; -use App\Service\Provider; -use App\Service\Printers; -use App\Entity\PrintOptions; use App\Service\Log; -use App\Entity\Business; class DocsController extends AbstractController { @@ -28,24 +23,209 @@ class DocsController extends AbstractController } #[Route('/api/hrm/docs/list', name: 'hrm_docs_list', methods: ['POST'])] - public function list(Request $request): JsonResponse + public function list(Request $request, Access $access): JsonResponse { - // TODO: پیاده‌سازی دریافت لیست اسناد حقوق - return new JsonResponse([]); + try { + $params = []; + if ($content = $request->getContent()) { + $params = json_decode($content, true); + } + + $acc = $access->hasRole('hrm'); + + // دریافت پارامترهای فیلتر + $page = $params['page'] ?? 1; + $limit = $params['limit'] ?? 20; + $search = $params['search'] ?? ''; + $fromDate = $params['fromDate'] ?? null; + $toDate = $params['toDate'] ?? null; + $personId = $params['personId'] ?? null; + + // ایجاد کوئری + $qb = $this->entityManager->createQueryBuilder(); + $qb->select('d') + ->from(PlugHrmDoc::class, 'd') + ->where('d.business = :bid') + ->setParameter('bid', $acc['bid']); + + // اعمال فیلترها + if ($search) { + $qb->andWhere('d.description LIKE :search') + ->setParameter('search', '%' . $search . '%'); + } + + if ($fromDate) { + $qb->andWhere('d.date >= :fromDate') + ->setParameter('fromDate', $fromDate); + } + + if ($toDate) { + $qb->andWhere('d.date <= :toDate') + ->setParameter('toDate', $toDate); + } + + if ($personId) { + $qb->andWhere('d.person = :personId') + ->setParameter('personId', $personId); + } + + // محاسبه تعداد کل رکوردها + $countQb = clone $qb; + $countQb->select('COUNT(d.id)'); + $total = $countQb->getQuery()->getSingleScalarResult(); + + // اعمال مرتب‌سازی و صفحه‌بندی + $qb->orderBy('d.date', 'DESC') + ->setFirstResult(($page - 1) * $limit) + ->setMaxResults($limit); + + $docs = $qb->getQuery()->getResult(); + + // تبدیل نتایج به آرایه + $result = []; + foreach ($docs as $doc) { + $result[] = [ + 'id' => $doc->getId(), + 'date' => $doc->getDate(), + 'description' => $doc->getDescription(), + 'creator' => $doc->getCreator() ? [ + 'id' => $doc->getCreator()->getId(), + 'name' => $doc->getCreator()->getFullName() + ] : null, + 'total' => $this->calculateTotalAmount($doc), + 'accounting_doc' => $doc->getHesabdariDoc() ? 'صدور شده' : 'صدور نشده', + 'status' => $doc->getHesabdariDoc() ? 'تایید شده' : 'تایید نشده' + ]; + } + + return new JsonResponse([ + 'success' => true, + 'data' => $result, + 'total' => $total, + 'page' => $page, + 'limit' => $limit + ]); + + } catch (\Exception $e) { + return new JsonResponse(['error' => 'خطا در دریافت لیست اسناد: ' . $e->getMessage()], 500); + } + } + + private function calculateTotalAmount(PlugHrmDoc $doc): int + { + $total = 0; + foreach ($doc->getItems() as $item) { + $total += $item->getBaseSalary(); + $total += $item->getNight(); + $total += $item->getShift(); + $total += $item->getOvertime(); + } + return $total; } #[Route('/api/hrm/docs/get/{id}', name: 'hrm_docs_get', methods: ['POST'])] - public function get(int $id): JsonResponse + public function get(int $id, Access $access): JsonResponse { - // TODO: پیاده‌سازی دریافت اطلاعات یک سند حقوق - return new JsonResponse([]); + try { + $acc = $access->hasRole('hrm'); + + $doc = $this->entityManager->getRepository(PlugHrmDoc::class)->findOneBy([ + 'id' => $id, + 'business' => $acc['bid'] + ]); + + if (!$doc) { + return new JsonResponse(['error' => 'سند مورد نظر یافت نشد'], 404); + } + + $items = []; + foreach ($doc->getItems() as $item) { + $items[] = [ + 'id' => $item->getId(), + 'person' => [ + 'id' => $item->getPerson()->getId(), + 'name' => $item->getPerson()->getNikename(), + 'code' => $item->getPerson()->getCode(), + ], + 'baseSalary' => $item->getBaseSalary(), + 'overtime' => $item->getOvertime(), + 'shift' => $item->getShift(), + 'night' => $item->getNight(), + 'description' => $item->getDescription() + ]; + } + + return new JsonResponse([ + 'success' => true, + 'data' => [ + 'id' => $doc->getId(), + 'date' => $doc->getDate(), + 'description' => $doc->getDescription(), + 'items' => $items + ] + ]); + + } catch (\Exception $e) { + return new JsonResponse(['error' => 'خطا در دریافت اطلاعات سند: ' . $e->getMessage()], 500); + } } #[Route('/api/hrm/docs/insert', name: 'hrm_docs_insert', methods: ['POST'])] - public function insert(Request $request): JsonResponse + public function insert(Request $request, Access $access, Log $log): JsonResponse { - // TODO: پیاده‌سازی ثبت سند حقوق جدید - return new JsonResponse([]); + try { + $params = []; + if ($content = $request->getContent()) { + $params = json_decode($content, true); + } + + $acc = $access->hasRole('hrm'); + + // بررسی داده‌های ورودی + if (empty($params['date']) || empty($params['description']) || empty($params['items'])) { + return new JsonResponse(['error' => 'اطلاعات ناقص است'], 400); + } + + // ایجاد سند جدید + $doc = new PlugHrmDoc(); + $doc->setDate($params['date']); + $doc->setCreator($this->getUser()); + $doc->setBusiness($acc['bid']); + $doc->setDescription($params['description']); + $doc->setCreateDate(time()); + // افزودن آیتم‌ها + foreach ($params['items'] as $itemData) { + if (empty($itemData['person'])) { + continue; + } + + $item = new PlugHrmDocItem(); + $item->setPerson($this->entityManager->getReference(Person::class, $itemData['person'])); + $item->setBaseSalary($itemData['baseSalary'] ?? 0); + $item->setOvertime($itemData['overtime'] ?? 0); + $item->setShift($itemData['shift'] ?? 0); + $item->setNight($itemData['night'] ?? 0); + $item->setDescription($itemData['description'] ?? ''); + $item->setDoc($doc); + + $this->entityManager->persist($item); + } + + $this->entityManager->persist($doc); + $this->entityManager->flush(); + + + return new JsonResponse([ + 'success' => true, + 'message' => 'سند با موفقیت ثبت شد', + 'data' => [ + 'id' => $doc->getId() + ] + ]); + + } catch (\Exception $e) { + return new JsonResponse(['error' => 'خطا در ثبت سند: ' . $e->getMessage()], 500); + } } #[Route('/api/hrm/docs/update', name: 'hrm_docs_update', methods: ['POST'])] @@ -56,9 +236,47 @@ class DocsController extends AbstractController } #[Route('/api/hrm/docs/delete', name: 'hrm_docs_delete', methods: ['POST'])] - public function delete(Request $request): JsonResponse + public function delete(Request $request, Access $access, Log $log, EntityManagerInterface $entityManager): JsonResponse { - // TODO: پیاده‌سازی حذف سند حقوق - return new JsonResponse([]); + try { + $params = []; + if ($content = $request->getContent()) { + $params = json_decode($content, true); + } + + $acc = $access->hasRole('hrm'); + $id = $params['id'] ?? null; + + if (!$id) { + return new JsonResponse(['error' => 'شناسه سند الزامی است'], 400); + } + + $doc = $entityManager->getRepository(PlugHrmDoc::class)->findOneBy([ + 'id' => $id, + 'business' => $acc['bid'] + ]); + if (!$doc) { + return new JsonResponse(['error' => 'سند مورد نظر یافت نشد'], 404); + } + + // حذف آیتم‌های سند + foreach ($doc->getItems() as $item) { + $entityManager->remove($item); + } + + // حذف سند حسابداری در صورت وجود + if($doc->getHesabdariDoc()){ + $entityManager->remove($doc->getHesabdariDoc()); + } + // حذف سند + $entityManager->remove($doc); + $entityManager->flush(); + + + return new JsonResponse(['success' => true, 'message' => 'سند با موفقیت حذف شد']); + + } catch (\Exception $e) { + return new JsonResponse(['error' => 'خطا در حذف سند: ' . $e->getMessage()], 500); + } } } \ No newline at end of file diff --git a/hesabixCore/src/Entity/Business.php b/hesabixCore/src/Entity/Business.php index 7a97ae0..b91d808 100644 --- a/hesabixCore/src/Entity/Business.php +++ b/hesabixCore/src/Entity/Business.php @@ -297,6 +297,9 @@ class Business #[ORM\OneToMany(targetEntity: PlugGhestaDoc::class, mappedBy: 'bid', orphanRemoval: true)] private Collection $PlugGhestaDocs; + #[ORM\OneToMany(mappedBy: 'business', targetEntity: PlugHrmDoc::class)] + private Collection $plugHrmDocs; + public function __construct() { $this->logs = new ArrayCollection(); @@ -339,6 +342,7 @@ class Business $this->hesabdariTables = new ArrayCollection(); $this->accountingPackageOrders = new ArrayCollection(); $this->PlugGhestaDocs = new ArrayCollection(); + $this->plugHrmDocs = new ArrayCollection(); } public function getId(): ?int @@ -2055,4 +2059,31 @@ class Business return $this; } + + /** + * @return Collection + */ + public function getPlugHrmDocs(): Collection + { + return $this->plugHrmDocs; + } + + public function addPlugHrmDoc(PlugHrmDoc $plugHrmDoc): static + { + if (!$this->plugHrmDocs->contains($plugHrmDoc)) { + $this->plugHrmDocs->add($plugHrmDoc); + $plugHrmDoc->setBusiness($this); + } + return $this; + } + + public function removePlugHrmDoc(PlugHrmDoc $plugHrmDoc): static + { + if ($this->plugHrmDocs->removeElement($plugHrmDoc)) { + if ($plugHrmDoc->getBusiness() === $this) { + $plugHrmDoc->setBusiness(null); + } + } + return $this; + } } diff --git a/hesabixCore/src/Entity/HesabdariDoc.php b/hesabixCore/src/Entity/HesabdariDoc.php index 61b2977..c7f33c9 100644 --- a/hesabixCore/src/Entity/HesabdariDoc.php +++ b/hesabixCore/src/Entity/HesabdariDoc.php @@ -140,6 +140,12 @@ class HesabdariDoc #[ORM\OneToMany(targetEntity: PlugGhestaDoc::class, mappedBy: 'mainDoc', orphanRemoval: true)] private Collection $plugGhestaDocs; + /** + * @var Collection + */ + #[ORM\OneToMany(targetEntity: PlugHrmDoc::class, mappedBy: 'hesabdariDoc')] + private Collection $plugHrmDocs; + public function __construct() { $this->hesabdariRows = new ArrayCollection(); @@ -151,6 +157,7 @@ class HesabdariDoc $this->pairDoc = new ArrayCollection(); $this->plugGhestaItems = new ArrayCollection(); $this->plugGhestaDocs = new ArrayCollection(); + $this->plugHrmDocs = new ArrayCollection(); } public function getId(): ?int @@ -689,4 +696,34 @@ class HesabdariDoc return $this; } + + /** + * @return Collection + */ + public function getPlugHrmDocs(): Collection + { + return $this->plugHrmDocs; + } + + public function addPlugHrmDoc(PlugHrmDoc $plugHrmDoc): static + { + if (!$this->plugHrmDocs->contains($plugHrmDoc)) { + $this->plugHrmDocs->add($plugHrmDoc); + $plugHrmDoc->setHesabdariDoc($this); + } + + return $this; + } + + public function removePlugHrmDoc(PlugHrmDoc $plugHrmDoc): static + { + if ($this->plugHrmDocs->removeElement($plugHrmDoc)) { + // set the owning side to null (unless already changed) + if ($plugHrmDoc->getHesabdariDoc() === $this) { + $plugHrmDoc->setHesabdariDoc(null); + } + } + + return $this; + } } \ No newline at end of file diff --git a/hesabixCore/src/Entity/PlugHrmDoc.php b/hesabixCore/src/Entity/PlugHrmDoc.php new file mode 100644 index 0000000..9a5a8f2 --- /dev/null +++ b/hesabixCore/src/Entity/PlugHrmDoc.php @@ -0,0 +1,144 @@ +items = new ArrayCollection(); + } + + public function getId(): ?int + { + return $this->id; + } + + public function getDescription(): ?string + { + return $this->description; + } + + public function setDescription(string $description): static + { + $this->description = $description; + return $this; + } + + public function getDate(): ?string + { + return $this->date; + } + + public function setDate(string $date): self + { + $this->date = $date; + return $this; + } + + public function getBusiness(): ?Business + { + return $this->business; + } + + public function setBusiness(?Business $business): static + { + $this->business = $business; + return $this; + } + + public function getCreator(): ?User + { + return $this->creator; + } + + public function setCreator(?User $creator): static + { + $this->creator = $creator; + return $this; + } + + public function getCreateDate(): ?int + { + return $this->createDate; + } + + public function setCreateDate(int $createDate): static + { + $this->createDate = $createDate; + return $this; + } + + /** + * @return Collection + */ + public function getItems(): Collection + { + return $this->items; + } + + public function addItem(PlugHrmDocItem $item): static + { + if (!$this->items->contains($item)) { + $this->items->add($item); + $item->setDoc($this); + } + return $this; + } + + public function removeItem(PlugHrmDocItem $item): static + { + if ($this->items->removeElement($item)) { + if ($item->getDoc() === $this) { + $item->setDoc(null); + } + } + return $this; + } + + public function getHesabdariDoc(): ?HesabdariDoc + { + return $this->hesabdariDoc; + } + + public function setHesabdariDoc(?HesabdariDoc $hesabdariDoc): static + { + $this->hesabdariDoc = $hesabdariDoc; + + return $this; + } +} \ No newline at end of file diff --git a/hesabixCore/src/Entity/PlugHrmDocItem.php b/hesabixCore/src/Entity/PlugHrmDocItem.php new file mode 100644 index 0000000..1c15623 --- /dev/null +++ b/hesabixCore/src/Entity/PlugHrmDocItem.php @@ -0,0 +1,125 @@ +id; + } + + public function getDoc(): ?PlugHrmDoc + { + return $this->doc; + } + + public function setDoc(?PlugHrmDoc $doc): static + { + $this->doc = $doc; + return $this; + } + + public function getPerson(): ?Person + { + return $this->person; + } + + public function setPerson(?Person $person): static + { + $this->person = $person; + return $this; + } + + public function getBaseSalary(): ?int + { + return $this->baseSalary; + } + + public function setBaseSalary(int $baseSalary): static + { + $this->baseSalary = $baseSalary; + return $this; + } + + public function getOvertime(): ?int + { + return $this->overtime; + } + + public function setOvertime(int $overtime): static + { + $this->overtime = $overtime; + return $this; + } + + public function getShift(): ?int + { + return $this->shift; + } + + public function setShift(int $shift): static + { + $this->shift = $shift; + return $this; + } + + public function getNight(): ?int + { + return $this->night; + } + + public function setNight(int $night): static + { + $this->night = $night; + return $this; + } + + public function getDescription(): ?string + { + return $this->description; + } + + public function setDescription(?string $description): static + { + $this->description = $description; + return $this; + } + + public function getTotal(): int + { + return $this->baseSalary + $this->overtime + $this->shift + $this->night; + } +} \ No newline at end of file diff --git a/hesabixCore/src/Repository/PlugHrmDocItemRepository.php b/hesabixCore/src/Repository/PlugHrmDocItemRepository.php new file mode 100644 index 0000000..75f2370 --- /dev/null +++ b/hesabixCore/src/Repository/PlugHrmDocItemRepository.php @@ -0,0 +1,15 @@ + - - - - {{ $t('drawer.hrm_docs') }} - - - {{ $t('dialog.add_new') }} - - - - - - \ No newline at end of file + +onMounted(() => { + loadData() +}) + + + \ No newline at end of file diff --git a/webUI/src/views/acc/plugins/hrm/docs/mod.vue b/webUI/src/views/acc/plugins/hrm/docs/mod.vue index 948a60e..9a419bf 100644 --- a/webUI/src/views/acc/plugins/hrm/docs/mod.vue +++ b/webUI/src/views/acc/plugins/hrm/docs/mod.vue @@ -25,7 +25,7 @@ + :rules="[v => !!v || $t('dialog.hrm.required_fields.date')]" required density="compact" /> ({ + person: { + id: item.person.id, + name: item.person.name, + code: item.person.code + }, + description: item.description || '', + baseSalary: item.baseSalary || 0, + overtime: item.overtime || 0, + shift: item.shift || 0, + night: item.night || 0 + })) } catch (error) { - this.errorMessage = 'خطا در دریافت اطلاعات'; + this.errorMessage = error.response?.data?.error || 'خطا در دریافت اطلاعات'; this.showError = true; } }, @@ -193,16 +223,35 @@ export default { }, async save() { try { + console.log('Starting save process...'); this.loading = true; - const url = this.isEdit ? '/api/hrm/docs/update' : '/api/hrm/docs/insert' - await this.$axios.post(url, this.form) + const url = this.isEdit ? '/api/hrm/docs/update' : '/api/hrm/docs/insert'; + const data = { + date: this.form.date, + description: this.form.description, + items: this.tableItems.map(item => ({ + person: item.person?.id, + baseSalary: Number(item.baseSalary) || 0, + overtime: Number(item.overtime) || 0, + shift: Number(item.shift) || 0, + night: Number(item.night) || 0, + description: item.description || '' + })) + }; + console.log('Sending request to:', url); + console.log('Request data:', data); + + const response = await axios.post(url, data); + console.log('Server response:', response); + this.successMessage = this.isEdit ? this.$t('dialog.hrm.edit_success') : this.$t('dialog.hrm.save_success'); this.showSuccess = true; setTimeout(() => { - this.$router.push('/acc/hrm/docs/list') - }, 1200) + this.$router.push('/acc/hrm/docs/list'); + }, 1200); } catch (error) { - this.errorMessage = this.$t('dialog.hrm.save_error'); + console.error('Save error:', error); + this.errorMessage = error.response?.data?.error || this.$t('dialog.hrm.save_error'); this.showError = true; } finally { this.loading = false; @@ -211,7 +260,7 @@ export default { async confirmDelete() { try { this.loading = true; - await this.$axios.post('/api/hrm/docs/delete', { id: this.$route.params.id }) + await axios.post('/api/hrm/docs/delete', { id: this.$route.params.id }) this.successMessage = 'سند با موفقیت حذف شد'; this.showSuccess = true; setTimeout(() => { @@ -318,6 +367,14 @@ export default { z-index: 9999 !important; } +:deep(.v-date-picker__menu) { + z-index: 9999 !important; +} + +:deep(.v-date-picker__menu__content) { + z-index: 9999 !important; +} + .settings-section-card { height: 100%; transition: all 0.3s ease;