bug fix in cheque and add support person transactions sort by

This commit is contained in:
Hesabix 2025-08-04 15:02:55 +00:00
parent 63b6654cc8
commit 11caf42da8
5 changed files with 89 additions and 15 deletions

View file

@ -86,6 +86,7 @@ class PersonService
$search = $params['search'] ?? ''; $search = $params['search'] ?? '';
$types = $params['types'] ?? null; $types = $params['types'] ?? null;
$transactionFilters = $params['transactionFilters'] ?? null; $transactionFilters = $params['transactionFilters'] ?? null;
$sortBy = $params['sortBy'] ?? null;
$queryBuilder = $this->entityManager->getRepository(Person::class) $queryBuilder = $this->entityManager->getRepository(Person::class)
->createQueryBuilder('p') ->createQueryBuilder('p')
@ -104,18 +105,66 @@ class PersonService
->setParameter('types', $types); ->setParameter('types', $types);
} }
// بررسی اینکه آیا سورت روی فیلدهای محاسبه‌شده است
$hasCalculatedSort = false;
$calculatedSortField = null;
$calculatedSortOrder = null;
if ($sortBy && is_array($sortBy) && !empty($sortBy)) {
foreach ($sortBy as $sort) {
if (isset($sort['key']) && in_array($sort['key'], ['bs', 'bd', 'balance'])) {
$hasCalculatedSort = true;
$calculatedSortField = $sort['key'];
$calculatedSortOrder = $sort['order'];
break;
}
}
}
// اگر سورت روی فیلدهای محاسبه‌شده است، ابتدا همه داده‌ها را دریافت کن
if ($hasCalculatedSort) {
$persons = $queryBuilder
->select('p')
->getQuery()
->getResult();
} else {
// اعمال سورت کردن برای فیلدهای مستقیم
if ($sortBy && is_array($sortBy) && !empty($sortBy)) {
foreach ($sortBy as $sort) {
if (isset($sort['key']) && isset($sort['order'])) {
$field = $sort['key'];
$order = strtoupper($sort['order']);
// بررسی فیلدهای مجاز برای سورت
$allowedFields = [
'code', 'nikename', 'name', 'birthday', 'company',
'shenasemeli', 'codeeghtesadi', 'sabt', 'keshvar',
'ostan', 'shahr', 'postalcode', 'tel', 'mobile',
'mobile2', 'email', 'website', 'fax', 'speedAccess'
];
if (in_array($field, $allowedFields)) {
$queryBuilder->addOrderBy("p.$field", $order);
}
}
}
} else {
// سورت پیش‌فرض بر اساس کد
$queryBuilder->orderBy('p.code', 'ASC');
}
$persons = $queryBuilder
->select('p')
->setFirstResult(($page - 1) * $itemsPerPage)
->setMaxResults($itemsPerPage)
->getQuery()
->getResult();
}
$totalItems = (clone $queryBuilder) $totalItems = (clone $queryBuilder)
->select('COUNT(p.id)') ->select('COUNT(p.id)')
->getQuery() ->getQuery()
->getSingleScalarResult(); ->getSingleScalarResult();
$persons = $queryBuilder
->select('p')
->setFirstResult(($page - 1) * $itemsPerPage)
->setMaxResults($itemsPerPage)
->getQuery()
->getResult();
$response = []; $response = [];
foreach ($persons as $person) { foreach ($persons as $person) {
$rows = $this->entityManager->getRepository(HesabdariRow::class)->findBy([ $rows = $this->entityManager->getRepository(HesabdariRow::class)->findBy([
@ -158,10 +207,27 @@ class PersonService
} }
} }
// اگر سورت روی فیلدهای محاسبه‌شده است، اینجا سورت کن
if ($hasCalculatedSort && $calculatedSortField && $calculatedSortOrder) {
usort($response, function($a, $b) use ($calculatedSortField, $calculatedSortOrder) {
$aVal = $a[$calculatedSortField] ?? 0;
$bVal = $b[$calculatedSortField] ?? 0;
if ($calculatedSortOrder === 'ASC') {
return $aVal <=> $bVal;
} else {
return $bVal <=> $aVal;
}
});
// اعمال صفحه‌بندی بعد از سورت
$response = array_slice($response, ($page - 1) * $itemsPerPage, $itemsPerPage);
}
$filteredTotal = count($response); $filteredTotal = count($response);
return [ return [
'items' => array_slice($response, 0, $itemsPerPage), 'items' => $response,
'total' => $filteredTotal, 'total' => $filteredTotal,
'unfilteredTotal' => $totalItems, 'unfilteredTotal' => $totalItems,
]; ];

View file

@ -745,6 +745,7 @@ const fa_lang = {
}, },
"person_card": { "person_card": {
accounting_status: 'وضعیت حسابداری', accounting_status: 'وضعیت حسابداری',
transfer_cheque: 'واگذاری چک',
"title": "کارت حساب اشخاص", "title": "کارت حساب اشخاص",
"account_card": "کارت حساب", "account_card": "کارت حساب",
"account_status": "وضعیت حساب", "account_status": "وضعیت حساب",

View file

@ -384,6 +384,7 @@ export default {
modify_cheque: '/acc/accounting/view/', modify_cheque: '/acc/accounting/view/',
modify_cheque_output: '/acc/accounting/view/', modify_cheque_output: '/acc/accounting/view/',
pass_cheque: '/acc/accounting/view/', pass_cheque: '/acc/accounting/view/',
transfer_cheque: '/acc/accounting/view/',
}; };
return routes[type] + code; return routes[type] + code;
}, },
@ -403,6 +404,7 @@ export default {
modify_cheque: this.$t('pages.person_card.modify_cheque'), modify_cheque: this.$t('pages.person_card.modify_cheque'),
pass_cheque: this.$t('pages.person_card.pass_cheque'), pass_cheque: this.$t('pages.person_card.pass_cheque'),
modify_cheque_output: this.$t('pages.person_card.modify_cheque_output'), modify_cheque_output: this.$t('pages.person_card.modify_cheque_output'),
transfer_cheque: this.$t('pages.person_card.transfer_cheque'),
}; };
return labels[type] || type; return labels[type] || type;
}, },

