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 App\Service\Provider;
|
||||
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
|
||||
{
|
||||
|
@ -467,8 +474,6 @@ class CostController extends AbstractController
|
|||
$paymentCenter = $row->getCashdesk()->getName();
|
||||
} elseif ($row->getSalary()) {
|
||||
$paymentCenter = $row->getSalary()->getName();
|
||||
} elseif ($row->getCommodity()) {
|
||||
$paymentCenter = $row->getCommodity()->getName();
|
||||
} elseif ($row->getPerson()) {
|
||||
$paymentCenter = $row->getPerson()->getNikename();
|
||||
}
|
||||
|
@ -492,4 +497,138 @@ class CostController extends AbstractController
|
|||
|
||||
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();
|
||||
$hesabdariRow->setCheque($cheque);
|
||||
} 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)
|
||||
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);
|
||||
} elseif ($row['type'] == 'salary') {
|
||||
$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 {
|
||||
const response = await axios.get('/api/accounting/table/childs/cost');
|
||||
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) {
|
||||
console.error('خطا در دریافت دادهها:', error);
|
||||
this.$toast.error('خطا در بارگذاری دادهها');
|
||||
|
|
|
@ -295,15 +295,7 @@
|
|||
<v-card-text>
|
||||
<v-row>
|
||||
<v-col cols="12" md="4">
|
||||
<v-autocomplete
|
||||
v-model="item.person"
|
||||
:items="listPersons"
|
||||
item-title="name"
|
||||
item-value="id"
|
||||
label="شخص"
|
||||
variant="outlined"
|
||||
density="compact"
|
||||
></v-autocomplete>
|
||||
<Hpersonsearch v-model="item.id" label="شخص" />
|
||||
</v-col>
|
||||
<v-col cols="12" md="4">
|
||||
<Hnumberinput
|
||||
|
@ -346,6 +338,7 @@ import archiveUpload from "../component/archive/archiveUpload.vue";
|
|||
import Hdatepicker from "@/components/forms/Hdatepicker.vue";
|
||||
import Hnumberinput from "@/components/forms/Hnumberinput.vue";
|
||||
import Htabletreeselect from '@/components/forms/Htabletreeselect.vue'
|
||||
import Hpersonsearch from '@/components/forms/Hpersonsearch.vue'
|
||||
// import the styles
|
||||
import quickAdd from "../component/person/quickAdd.vue";
|
||||
export default {
|
||||
|
@ -357,6 +350,7 @@ export default {
|
|||
Hdatepicker,
|
||||
Hnumberinput,
|
||||
Htabletreeselect,
|
||||
Hpersonsearch,
|
||||
},
|
||||
data: () => {
|
||||
return {
|
||||
|
@ -486,7 +480,7 @@ export default {
|
|||
},
|
||||
addPerson() {
|
||||
this.persons.push({
|
||||
person: '',
|
||||
id: '',
|
||||
amount: '',
|
||||
des: ''
|
||||
})
|
||||
|
@ -575,11 +569,6 @@ export default {
|
|||
axios.post('/api/salary/list').then((response) => {
|
||||
this.listSalarys = response.data;
|
||||
});
|
||||
|
||||
//get list of persons
|
||||
axios.post('/api/person/list/search').then((response) => {
|
||||
this.listPersons = response.data;
|
||||
});
|
||||
},
|
||||
save() {
|
||||
let haszero = false;
|
||||
|
@ -618,7 +607,7 @@ export default {
|
|||
}
|
||||
})
|
||||
this.persons.forEach((item) => {
|
||||
if (item.person == null || item.person == '') {
|
||||
if (item.id == null || item.id == '') {
|
||||
sideOK = false;
|
||||
}
|
||||
})
|
||||
|
@ -697,7 +686,7 @@ export default {
|
|||
this.persons.forEach((item) => {
|
||||
if (item.des == '') item.des = 'هزینه'
|
||||
rows.push({
|
||||
id: item.person,
|
||||
id: item.id,
|
||||
bs: parseInt(item.amount),
|
||||
bd: 0,
|
||||
des: item.des,
|
||||
|
|
Loading…
Reference in a new issue