bug fix in persons and progress in redesign cost mod
This commit is contained in:
parent
2f3a47fc49
commit
290f5689dc
|
@ -543,15 +543,11 @@ class PersonsController extends AbstractController
|
|||
}
|
||||
|
||||
if ($include) {
|
||||
$response[] = [
|
||||
'id' => $person->getId(),
|
||||
'name' => $person->getName(),
|
||||
'nikename' => $person->getNikename(),
|
||||
'code' => $person->getCode(),
|
||||
'bs' => $bs, // بستانکار
|
||||
'bd' => $bd, // بدهکار
|
||||
'balance' => $balance, // تراز
|
||||
];
|
||||
$result = Explore::ExplorePerson($person, $entityManager->getRepository(PersonType::class)->findAll());
|
||||
$result['bs'] = $bs;
|
||||
$result['bd'] = $bd;
|
||||
$result['balance'] = $balance;
|
||||
$response[] = $result;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1059,14 +1055,14 @@ class PersonsController extends AbstractController
|
|||
if (!$acc) {
|
||||
throw $this->createAccessDeniedException();
|
||||
}
|
||||
|
||||
|
||||
// دریافت پارامترها
|
||||
$params = json_decode($request->getContent(), true) ?? [];
|
||||
$page = (int) ($params['page'] ?? 1);
|
||||
$itemsPerPage = (int) ($params['itemsPerPage'] ?? 10);
|
||||
$search = $params['search'] ?? '';
|
||||
$dateFilter = $params['dateFilter'] ?? 'all';
|
||||
|
||||
|
||||
// کوئری پایه برای اسناد
|
||||
$queryBuilder = $entityManager->getRepository(HesabdariDoc::class)
|
||||
->createQueryBuilder('d')
|
||||
|
@ -1078,13 +1074,13 @@ class PersonsController extends AbstractController
|
|||
->andWhere('d.year = :year')
|
||||
->andWhere('d.money = :money')
|
||||
->setParameters([
|
||||
'bid' => $acc['bid'],
|
||||
'type' => 'person_receive',
|
||||
'year' => $acc['year'],
|
||||
'money' => $acc['money'],
|
||||
])
|
||||
'bid' => $acc['bid'],
|
||||
'type' => 'person_receive',
|
||||
'year' => $acc['year'],
|
||||
'money' => $acc['money'],
|
||||
])
|
||||
->orderBy('d.id', 'DESC');
|
||||
|
||||
|
||||
// جستوجو
|
||||
if (!empty($search)) {
|
||||
$queryBuilder->andWhere(
|
||||
|
@ -1095,7 +1091,7 @@ class PersonsController extends AbstractController
|
|||
)
|
||||
)->setParameter('search', "%$search%");
|
||||
}
|
||||
|
||||
|
||||
// فیلتر تاریخ
|
||||
$today = $jdate->GetTodayDate();
|
||||
switch ($dateFilter) {
|
||||
|
@ -1123,14 +1119,14 @@ class PersonsController extends AbstractController
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// محاسبه تعداد کل
|
||||
$totalQuery = (clone $queryBuilder)
|
||||
->select('COUNT(DISTINCT d.id) as total')
|
||||
->getQuery()
|
||||
->getSingleResult();
|
||||
$total = (int) $totalQuery['total'];
|
||||
|
||||
|
||||
// گرفتن اسناد با صفحهبندی
|
||||
$docs = $queryBuilder
|
||||
->setFirstResult(($page - 1) * $itemsPerPage)
|
||||
|
@ -1173,7 +1169,7 @@ class PersonsController extends AbstractController
|
|||
'persons' => $persons[$doc['id']] ?? [],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
return $this->json([
|
||||
'items' => $items,
|
||||
'total' => $total,
|
||||
|
|
187
webUI/src/components/forms/Htabletreeselect.vue
Normal file
187
webUI/src/components/forms/Htabletreeselect.vue
Normal file
|
@ -0,0 +1,187 @@
|
|||
<template>
|
||||
<v-menu v-model="menu" :close-on-content-click="false">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-text-field
|
||||
v-bind="props"
|
||||
:model-value="selectedItem ? decodeLabel(selectedItem.label) + ` (${selectedItem.id})` : ''"
|
||||
readonly
|
||||
variant="outlined"
|
||||
hide-details
|
||||
density="compact"
|
||||
:label="label"
|
||||
class=""
|
||||
prepend-inner-icon="mdi-table"
|
||||
clearable
|
||||
@click:clear="clearSelection"
|
||||
>
|
||||
<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">
|
||||
<v-text-field
|
||||
v-model="searchQuery"
|
||||
density="compact"
|
||||
variant="outlined"
|
||||
hide-details
|
||||
class="mb-2"
|
||||
placeholder="جستجو..."
|
||||
prepend-inner-icon="mdi-magnify"
|
||||
clearable
|
||||
@click:clear="searchQuery = ''"
|
||||
></v-text-field>
|
||||
|
||||
<v-treeview
|
||||
:items="filteredItems"
|
||||
item-children="children"
|
||||
item-title="label"
|
||||
item-value="id"
|
||||
:loading="loading"
|
||||
density="compact"
|
||||
class="tree-container rtl-tree"
|
||||
hoverable
|
||||
>
|
||||
<template v-slot:prepend="{ item }">
|
||||
<div class="d-flex align-center">
|
||||
<v-radio
|
||||
:model-value="selectedItem?.id"
|
||||
:value="item.id"
|
||||
hide-details
|
||||
density="compact"
|
||||
@click.stop
|
||||
@change="selectItem(item)"
|
||||
></v-radio>
|
||||
<v-icon size="small" class="mr-1">
|
||||
{{ item.children && item.children.length > 0 ? 'mdi-folder' : 'mdi-file-outline' }}
|
||||
</v-icon>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-slot:label="{ item }">
|
||||
{{ decodeLabel(item.label) }} ({{ item.id }})
|
||||
</template>
|
||||
</v-treeview>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-menu>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios';
|
||||
|
||||
export default {
|
||||
name: 'CostTreeSelect',
|
||||
props: {
|
||||
modelValue: {
|
||||
type: [Object, Number],
|
||||
default: null
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
default: 'جدول حساب'
|
||||
},
|
||||
returnObject: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedItem: null,
|
||||
treeItems: [],
|
||||
loading: false,
|
||||
menu: false,
|
||||
searchQuery: ''
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
filteredItems() {
|
||||
if (!this.searchQuery) return this.treeItems;
|
||||
|
||||
const searchTerm = this.searchQuery.toLowerCase();
|
||||
return this.filterNodes(this.treeItems, (node) => {
|
||||
const labelMatch = this.decodeLabel(node.label).toLowerCase().includes(searchTerm);
|
||||
const idMatch = node.id.toString().includes(searchTerm);
|
||||
return labelMatch || idMatch;
|
||||
});
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
modelValue: {
|
||||
handler(newVal) {
|
||||
if (this.returnObject) {
|
||||
this.selectedItem = newVal;
|
||||
} else {
|
||||
this.selectedItem = this.findItemById(this.treeItems, newVal);
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
findItemById(items, id) {
|
||||
for (const item of items) {
|
||||
if (item.id === id) return item;
|
||||
if (item.children?.length) {
|
||||
const found = this.findItemById(item.children, id);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
async fetchTreeData() {
|
||||
this.loading = true;
|
||||
try {
|
||||
const response = await axios.get('/api/accounting/table/childs/cost');
|
||||
this.treeItems = response.data;
|
||||
} catch (error) {
|
||||
console.error('خطا در دریافت دادهها:', error);
|
||||
this.$toast.error('خطا در بارگذاری دادهها');
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
decodeLabel(label) {
|
||||
try {
|
||||
return decodeURIComponent(JSON.parse(`"${label}"`));
|
||||
} catch (e) {
|
||||
return label;
|
||||
}
|
||||
},
|
||||
selectItem(item) {
|
||||
this.selectedItem = item;
|
||||
this.$emit('update:modelValue', this.returnObject ? item : item.id);
|
||||
this.menu = false;
|
||||
},
|
||||
clearSelection() {
|
||||
this.selectedItem = null;
|
||||
this.$emit('update:modelValue', null);
|
||||
},
|
||||
filterNodes(nodes, predicate) {
|
||||
return nodes.reduce((filtered, node) => {
|
||||
const clone = { ...node };
|
||||
|
||||
if (predicate(clone)) {
|
||||
if (clone.children?.length) {
|
||||
clone.children = this.filterNodes(clone.children, predicate);
|
||||
}
|
||||
filtered.push(clone);
|
||||
} else if (clone.children?.length) {
|
||||
clone.children = this.filterNodes(clone.children, predicate);
|
||||
if (clone.children.length) {
|
||||
filtered.push(clone);
|
||||
}
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}, []);
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchTreeData();
|
||||
},
|
||||
};
|
||||
</script>
|
|
@ -102,16 +102,7 @@
|
|||
<v-card-text>
|
||||
<v-row>
|
||||
<v-col cols="12" md="4">
|
||||
<v-select
|
||||
v-model="item.id"
|
||||
:items="formattedCostItems"
|
||||
item-title="label"
|
||||
item-value="id"
|
||||
label="مرکز هزینه"
|
||||
variant="outlined"
|
||||
density="compact"
|
||||
return-object
|
||||
></v-select>
|
||||
<Htabletreeselect v-model="item.id" :items="listscosts" label="مرکز هزینه" />
|
||||
</v-col>
|
||||
<v-col cols="12" md="4">
|
||||
<Hnumberinput
|
||||
|
@ -203,19 +194,18 @@ import 'vue-loading-overlay/dist/css/index.css';
|
|||
import archiveUpload from "../component/archive/archiveUpload.vue";
|
||||
import Hdatepicker from "@/components/forms/Hdatepicker.vue";
|
||||
import Hnumberinput from "@/components/forms/Hnumberinput.vue";
|
||||
import Treeselect from 'vue3-treeselect'
|
||||
import Htabletreeselect from '@/components/forms/Htabletreeselect.vue'
|
||||
// import the styles
|
||||
import 'vue3-treeselect/dist/vue3-treeselect.css'
|
||||
import quickAdd from "../component/person/quickAdd.vue";
|
||||
export default {
|
||||
name: "mod",
|
||||
components: {
|
||||
Loading,
|
||||
Treeselect,
|
||||
archiveUpload,
|
||||
quickAdd,
|
||||
Hdatepicker,
|
||||
Hnumberinput
|
||||
Hnumberinput,
|
||||
Htabletreeselect,
|
||||
},
|
||||
data: () => {
|
||||
return {
|
||||
|
|
Loading…
Reference in a new issue