View file

@ -307,10 +307,13 @@ const fetchData = async () => {
const selectedTransactionFilters = transactionFilters.value const selectedTransactionFilters = transactionFilters.value
.filter((filter) => filter.checked) .filter((filter) => filter.checked)
.map((filter) => filter.value); .map((filter) => filter.value);
// تبدیل سورتهای Vuetify به فرمت مورد نیاز سرور
const sortBy = serverOptions.value.sortBy.map((sort) => ({ const sortBy = serverOptions.value.sortBy.map((sort) => ({
key: sort.key, key: sort.key,
order: sort.order === 'asc' ? 'ASC' : 'DESC', order: sort.order === 'asc' ? 'ASC' : 'DESC',
})); }));
const response = await axios.post('/api/person/list', { const response = await axios.post('/api/person/list', {
page: serverOptions.value.page, page: serverOptions.value.page,
itemsPerPage: serverOptions.value.rowsPerPage, itemsPerPage: serverOptions.value.rowsPerPage,

View file

@ -121,7 +121,7 @@
<PrintDialog <PrintDialog
v-model="modal" v-model="modal"
:plugins="plugins" :plugins="plugins"
@print="printInvoice" @print="handlePrint"
@cancel="modal = false" @cancel="modal = false"
/> />
<!-- End Print Modal --> <!-- End Print Modal -->
@ -187,10 +187,9 @@
<script> <script>
import axios from "axios"; import axios from "axios";
import { ref, defineComponent } from "vue";
import PrintDialog from '@/components/PrintDialog.vue'; import PrintDialog from '@/components/PrintDialog.vue';
export default defineComponent ({ export default {
name: "list", name: "list",
components: { components: {
PrintDialog PrintDialog
@ -232,7 +231,7 @@ export default defineComponent ({
sumTotal: 0, sumTotal: 0,
itemsSelected: [], itemsSelected: [],
searchValue: '', searchValue: '',
loading: ref(true), loading: true,
items: [], items: [],
orgItems: [], orgItems: [],
headers: [ headers: [
@ -335,13 +334,16 @@ export default defineComponent ({
} }
}); });
}, },
printInvoice(pdf = true, cloudePrinters = true) { handlePrint(printOptions) {
this.printInvoice(true, true, printOptions);
},
printInvoice(pdf = true, cloudePrinters = true, printOptions = null) {
this.loading = true; this.loading = true;
axios.post('/api/preinvoice/print/invoice', { axios.post('/api/preinvoice/print/invoice', {
'code': this.printOptions.selectedPrintCode, 'code': this.printOptions.selectedPrintCode,
'pdf': pdf, 'pdf': pdf,
'printers': cloudePrinters, 'printers': cloudePrinters,
'printOptions': this.printOptions 'printOptions': printOptions || this.printOptions
}).then((response) => { }).then((response) => {
this.loading = false; this.loading = false;
window.open(this.$API_URL + '/front/print/' + response.data.id, '_blank', 'noreferrer'); window.open(this.$API_URL + '/front/print/' + response.data.id, '_blank', 'noreferrer');
@ -419,7 +421,7 @@ export default defineComponent ({
deep: false deep: false
} }
} }
}) }
</script> </script>
<style scoped> <style scoped>