progress in sustome controls
This commit is contained in:
parent
2d0305f918
commit
2fb2449207
|
@ -12,6 +12,13 @@ use Symfony\Component\Routing\Annotation\Route;
|
||||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||||
use App\Service\Provider;
|
use App\Service\Provider;
|
||||||
use App\Entity\HesabdariDoc;
|
use App\Entity\HesabdariDoc;
|
||||||
|
use App\Entity\HesabdariRow;
|
||||||
|
use App\Entity\HesabdariTable;
|
||||||
|
use App\Entity\BankAccount;
|
||||||
|
use App\Entity\Cashdesk;
|
||||||
|
use App\Entity\Salary;
|
||||||
|
use App\Entity\Person;
|
||||||
|
use App\Service\Log;
|
||||||
|
|
||||||
class CostController extends AbstractController
|
class CostController extends AbstractController
|
||||||
{
|
{
|
||||||
|
@ -467,8 +474,6 @@ class CostController extends AbstractController
|
||||||
$paymentCenter = $row->getCashdesk()->getName();
|
$paymentCenter = $row->getCashdesk()->getName();
|
||||||
} elseif ($row->getSalary()) {
|
} elseif ($row->getSalary()) {
|
||||||
$paymentCenter = $row->getSalary()->getName();
|
$paymentCenter = $row->getSalary()->getName();
|
||||||
} elseif ($row->getCommodity()) {
|
|
||||||
$paymentCenter = $row->getCommodity()->getName();
|
|
||||||
} elseif ($row->getPerson()) {
|
} elseif ($row->getPerson()) {
|
||||||
$paymentCenter = $row->getPerson()->getNikename();
|
$paymentCenter = $row->getPerson()->getNikename();
|
||||||
}
|
}
|
||||||
|
@ -492,4 +497,138 @@ class CostController extends AbstractController
|
||||||
|
|
||||||
return new BinaryFileResponse($filePath);
|
return new BinaryFileResponse($filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[Route('/api/cost/doc/insert', name: 'app_cost_doc_insert', methods: ['POST'])]
|
||||||
|
public function insertCostDoc(
|
||||||
|
Request $request,
|
||||||
|
Access $access,
|
||||||
|
EntityManagerInterface $entityManager,
|
||||||
|
Provider $provider,
|
||||||
|
Log $log,
|
||||||
|
Jdate $jdate
|
||||||
|
): JsonResponse {
|
||||||
|
$acc = $access->hasRole('cost');
|
||||||
|
if (!$acc) {
|
||||||
|
throw $this->createAccessDeniedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
$params = json_decode($request->getContent(), true) ?? [];
|
||||||
|
|
||||||
|
// بررسی پارامترهای ضروری
|
||||||
|
if (!isset($params['rows']) || count($params['rows']) < 2) {
|
||||||
|
return $this->json(['result' => 0, 'message' => 'حداقل دو ردیف برای سند هزینه الزامی است'], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($params['date']) || !isset($params['des'])) {
|
||||||
|
return $this->json(['result' => 0, 'message' => 'تاریخ و شرح سند الزامی است'], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
// تنظیم نوع سند به cost
|
||||||
|
$params['type'] = 'cost';
|
||||||
|
|
||||||
|
// بررسی وجود سند برای ویرایش
|
||||||
|
if (isset($params['update']) && $params['update'] != '') {
|
||||||
|
$doc = $entityManager->getRepository(HesabdariDoc::class)->findOneBy([
|
||||||
|
'bid' => $acc['bid'],
|
||||||
|
'year' => $acc['year'],
|
||||||
|
'code' => $params['update'],
|
||||||
|
'money' => $acc['money']
|
||||||
|
]);
|
||||||
|
if (!$doc) {
|
||||||
|
return $this->json(['result' => 0, 'message' => 'سند مورد نظر یافت نشد'], 404);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ایجاد سند جدید
|
||||||
|
$doc = new HesabdariDoc();
|
||||||
|
$doc->setBid($acc['bid']);
|
||||||
|
$doc->setYear($acc['year']);
|
||||||
|
$doc->setDes($params['des']);
|
||||||
|
$doc->setDateSubmit(time());
|
||||||
|
$doc->setType('cost');
|
||||||
|
$doc->setDate($params['date']);
|
||||||
|
$doc->setSubmitter($this->getUser());
|
||||||
|
$doc->setMoney($acc['money']);
|
||||||
|
$doc->setCode($provider->getAccountingCode($acc['bid'], 'accounting'));
|
||||||
|
|
||||||
|
$entityManager->persist($doc);
|
||||||
|
$entityManager->flush();
|
||||||
|
|
||||||
|
// پردازش ردیفهای سند
|
||||||
|
$amount = 0;
|
||||||
|
foreach ($params['rows'] as $row) {
|
||||||
|
$row['bs'] = str_replace(',', '', $row['bs']);
|
||||||
|
$row['bd'] = str_replace(',', '', $row['bd']);
|
||||||
|
|
||||||
|
$hesabdariRow = new HesabdariRow();
|
||||||
|
$hesabdariRow->setBid($acc['bid']);
|
||||||
|
$hesabdariRow->setYear($acc['year']);
|
||||||
|
$hesabdariRow->setDoc($doc);
|
||||||
|
$hesabdariRow->setBs($row['bs']);
|
||||||
|
$hesabdariRow->setBd($row['bd']);
|
||||||
|
|
||||||
|
// تنظیم مرکز هزینه
|
||||||
|
$ref = $entityManager->getRepository(HesabdariTable::class)->findOneBy([
|
||||||
|
'code' => $row['table']
|
||||||
|
]);
|
||||||
|
$hesabdariRow->setRef($ref);
|
||||||
|
|
||||||
|
// تنظیم مرکز پرداخت (بانک، صندوق، تنخواه، شخص)
|
||||||
|
if ($row['type'] == 'bank') {
|
||||||
|
$bank = $entityManager->getRepository(BankAccount::class)->findOneBy([
|
||||||
|
'id' => $row['id'],
|
||||||
|
'bid' => $acc['bid']
|
||||||
|
]);
|
||||||
|
if (!$bank) {
|
||||||
|
return $this->json(['result' => 0, 'message' => 'حساب بانکی مورد نظر یافت نشد'], 404);
|
||||||
|
}
|
||||||
|
$hesabdariRow->setBank($bank);
|
||||||
|
} elseif ($row['type'] == 'cashdesk') {
|
||||||
|
$cashdesk = $entityManager->getRepository(Cashdesk::class)->find($row['id']);
|
||||||
|
if (!$cashdesk) {
|
||||||
|
return $this->json(['result' => 0, 'message' => 'صندوق مورد نظر یافت نشد'], 404);
|
||||||
|
}
|
||||||
|
$hesabdariRow->setCashdesk($cashdesk);
|
||||||
|
} elseif ($row['type'] == 'salary') {
|
||||||
|
$salary = $entityManager->getRepository(Salary::class)->find($row['id']);
|
||||||
|
if (!$salary) {
|
||||||
|
return $this->json(['result' => 0, 'message' => 'تنخواه مورد نظر یافت نشد'], 404);
|
||||||
|
}
|
||||||
|
$hesabdariRow->setSalary($salary);
|
||||||
|
} elseif ($row['type'] == 'person') {
|
||||||
|
$person = $entityManager->getRepository(Person::class)->findOneBy([
|
||||||
|
'id' => $row['id'],
|
||||||
|
'bid' => $acc['bid']
|
||||||
|
]);
|
||||||
|
if (!$person) {
|
||||||
|
return $this->json(['result' => 0, 'message' => 'شخص مورد نظر یافت نشد'], 404);
|
||||||
|
}
|
||||||
|
$hesabdariRow->setPerson($person);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($row['des'])) {
|
||||||
|
$hesabdariRow->setDes($row['des']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$entityManager->persist($hesabdariRow);
|
||||||
|
$amount += $row['bs'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$doc->setAmount($amount);
|
||||||
|
$entityManager->persist($doc);
|
||||||
|
$entityManager->flush();
|
||||||
|
|
||||||
|
$log->insert(
|
||||||
|
'حسابداری',
|
||||||
|
'سند هزینه شماره ' . $doc->getCode() . ' ثبت شد.',
|
||||||
|
$this->getUser(),
|
||||||
|
$acc['bid'],
|
||||||
|
$doc
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->json([
|
||||||
|
'result' => 1,
|
||||||
|
'doc' => $provider->Entity2Array($doc, 0)
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -426,11 +426,12 @@ class HesabdariController extends AbstractController
|
||||||
$entityManager->flush();
|
$entityManager->flush();
|
||||||
$hesabdariRow->setCheque($cheque);
|
$hesabdariRow->setCheque($cheque);
|
||||||
} elseif ($row['type'] == 'bank') {
|
} elseif ($row['type'] == 'bank') {
|
||||||
$bank = $entityManager->getRepository(BankAccount::class)->find($row['id']);
|
$bank = $entityManager->getRepository(BankAccount::class)->findOneBy([
|
||||||
|
'id' => $row['id'],
|
||||||
|
'bid' => $acc['bid']
|
||||||
|
]);
|
||||||
if (!$bank)
|
if (!$bank)
|
||||||
throw $this->createNotFoundException('bank not found');
|
throw $this->createNotFoundException('bank not found');
|
||||||
elseif ($bank->getBid()->getId() != $acc['bid']->getId())
|
|
||||||
throw $this->createAccessDeniedException('bank is not in this business');
|
|
||||||
$hesabdariRow->setBank($bank);
|
$hesabdariRow->setBank($bank);
|
||||||
} elseif ($row['type'] == 'salary') {
|
} elseif ($row['type'] == 'salary') {
|
||||||
$salary = $entityManager->getRepository(Salary::class)->find($row['id']);
|
$salary = $entityManager->getRepository(Salary::class)->find($row['id']);
|
||||||
|
|
667
webUI/src/components/forms/Hpersonsearch.vue
Normal file
667
webUI/src/components/forms/Hpersonsearch.vue
Normal file
|
@ -0,0 +1,667 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<v-menu v-model="menu" :close-on-content-click="false">
|
||||||
|
<template v-slot:activator="{ props }">
|
||||||
|
<v-text-field
|
||||||
|
v-bind="props"
|
||||||
|
v-model="displayValue"
|
||||||
|
variant="outlined"
|
||||||
|
hide-details
|
||||||
|
density="compact"
|
||||||
|
:label="label"
|
||||||
|
class=""
|
||||||
|
prepend-inner-icon="mdi-account"
|
||||||
|
clearable
|
||||||
|
@click:clear="clearSelection"
|
||||||
|
:loading="loading"
|
||||||
|
@keydown.enter="handleEnter"
|
||||||
|
>
|
||||||
|
<template v-slot:append-inner>
|
||||||
|
<v-icon>{{ menu ? 'mdi-chevron-up' : 'mdi-chevron-down' }}</v-icon>
|
||||||
|
</template>
|
||||||
|
</v-text-field>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<v-card min-width="300" max-width="400">
|
||||||
|
<v-card-text class="pa-2">
|
||||||
|
<template v-if="!loading">
|
||||||
|
<v-list density="compact" class="list-container">
|
||||||
|
<template v-if="filteredItems.length > 0">
|
||||||
|
<v-list-item
|
||||||
|
v-for="item in filteredItems"
|
||||||
|
:key="item.id"
|
||||||
|
@click="selectItem(item)"
|
||||||
|
class="mb-1"
|
||||||
|
>
|
||||||
|
<v-list-item-title class="text-right">{{ item.nikename }}</v-list-item-title>
|
||||||
|
<v-list-item-subtitle class="text-right">{{ item.code }}</v-list-item-subtitle>
|
||||||
|
</v-list-item>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<v-list-item>
|
||||||
|
<v-list-item-title class="text-center text-grey">
|
||||||
|
نتیجهای یافت نشد
|
||||||
|
</v-list-item-title>
|
||||||
|
</v-list-item>
|
||||||
|
</template>
|
||||||
|
</v-list>
|
||||||
|
<v-btn
|
||||||
|
v-if="filteredItems.length === 0"
|
||||||
|
block
|
||||||
|
color="primary"
|
||||||
|
class="mt-2"
|
||||||
|
@click="showAddDialog = true"
|
||||||
|
>
|
||||||
|
افزودن کاربر جدید
|
||||||
|
</v-btn>
|
||||||
|
</template>
|
||||||
|
<v-progress-circular
|
||||||
|
v-else
|
||||||
|
indeterminate
|
||||||
|
color="primary"
|
||||||
|
class="d-flex mx-auto my-4"
|
||||||
|
></v-progress-circular>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</v-menu>
|
||||||
|
|
||||||
|
<v-dialog v-model="showAddDialog" :fullscreen="$vuetify.display.mobile" max-width="800">
|
||||||
|
<v-card>
|
||||||
|
<v-toolbar color="primary" density="compact" class="sticky-toolbar">
|
||||||
|
<v-toolbar-title>افزودن کاربر جدید</v-toolbar-title>
|
||||||
|
<v-spacer></v-spacer>
|
||||||
|
<v-tooltip text="بستن">
|
||||||
|
<template v-slot:activator="{ props }">
|
||||||
|
<v-btn
|
||||||
|
icon="mdi-close"
|
||||||
|
v-bind="props"
|
||||||
|
@click="showAddDialog = false"
|
||||||
|
></v-btn>
|
||||||
|
</template>
|
||||||
|
</v-tooltip>
|
||||||
|
<v-tooltip text="ذخیره">
|
||||||
|
<template v-slot:activator="{ props }">
|
||||||
|
<v-btn
|
||||||
|
icon="mdi-content-save"
|
||||||
|
v-bind="props"
|
||||||
|
@click="savePerson"
|
||||||
|
:loading="saving"
|
||||||
|
></v-btn>
|
||||||
|
</template>
|
||||||
|
</v-tooltip>
|
||||||
|
</v-toolbar>
|
||||||
|
|
||||||
|
<v-tabs
|
||||||
|
v-model="tabs"
|
||||||
|
color="primary"
|
||||||
|
show-arrows
|
||||||
|
class="sticky-tabs"
|
||||||
|
>
|
||||||
|
<v-tab value="basic" class="flex-grow-1">اطلاعات پایه</v-tab>
|
||||||
|
<v-tab value="contact" class="flex-grow-1">اطلاعات تماس</v-tab>
|
||||||
|
<v-tab value="address" class="flex-grow-1">آدرس</v-tab>
|
||||||
|
<v-tab value="bank" class="flex-grow-1">حسابهای بانکی</v-tab>
|
||||||
|
</v-tabs>
|
||||||
|
|
||||||
|
<v-card-text class="content-container">
|
||||||
|
<v-window v-model="tabs">
|
||||||
|
<v-window-item value="basic">
|
||||||
|
<v-form @submit.prevent="savePerson">
|
||||||
|
<v-row class="mt-4">
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="newPerson.nikename"
|
||||||
|
label="نام مستعار *"
|
||||||
|
required
|
||||||
|
:error-messages="nikenameErrors"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="newPerson.name"
|
||||||
|
label="نام و نام خانوادگی"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="newPerson.company"
|
||||||
|
label="شرکت"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="newPerson.des"
|
||||||
|
label="توضیحات"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12">
|
||||||
|
<v-switch
|
||||||
|
v-model="newPerson.speedAccess"
|
||||||
|
label="دسترسی سریع"
|
||||||
|
color="primary"
|
||||||
|
></v-switch>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12">
|
||||||
|
<v-card variant="outlined" class="pa-2">
|
||||||
|
<v-card-title class="text-subtitle-1">نوع مشتری</v-card-title>
|
||||||
|
<v-card-text class="pa-0">
|
||||||
|
<v-row dense>
|
||||||
|
<v-col v-for="(type, index) in personTypes" :key="type.code" cols="12" sm="6" md="4">
|
||||||
|
<v-checkbox
|
||||||
|
v-model="newPerson.types[index].checked"
|
||||||
|
:label="type.label"
|
||||||
|
color="primary"
|
||||||
|
density="compact"
|
||||||
|
hide-details
|
||||||
|
></v-checkbox>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-form>
|
||||||
|
</v-window-item>
|
||||||
|
|
||||||
|
<v-window-item value="contact">
|
||||||
|
<v-row class="mt-4">
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="newPerson.mobile"
|
||||||
|
label="موبایل"
|
||||||
|
:error-messages="mobileErrors"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="newPerson.mobile2"
|
||||||
|
label="موبایل دوم"
|
||||||
|
:error-messages="mobile2Errors"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="newPerson.tel"
|
||||||
|
label="تلفن"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="newPerson.fax"
|
||||||
|
label="فکس"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="newPerson.email"
|
||||||
|
label="ایمیل"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="newPerson.website"
|
||||||
|
label="وب سایت"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-window-item>
|
||||||
|
|
||||||
|
<v-window-item value="address">
|
||||||
|
<v-row class="mt-4">
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="newPerson.keshvar"
|
||||||
|
label="کشور"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="newPerson.ostan"
|
||||||
|
label="استان"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="newPerson.shahr"
|
||||||
|
label="شهر"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="newPerson.postalcode"
|
||||||
|
label="کد پستی"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12">
|
||||||
|
<v-textarea
|
||||||
|
v-model="newPerson.address"
|
||||||
|
label="آدرس"
|
||||||
|
rows="3"
|
||||||
|
></v-textarea>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-window-item>
|
||||||
|
|
||||||
|
<v-window-item value="bank">
|
||||||
|
<v-row class="mt-4">
|
||||||
|
<v-col cols="12">
|
||||||
|
<v-btn
|
||||||
|
color="primary"
|
||||||
|
@click="addNewBankAccount"
|
||||||
|
prepend-icon="mdi-plus"
|
||||||
|
>
|
||||||
|
افزودن حساب بانکی
|
||||||
|
</v-btn>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" v-for="(account, index) in newPerson.accounts" :key="index">
|
||||||
|
<v-card variant="outlined" class="mb-4">
|
||||||
|
<v-card-title class="d-flex justify-space-between align-center">
|
||||||
|
<span>حساب بانکی {{ index + 1 }}</span>
|
||||||
|
<v-btn
|
||||||
|
icon="mdi-delete"
|
||||||
|
variant="text"
|
||||||
|
color="error"
|
||||||
|
@click="removeBankAccount(index)"
|
||||||
|
></v-btn>
|
||||||
|
</v-card-title>
|
||||||
|
<v-card-text>
|
||||||
|
<v-row>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="account.bank"
|
||||||
|
label="نام بانک *"
|
||||||
|
required
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="account.accountNum"
|
||||||
|
label="شماره حساب"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="account.cardNum"
|
||||||
|
label="شماره کارت"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-text-field
|
||||||
|
v-model="account.shabaNum"
|
||||||
|
label="شماره شبا"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-window-item>
|
||||||
|
</v-window>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</v-dialog>
|
||||||
|
|
||||||
|
<v-snackbar
|
||||||
|
v-model="snackbar.show"
|
||||||
|
:color="snackbar.color"
|
||||||
|
:timeout="3000"
|
||||||
|
>
|
||||||
|
{{ snackbar.text }}
|
||||||
|
<template v-slot:actions>
|
||||||
|
<v-btn
|
||||||
|
color="white"
|
||||||
|
variant="text"
|
||||||
|
@click="snackbar.show = false"
|
||||||
|
>
|
||||||
|
بستن
|
||||||
|
</v-btn>
|
||||||
|
</template>
|
||||||
|
</v-snackbar>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Hpersonsearch',
|
||||||
|
props: {
|
||||||
|
modelValue: {
|
||||||
|
type: [Object, Number],
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
type: String,
|
||||||
|
default: 'شخص'
|
||||||
|
},
|
||||||
|
returnObject: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
selectedItem: null,
|
||||||
|
items: [],
|
||||||
|
loading: false,
|
||||||
|
menu: false,
|
||||||
|
searchQuery: '',
|
||||||
|
totalItems: 0,
|
||||||
|
currentPage: 1,
|
||||||
|
itemsPerPage: 10,
|
||||||
|
searchTimeout: null,
|
||||||
|
showAddDialog: false,
|
||||||
|
tabs: 'basic',
|
||||||
|
saving: false,
|
||||||
|
personTypes: [],
|
||||||
|
snackbar: {
|
||||||
|
show: false,
|
||||||
|
text: '',
|
||||||
|
color: 'success'
|
||||||
|
},
|
||||||
|
newPerson: {
|
||||||
|
nikename: '',
|
||||||
|
name: '',
|
||||||
|
des: '',
|
||||||
|
tel: '',
|
||||||
|
mobile: '',
|
||||||
|
mobile2: '',
|
||||||
|
address: '',
|
||||||
|
company: '',
|
||||||
|
shenasemeli: '',
|
||||||
|
codeeghtesadi: '',
|
||||||
|
sabt: '',
|
||||||
|
keshvar: '',
|
||||||
|
ostan: '',
|
||||||
|
shahr: '',
|
||||||
|
postalcode: '',
|
||||||
|
email: '',
|
||||||
|
website: '',
|
||||||
|
fax: '',
|
||||||
|
code: 0,
|
||||||
|
types: [],
|
||||||
|
accounts: [],
|
||||||
|
speedAccess: false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
filteredItems() {
|
||||||
|
return Array.isArray(this.items) ? this.items : [];
|
||||||
|
},
|
||||||
|
displayValue: {
|
||||||
|
get() {
|
||||||
|
if (this.menu) {
|
||||||
|
return this.searchQuery;
|
||||||
|
}
|
||||||
|
return this.selectedItem ? this.selectedItem.nikename : this.searchQuery;
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
this.searchQuery = value;
|
||||||
|
if (!value) {
|
||||||
|
this.clearSelection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
nikenameErrors() {
|
||||||
|
if (!this.newPerson.nikename) return ['نام مستعار الزامی است'];
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
mobileErrors() {
|
||||||
|
if (this.newPerson.mobile && !/^09\d{9}$/.test(this.newPerson.mobile)) {
|
||||||
|
return ['شماره موبایل باید با 09 شروع شود و 11 رقم باشد'];
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
mobile2Errors() {
|
||||||
|
if (this.newPerson.mobile2 && !/^09\d{9}$/.test(this.newPerson.mobile2)) {
|
||||||
|
return ['شماره موبایل دوم باید با 09 شروع شود و 11 رقم باشد'];
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
modelValue: {
|
||||||
|
handler(newVal) {
|
||||||
|
if (this.returnObject) {
|
||||||
|
this.selectedItem = newVal;
|
||||||
|
} else {
|
||||||
|
this.selectedItem = this.items.find(item => item.id === newVal);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
},
|
||||||
|
searchQuery: {
|
||||||
|
handler(newVal) {
|
||||||
|
this.currentPage = 1;
|
||||||
|
if (this.searchTimeout) {
|
||||||
|
clearTimeout(this.searchTimeout);
|
||||||
|
}
|
||||||
|
this.searchTimeout = setTimeout(() => {
|
||||||
|
this.fetchData();
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
showAddDialog: {
|
||||||
|
handler(newVal) {
|
||||||
|
if (newVal) {
|
||||||
|
this.newPerson.nikename = this.searchQuery;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'newPerson.mobile': {
|
||||||
|
handler(newVal) {
|
||||||
|
if (newVal && !newVal.startsWith('09')) {
|
||||||
|
this.newPerson.mobile = '09' + newVal.replace(/^09/, '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'newPerson.mobile2': {
|
||||||
|
handler(newVal) {
|
||||||
|
if (newVal && !newVal.startsWith('09')) {
|
||||||
|
this.newPerson.mobile2 = '09' + newVal.replace(/^09/, '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
showMessage(text, color = 'success') {
|
||||||
|
this.snackbar.text = text;
|
||||||
|
this.snackbar.color = color;
|
||||||
|
this.snackbar.show = true;
|
||||||
|
},
|
||||||
|
async fetchData() {
|
||||||
|
this.loading = true;
|
||||||
|
try {
|
||||||
|
const response = await axios.post('/api/person/list', {
|
||||||
|
page: this.currentPage,
|
||||||
|
itemsPerPage: this.itemsPerPage,
|
||||||
|
search: this.searchQuery,
|
||||||
|
types: null,
|
||||||
|
transactionFilters: null,
|
||||||
|
sortBy: null
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('پاسخ API:', response.data);
|
||||||
|
|
||||||
|
if (response.data && Array.isArray(response.data)) {
|
||||||
|
this.items = response.data;
|
||||||
|
this.totalItems = response.data.length;
|
||||||
|
} else if (response.data && response.data.items) {
|
||||||
|
this.items = response.data.items;
|
||||||
|
this.totalItems = response.data.total || response.data.items.length;
|
||||||
|
} else {
|
||||||
|
this.items = [];
|
||||||
|
this.totalItems = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('آیتمهای ذخیره شده:', this.items);
|
||||||
|
|
||||||
|
if (this.modelValue) {
|
||||||
|
if (this.returnObject) {
|
||||||
|
this.selectedItem = this.modelValue;
|
||||||
|
} else {
|
||||||
|
this.selectedItem = this.items.find(item => item.id === this.modelValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('خطا در دریافت دادهها:', error);
|
||||||
|
this.showMessage('خطا در بارگذاری دادهها', 'error');
|
||||||
|
this.items = [];
|
||||||
|
this.totalItems = 0;
|
||||||
|
} finally {
|
||||||
|
this.loading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async loadPersonTypes() {
|
||||||
|
try {
|
||||||
|
const response = await axios.post('/api/person/types/get');
|
||||||
|
this.personTypes = response.data;
|
||||||
|
this.newPerson.types = response.data.map(type => ({
|
||||||
|
...type,
|
||||||
|
checked: false
|
||||||
|
}));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('خطا در دریافت انواع شخص:', error);
|
||||||
|
this.showMessage('خطا در بارگذاری انواع شخص', 'error');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
addNewBankAccount() {
|
||||||
|
this.newPerson.accounts.push({
|
||||||
|
bank: '',
|
||||||
|
accountNum: '',
|
||||||
|
cardNum: '',
|
||||||
|
shabaNum: ''
|
||||||
|
});
|
||||||
|
},
|
||||||
|
removeBankAccount(index) {
|
||||||
|
this.newPerson.accounts.splice(index, 1);
|
||||||
|
},
|
||||||
|
async savePerson() {
|
||||||
|
if (!this.newPerson.nikename) {
|
||||||
|
this.showMessage('نام مستعار الزامی است', 'error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.newPerson.mobile && !/^09\d{9}$/.test(this.newPerson.mobile)) {
|
||||||
|
this.showMessage('شماره موبایل باید با 09 شروع شود و 11 رقم باشد', 'error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.newPerson.mobile2 && !/^09\d{9}$/.test(this.newPerson.mobile2)) {
|
||||||
|
this.showMessage('شماره موبایل دوم باید با 09 شروع شود و 11 رقم باشد', 'error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const account of this.newPerson.accounts) {
|
||||||
|
if (!account.bank) {
|
||||||
|
this.showMessage('نام بانک برای حسابهای بانکی الزامی است', 'error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.saving = true;
|
||||||
|
try {
|
||||||
|
const response = await axios.post('/api/person/mod/' + this.newPerson.code, this.newPerson);
|
||||||
|
if (response.data.Success) {
|
||||||
|
if (response.data.result === 1) {
|
||||||
|
this.showMessage('شخص با موفقیت ثبت شد');
|
||||||
|
this.showAddDialog = false;
|
||||||
|
this.fetchData();
|
||||||
|
} else if (response.data.result === 2) {
|
||||||
|
this.showMessage('این شخص قبلاً ثبت شده است', 'error');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.showMessage('خطا در ثبت شخص', 'error');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('خطا در ثبت شخص:', error);
|
||||||
|
this.showMessage('خطا در ثبت شخص', 'error');
|
||||||
|
} finally {
|
||||||
|
this.saving = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
selectItem(item) {
|
||||||
|
this.selectedItem = item;
|
||||||
|
this.searchQuery = item.nikename;
|
||||||
|
this.$emit('update:modelValue', this.returnObject ? item : item.id);
|
||||||
|
this.menu = false;
|
||||||
|
},
|
||||||
|
clearSelection() {
|
||||||
|
this.selectedItem = null;
|
||||||
|
this.searchQuery = '';
|
||||||
|
this.$emit('update:modelValue', null);
|
||||||
|
},
|
||||||
|
handleEnter() {
|
||||||
|
if (!this.loading && this.filteredItems.length === 0) {
|
||||||
|
this.showAddDialog = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.fetchData();
|
||||||
|
this.loadPersonTypes();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.list-container {
|
||||||
|
max-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-container {
|
||||||
|
max-height: 500px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sticky-toolbar {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sticky-tabs {
|
||||||
|
position: sticky;
|
||||||
|
top: 48px;
|
||||||
|
z-index: 1;
|
||||||
|
overflow-x: auto;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.v-menu__content) {
|
||||||
|
position: fixed !important;
|
||||||
|
z-index: 9999 !important;
|
||||||
|
transform-origin: center top !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.v-overlay__content) {
|
||||||
|
position: fixed !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.v-window-item[value="contact"] .v-text-field input) {
|
||||||
|
text-align: left !important;
|
||||||
|
direction: ltr !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.v-window-item[value="contact"] .v-text-field .v-field__input) {
|
||||||
|
text-align: left !important;
|
||||||
|
direction: ltr !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.v-window-item[value="contact"] .v-text-field .v-label) {
|
||||||
|
text-align: right !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.content-container {
|
||||||
|
max-height: calc(100vh - 120px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sticky-tabs {
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -137,6 +137,14 @@ export default {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get('/api/accounting/table/childs/cost');
|
const response = await axios.get('/api/accounting/table/childs/cost');
|
||||||
this.treeItems = response.data;
|
this.treeItems = response.data;
|
||||||
|
|
||||||
|
if (this.modelValue) {
|
||||||
|
if (this.returnObject) {
|
||||||
|
this.selectedItem = this.modelValue;
|
||||||
|
} else {
|
||||||
|
this.selectedItem = this.findItemById(this.treeItems, this.modelValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('خطا در دریافت دادهها:', error);
|
console.error('خطا در دریافت دادهها:', error);
|
||||||
this.$toast.error('خطا در بارگذاری دادهها');
|
this.$toast.error('خطا در بارگذاری دادهها');
|
||||||
|
|
|
@ -295,15 +295,7 @@
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col cols="12" md="4">
|
<v-col cols="12" md="4">
|
||||||
<v-autocomplete
|
<Hpersonsearch v-model="item.id" label="شخص" />
|
||||||
v-model="item.person"
|
|
||||||
:items="listPersons"
|
|
||||||
item-title="name"
|
|
||||||
item-value="id"
|
|
||||||
label="شخص"
|
|
||||||
variant="outlined"
|
|
||||||
density="compact"
|
|
||||||
></v-autocomplete>
|
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col cols="12" md="4">
|
<v-col cols="12" md="4">
|
||||||
<Hnumberinput
|
<Hnumberinput
|
||||||
|
@ -346,6 +338,7 @@ import archiveUpload from "../component/archive/archiveUpload.vue";
|
||||||
import Hdatepicker from "@/components/forms/Hdatepicker.vue";
|
import Hdatepicker from "@/components/forms/Hdatepicker.vue";
|
||||||
import Hnumberinput from "@/components/forms/Hnumberinput.vue";
|
import Hnumberinput from "@/components/forms/Hnumberinput.vue";
|
||||||
import Htabletreeselect from '@/components/forms/Htabletreeselect.vue'
|
import Htabletreeselect from '@/components/forms/Htabletreeselect.vue'
|
||||||
|
import Hpersonsearch from '@/components/forms/Hpersonsearch.vue'
|
||||||
// import the styles
|
// import the styles
|
||||||
import quickAdd from "../component/person/quickAdd.vue";
|
import quickAdd from "../component/person/quickAdd.vue";
|
||||||
export default {
|
export default {
|
||||||
|
@ -357,6 +350,7 @@ export default {
|
||||||
Hdatepicker,
|
Hdatepicker,
|
||||||
Hnumberinput,
|
Hnumberinput,
|
||||||
Htabletreeselect,
|
Htabletreeselect,
|
||||||
|
Hpersonsearch,
|
||||||
},
|
},
|
||||||
data: () => {
|
data: () => {
|
||||||
return {
|
return {
|
||||||
|
@ -486,7 +480,7 @@ export default {
|
||||||
},
|
},
|
||||||
addPerson() {
|
addPerson() {
|
||||||
this.persons.push({
|
this.persons.push({
|
||||||
person: '',
|
id: '',
|
||||||
amount: '',
|
amount: '',
|
||||||
des: ''
|
des: ''
|
||||||
})
|
})
|
||||||
|
@ -575,11 +569,6 @@ export default {
|
||||||
axios.post('/api/salary/list').then((response) => {
|
axios.post('/api/salary/list').then((response) => {
|
||||||
this.listSalarys = response.data;
|
this.listSalarys = response.data;
|
||||||
});
|
});
|
||||||
|
|
||||||
//get list of persons
|
|
||||||
axios.post('/api/person/list/search').then((response) => {
|
|
||||||
this.listPersons = response.data;
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
save() {
|
save() {
|
||||||
let haszero = false;
|
let haszero = false;
|
||||||
|
@ -618,7 +607,7 @@ export default {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.persons.forEach((item) => {
|
this.persons.forEach((item) => {
|
||||||
if (item.person == null || item.person == '') {
|
if (item.id == null || item.id == '') {
|
||||||
sideOK = false;
|
sideOK = false;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -697,7 +686,7 @@ export default {
|
||||||
this.persons.forEach((item) => {
|
this.persons.forEach((item) => {
|
||||||
if (item.des == '') item.des = 'هزینه'
|
if (item.des == '') item.des = 'هزینه'
|
||||||
rows.push({
|
rows.push({
|
||||||
id: item.person,
|
id: item.id,
|
||||||
bs: parseInt(item.amount),
|
bs: parseInt(item.amount),
|
||||||
bd: 0,
|
bd: 0,
|
||||||
des: item.des,
|
des: item.des,
|
||||||
|
|
Loading…
Reference in a new issue