start working on payment ID
This commit is contained in:
parent
b7ecafb3a7
commit
c8c2bb11d0
35
hesabixCore/migrations/Version20250824071413.php
Normal file
35
hesabixCore/migrations/Version20250824071413.php
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20250824071413 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->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);
|
||||
}
|
||||
}
|
|
@ -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'] != '') {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -59,6 +59,10 @@
|
|||
<span class="info-label">استان:</span>
|
||||
<span class="info-value">{{ person.ostan }}</span>
|
||||
</div>
|
||||
<div class="info-item" v-if="person.paymentId">
|
||||
<span class="info-label">شناسه پرداخت:</span>
|
||||
<span class="info-value">{{ person.paymentId }}</span>
|
||||
</div>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
|
|
|
@ -56,6 +56,12 @@
|
|||
{{ formatBalance(item.balance) }}
|
||||
</v-chip>
|
||||
</div>
|
||||
<div class="d-flex align-center justify-space-between mt-1" v-if="item.paymentId">
|
||||
<div class="d-flex align-center">
|
||||
<v-icon size="small" color="secondary" class="mr-1">mdi-credit-card-outline</v-icon>
|
||||
<span class="text-caption text-secondary-dark">شناسه پرداخت: {{ item.paymentId }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</v-list-item>
|
||||
</template>
|
||||
|
@ -156,6 +162,12 @@
|
|||
label="توضیحات"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="12" md="6">
|
||||
<v-text-field
|
||||
v-model="newPerson.paymentId"
|
||||
label="شناسه پرداخت"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="12">
|
||||
<v-switch
|
||||
v-model="newPerson.speedAccess"
|
||||
|
@ -409,7 +421,8 @@ export default {
|
|||
code: 0,
|
||||
types: [],
|
||||
accounts: [],
|
||||
speedAccess: false
|
||||
speedAccess: false,
|
||||
paymentId: ''
|
||||
}
|
||||
};
|
||||
},
|
||||
|
@ -600,13 +613,19 @@ export default {
|
|||
this.fetchData();
|
||||
} else if (response.data.result === 2) {
|
||||
this.showMessage('این شخص قبلاً ثبت شده است', 'error');
|
||||
} else if (response.data.result === -4) {
|
||||
this.showMessage(response.data.error || 'شناسه پرداخت تکراری است', 'error');
|
||||
}
|
||||
} else {
|
||||
this.showMessage('خطا در ثبت شخص', 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('خطا در ثبت شخص:', error);
|
||||
this.showMessage('خطا در ثبت شخص', 'error');
|
||||
if (error.response && error.response.data && error.response.data.result === -4) {
|
||||
this.showMessage(error.response.data.error || 'شناسه پرداخت تکراری است', 'error');
|
||||
} else {
|
||||
this.showMessage('خطا در ثبت شخص', 'error');
|
||||
}
|
||||
} finally {
|
||||
this.saving = false;
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ export default defineComponent({
|
|||
code: 0,
|
||||
types: [],
|
||||
accounts: [],
|
||||
paymentId: '',
|
||||
},
|
||||
personPattern: {
|
||||
nikename: '',
|
||||
|
@ -74,6 +75,13 @@ export default defineComponent({
|
|||
code: 0,
|
||||
types: [],
|
||||
accounts: [],
|
||||
paymentId: '',
|
||||
},
|
||||
snackbar: {
|
||||
show: false,
|
||||
text: '',
|
||||
color: 'success',
|
||||
timeout: 3000
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -81,6 +89,12 @@ export default defineComponent({
|
|||
this.loadData();
|
||||
},
|
||||
methods: {
|
||||
showSnackbar(text, color = 'success', timeout = 3000) {
|
||||
this.snackbar.show = true;
|
||||
this.snackbar.text = text;
|
||||
this.snackbar.color = color;
|
||||
this.snackbar.timeout = timeout;
|
||||
},
|
||||
addNewcard() {
|
||||
this.person.accounts.push({
|
||||
cardNum: '',
|
||||
|
@ -105,29 +119,17 @@ export default defineComponent({
|
|||
const regex = new RegExp("^(\\+98|0)?9\\d{9}$");
|
||||
if (!regex.test(this.person.mobile)) {
|
||||
canSubmit = false;
|
||||
Swal.fire({
|
||||
text: 'شماره موبایل وارد شده نامعتبر است.',
|
||||
icon: 'error',
|
||||
confirmButtonText: 'قبول'
|
||||
});
|
||||
this.showSnackbar('شماره موبایل وارد شده نامعتبر است.', 'error');
|
||||
}
|
||||
}
|
||||
if (this.person.nikename.length === 0) {
|
||||
canSubmit = false;
|
||||
Swal.fire({
|
||||
text: 'نام مستعار الزامی است.',
|
||||
icon: 'error',
|
||||
confirmButtonText: 'قبول'
|
||||
});
|
||||
this.showSnackbar('نام مستعار الزامی است.', 'error');
|
||||
}
|
||||
this.person.accounts.forEach((item) => {
|
||||
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({
|
|||
<label class="form-label">توضیحات</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<div class="form-floating mb-4">
|
||||
<input v-model="person.paymentId" class="form-control" type="text">
|
||||
<label class="form-label">شناسه پرداخت</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
|
@ -445,6 +454,16 @@ export default defineComponent({
|
|||
</v-row>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
|
||||
<!-- Snackbar برای نمایش پیامها -->
|
||||
<v-snackbar v-model="snackbar.show" :color="snackbar.color" :timeout="snackbar.timeout">
|
||||
{{ snackbar.text }}
|
||||
<template v-slot:actions>
|
||||
<v-btn color="white" text @click="snackbar.show = false">
|
||||
بستن
|
||||
</v-btn>
|
||||
</template>
|
||||
</v-snackbar>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
|
@ -151,6 +151,13 @@
|
|||
dense
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="12" md="6">
|
||||
<v-text-field
|
||||
v-model="editPersonData.paymentId"
|
||||
label="شناسه پرداخت"
|
||||
dense
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="12">
|
||||
|
||||
</v-col>
|
||||
|
@ -229,6 +236,8 @@
|
|||
selectedPerson.address || '-' }}</span></div>
|
||||
<div class="text-subtitle-2">{{ $t('pages.person.description') }}: <span class="text-primary">{{
|
||||
selectedPerson.des || '-' }}</span></div>
|
||||
<div class="text-subtitle-2">شناسه پرداخت: <span class="text-primary">{{
|
||||
selectedPerson.paymentId || '-' }}</span></div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -65,6 +65,10 @@
|
|||
<v-text-field v-model="person.des" :label="$t('pages.person.description')" dense
|
||||
prepend-inner-icon="mdi-text" hide-details />
|
||||
</v-col>
|
||||
<v-col cols="12" md="6">
|
||||
<v-text-field v-model="person.paymentId" label="شناسه پرداخت" dense
|
||||
prepend-inner-icon="mdi-credit-card-outline" hide-details />
|
||||
</v-col>
|
||||
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
|
@ -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')
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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' },
|
||||
]);
|
||||
|
||||
// توابع کمکی
|
||||
|
|
Loading…
Reference in a new issue