From c8c2bb11d07a401a7cb040c7f1bc82930ab9da93 Mon Sep 17 00:00:00 2001 From: Babak Alizadeh Date: Sun, 24 Aug 2025 07:37:10 +0000 Subject: [PATCH] start working on payment ID --- .../migrations/Version20250824071413.php | 35 +++++++++ hesabixCore/src/Cog/PersonService.php | 18 ++++- .../src/Controller/PersonsController.php | 6 +- hesabixCore/src/Entity/Person.php | 13 ++++ .../src/Repository/PersonRepository.php | 2 +- hesabixCore/src/Service/Explore.php | 1 + webUI/src/components/PersonInfo.vue | 4 + webUI/src/components/forms/Hpersonsearch.vue | 23 +++++- .../views/acc/component/person/quickAdd.vue | 75 ++++++++++++------- webUI/src/views/acc/persons/card.vue | 21 +++++- webUI/src/views/acc/persons/insert.vue | 29 +++++-- webUI/src/views/acc/persons/list.vue | 1 + 12 files changed, 186 insertions(+), 42 deletions(-) create mode 100644 hesabixCore/migrations/Version20250824071413.php diff --git a/hesabixCore/migrations/Version20250824071413.php b/hesabixCore/migrations/Version20250824071413.php new file mode 100644 index 0000000..5ba4e31 --- /dev/null +++ b/hesabixCore/migrations/Version20250824071413.php @@ -0,0 +1,35 @@ +addSql(<<<'SQL' + ALTER TABLE person ADD payment_id VARCHAR(255) DEFAULT NULL + SQL); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql(<<<'SQL' + ALTER TABLE person DROP payment_id + SQL); + } +} diff --git a/hesabixCore/src/Cog/PersonService.php b/hesabixCore/src/Cog/PersonService.php index 1137a6d..7d3400a 100644 --- a/hesabixCore/src/Cog/PersonService.php +++ b/hesabixCore/src/Cog/PersonService.php @@ -95,7 +95,7 @@ class PersonService if (!empty($search) || $search === '0') { $search = trim($search); - $queryBuilder->andWhere('p.nikename LIKE :search OR p.name LIKE :search OR p.code LIKE :search OR p.mobile LIKE :search') + $queryBuilder->andWhere('p.nikename LIKE :search OR p.name LIKE :search OR p.code LIKE :search OR p.mobile LIKE :search OR p.paymentId LIKE :search') ->setParameter('search', "%$search%"); } @@ -288,6 +288,22 @@ class PersonService if (isset($params['shenasemeli'])) $person->setShenasemeli($params['shenasemeli']); if (isset($params['company'])) $person->setCompany($params['company']); if (isset($params['tags'])) $person->setTags($params['tags']); + + // بررسی منحصر به فرد بودن شناسه پرداخت در کسب و کار + if (isset($params['paymentId']) && !empty(trim($params['paymentId']))) { + $existingPerson = $em->getRepository(\App\Entity\Person::class)->findOneBy([ + 'paymentId' => trim($params['paymentId']), + 'bid' => $acc['bid'] + ]); + + // اگر شخص دیگری با همین شناسه پرداخت وجود دارد و این شخص فعلی نیست + if ($existingPerson && $existingPerson->getId() !== $person->getId()) { + return ['result' => -4, 'error' => 'شناسه پرداخت تکراری است']; + } + $person->setPaymentId(trim($params['paymentId'])); + } else { + $person->setPaymentId(null); + } if (array_key_exists('prelabel', $params)) { if ($params['prelabel'] != '') { diff --git a/hesabixCore/src/Controller/PersonsController.php b/hesabixCore/src/Controller/PersonsController.php index 4102ef2..9753829 100644 --- a/hesabixCore/src/Controller/PersonsController.php +++ b/hesabixCore/src/Controller/PersonsController.php @@ -295,7 +295,8 @@ class PersonsController extends AbstractController 'id' => $person->getId(), 'nikename' => $person->getNikename(), 'code' => $person->getCode(), - 'mobile' => $person->getMobile() + 'mobile' => $person->getMobile(), + 'paymentId' => $person->getPaymentId() ]; $rows = $entityManager->getRepository(HesabdariRow::class)->findBy([ 'person' => $person, @@ -344,7 +345,8 @@ class PersonsController extends AbstractController 'id' => $person->getId(), 'nikename' => $person->getNikename(), 'code' => $person->getCode(), - 'mobile' => $person->getMobile() + 'mobile' => $person->getMobile(), + 'paymentId' => $person->getPaymentId() ]; $rows = $entityManager->getRepository(HesabdariRow::class)->findBy([ 'person' => $person, diff --git a/hesabixCore/src/Entity/Person.php b/hesabixCore/src/Entity/Person.php index 13e26f0..1fccfbd 100644 --- a/hesabixCore/src/Entity/Person.php +++ b/hesabixCore/src/Entity/Person.php @@ -161,6 +161,8 @@ class Person #[ORM\Column(type: Types::TEXT, nullable: true)] private ?string $tags = null; + #[ORM\Column(length: 255, nullable: true)] + private ?string $paymentId = null; public function __construct() @@ -916,5 +918,16 @@ class Person return $this; } + public function getPaymentId(): ?string + { + return $this->paymentId; + } + + public function setPaymentId(?string $paymentId): self + { + $this->paymentId = $paymentId; + return $this; + } + } diff --git a/hesabixCore/src/Repository/PersonRepository.php b/hesabixCore/src/Repository/PersonRepository.php index 246dd9b..76d32a3 100644 --- a/hesabixCore/src/Repository/PersonRepository.php +++ b/hesabixCore/src/Repository/PersonRepository.php @@ -47,7 +47,7 @@ class PersonRepository extends ServiceEntityRepository { return $this->createQueryBuilder('p') ->where('p.bid = :val') - ->andWhere("p.nikename LIKE :search OR p.mobile LIKE :search") + ->andWhere("p.nikename LIKE :search OR p.mobile LIKE :search OR p.paymentId LIKE :search") ->setParameter('val', $bid) ->setParameter('search', '%' . $search . '%') ->setMaxResults($maxResults) diff --git a/hesabixCore/src/Service/Explore.php b/hesabixCore/src/Service/Explore.php index 964c452..44fea77 100644 --- a/hesabixCore/src/Service/Explore.php +++ b/hesabixCore/src/Service/Explore.php @@ -354,6 +354,7 @@ class Explore 'address' => $person->getAddress(), 'prelabel' => null, 'tags' => $person->getTags(), + 'paymentId' => $person->getPaymentId(), 'requireTwoStep' => $person->getBid() ? $person->getBid()->isRequireTwoStepApproval() : false, ]; if ($person->getPrelabel()) { diff --git a/webUI/src/components/PersonInfo.vue b/webUI/src/components/PersonInfo.vue index ce73dd2..3d6e93c 100644 --- a/webUI/src/components/PersonInfo.vue +++ b/webUI/src/components/PersonInfo.vue @@ -59,6 +59,10 @@ استان: {{ person.ostan }} +
+ شناسه پرداخت: + {{ person.paymentId }} +
diff --git a/webUI/src/components/forms/Hpersonsearch.vue b/webUI/src/components/forms/Hpersonsearch.vue index 174c5e2..8f35b23 100755 --- a/webUI/src/components/forms/Hpersonsearch.vue +++ b/webUI/src/components/forms/Hpersonsearch.vue @@ -56,6 +56,12 @@ {{ formatBalance(item.balance) }} +
+
+ mdi-credit-card-outline + شناسه پرداخت: {{ item.paymentId }} +
+
@@ -156,6 +162,12 @@ label="توضیحات" > + + + { if (item.bank == '') { canSubmit = false; - Swal.fire({ - text: 'بخش حساب‌های بانکی به درستی تکمیل نشده است.لطفا موارد الزامی را وارد کنید.', - icon: 'error', - confirmButtonText: 'قبول' - }); + this.showSnackbar('بخش حساب‌های بانکی به درستی تکمیل نشده است.لطفا موارد الزامی را وارد کنید.', 'error'); } }); if (canSubmit) { @@ -135,21 +137,22 @@ export default defineComponent({ axios.post('/api/person/mod/' + this.person.code, this.person).then((response) => { this.loading = false; if (response.data.result == 2) { - Swal.fire({ - text: 'قبلا ثبت شده است.', - icon: 'error', - confirmButtonText: 'قبول' - }); + this.showSnackbar('قبلا ثبت شده است.', 'error'); + } + else if (response.data.result == -4) { + this.showSnackbar(response.data.error || 'شناسه پرداخت تکراری است.', 'error'); } else { - Swal.fire({ - text: 'مشخصات شخص ثبت شد.', - icon: 'success', - confirmButtonText: 'قبول' - }).then(() => { - this.person = this.personPattern - this.dialog = false; - }); + this.showSnackbar('مشخصات شخص ثبت شد.', 'success'); + this.person = this.personPattern; + this.dialog = false; + } + }).catch((error) => { + this.loading = false; + if (error.response && error.response.data && error.response.data.result === -4) { + this.showSnackbar(error.response.data.error || 'شناسه پرداخت تکراری است.', 'error'); + } else { + this.showSnackbar('خطا در ثبت شخص.', 'error'); } }) } @@ -256,6 +259,12 @@ export default defineComponent({ +
+
+ + +
+
@@ -445,6 +454,16 @@ export default defineComponent({ + + + + {{ snackbar.text }} + + \ No newline at end of file diff --git a/webUI/src/views/acc/persons/card.vue b/webUI/src/views/acc/persons/card.vue index 8518352..c684892 100755 --- a/webUI/src/views/acc/persons/card.vue +++ b/webUI/src/views/acc/persons/card.vue @@ -151,6 +151,13 @@ dense />
+ + + @@ -229,6 +236,8 @@ selectedPerson.address || '-' }}
{{ $t('pages.person.description') }}: {{ selectedPerson.des || '-' }}
+
شناسه پرداخت: {{ + selectedPerson.paymentId || '-' }}
@@ -352,7 +361,7 @@ export default { tel: '', address: '', des: '', - + paymentId: '', }, debounceTimeout: null, // برای مدیریت debounce headers: [ @@ -437,7 +446,7 @@ export default { tel: this.selectedPerson.tel || '', address: this.selectedPerson.address || '', des: this.selectedPerson.des || '', - + paymentId: this.selectedPerson.paymentId || '', }; const rowsResponse = await axios.post('/api/accounting/rows/search', { type: 'person', id }); @@ -463,12 +472,18 @@ export default { this.editPersonDialog = false; // بروزرسانی اطلاعات شخص await this.loadPerson(this.selectedPerson.code); + } else if (response.data.result === -4) { + this.snackbar = { show: true, text: response.data.error || 'شناسه پرداخت تکراری است', color: 'error' }; } else { this.snackbar = { show: true, text: 'خطا در بروزرسانی اطلاعات شخص', color: 'error' }; } } catch (error) { console.error('Save person error:', error); - this.snackbar = { show: true, text: 'خطا در بروزرسانی اطلاعات شخص', color: 'error' }; + if (error.response && error.response.data && error.response.data.result === -4) { + this.snackbar = { show: true, text: error.response.data.error || 'شناسه پرداخت تکراری است', color: 'error' }; + } else { + this.snackbar = { show: true, text: 'خطا در بروزرسانی اطلاعات شخص', color: 'error' }; + } } finally { this.saveLoading = false; } diff --git a/webUI/src/views/acc/persons/insert.vue b/webUI/src/views/acc/persons/insert.vue index f3dbdbb..5d6274d 100755 --- a/webUI/src/views/acc/persons/insert.vue +++ b/webUI/src/views/acc/persons/insert.vue @@ -65,6 +65,10 @@ + + + @@ -289,6 +293,7 @@ export default { accounts: [], prelabel: ref(null), speedAccess: false, + paymentId: '', }, snackbar: { @@ -418,6 +423,12 @@ export default { icon: 'error', confirmButtonText: this.$t('dialog.confirm') }); + } else if (response.data && response.data.result === -4) { + Swal.fire({ + text: response.data.error || 'شناسه پرداخت تکراری است', + icon: 'error', + confirmButtonText: this.$t('dialog.confirm') + }); } else { Swal.fire({ text: this.$t('pages.person.saved'), @@ -429,11 +440,19 @@ export default { } } catch (error) { this.loading = false; - Swal.fire({ - text: this.$t('pages.person.save_error') + error.message, - icon: 'error', - confirmButtonText: this.$t('dialog.confirm') - }); + if (error.response && error.response.data && error.response.data.result === -4) { + Swal.fire({ + text: error.response.data.error || 'شناسه پرداخت تکراری است', + icon: 'error', + confirmButtonText: this.$t('dialog.confirm') + }); + } else { + Swal.fire({ + text: this.$t('pages.person.save_error') + error.message, + icon: 'error', + confirmButtonText: this.$t('dialog.confirm') + }); + } } } }, diff --git a/webUI/src/views/acc/persons/list.vue b/webUI/src/views/acc/persons/list.vue index c8fb4e0..50c7dc7 100755 --- a/webUI/src/views/acc/persons/list.vue +++ b/webUI/src/views/acc/persons/list.vue @@ -255,6 +255,7 @@ const allHeaders = ref([ { title: 'ایمیل', value: 'email', sortable: true, visible: true, align: 'center' }, { title: 'وب سایت', value: 'website', sortable: true, visible: true, align: 'center' }, { title: 'فکس', value: 'fax', sortable: true, visible: true, align: 'center' }, + { title: 'شناسه پرداخت', value: 'paymentId', sortable: true, visible: true, align: 'center' }, ]); // توابع کمکی