forked from morrning/hesabixCore
146 lines
4.9 KiB
Markdown
146 lines
4.9 KiB
Markdown
|
|
# رفع خطای NonUniqueResultException در کدهای تکراری
|
||
|
|
|
||
|
|
## مشکل
|
||
|
|
خطای `NonUniqueResultException` با پیام "More than one result was found for query although one row or none was expected" در متد `app_accounting_remove_doc` رخ میدهد.
|
||
|
|
|
||
|
|
## علت
|
||
|
|
این خطا زمانی رخ میدهد که چندین سند حسابداری با کد یکسان در دیتابیس وجود دارد و متد `findOneBy` نمیتواند تصمیم بگیرد کدام سند را برگرداند.
|
||
|
|
|
||
|
|
## راهحلهای پیادهسازی شده
|
||
|
|
|
||
|
|
### 1. بهبود متد `app_accounting_remove_doc`
|
||
|
|
|
||
|
|
#### تغییرات:
|
||
|
|
- **بررسی خودکار کدهای تکراری**: قبل از حذف سند، بررسی میشود که آیا کدهای تکراری وجود دارد
|
||
|
|
- **ترمیم خودکار**: در صورت وجود کدهای تکراری، سیستم خودکار آنها را ترمیم میکند
|
||
|
|
- **پیدا کردن ایمن**: پس از ترمیم، سند به صورت ایمن پیدا میشود
|
||
|
|
|
||
|
|
#### کد جدید:
|
||
|
|
```php
|
||
|
|
// ابتدا بررسی کن که آیا کدهای تکراری وجود دارد
|
||
|
|
if ($provider->hasDuplicateCodes($request->headers->get('activeBid'), 'accounting')) {
|
||
|
|
// کدهای تکراری وجود دارد، ترمیم کن
|
||
|
|
$provider->fixDuplicateCodes($request->headers->get('activeBid'), 'accounting');
|
||
|
|
}
|
||
|
|
|
||
|
|
// حالا سند را پیدا کن
|
||
|
|
$doc = $entityManager->getRepository(HesabdariDoc::class)->findOneBy([
|
||
|
|
'code' => $params['code'],
|
||
|
|
'bid' => $request->headers->get('activeBid')
|
||
|
|
]);
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. متد جدید `hasDuplicateCodes`
|
||
|
|
|
||
|
|
#### عملکرد:
|
||
|
|
- بررسی وجود کدهای تکراری بدون ترمیم
|
||
|
|
- بازگشت `true` یا `false`
|
||
|
|
- قابل استفاده برای بررسی وضعیت قبل از عملیات
|
||
|
|
|
||
|
|
#### کد:
|
||
|
|
```php
|
||
|
|
public function hasDuplicateCodes($bid, $part = 'accounting')
|
||
|
|
{
|
||
|
|
// پیدا کردن کدهای تکراری
|
||
|
|
$qb = $repository->createQueryBuilder('e');
|
||
|
|
$qb->select('e.code, COUNT(e.id) as count')
|
||
|
|
->where('e.bid = :bid')
|
||
|
|
->setParameter('bid', $bid)
|
||
|
|
->groupBy('e.code')
|
||
|
|
->having('COUNT(e.id) > 1');
|
||
|
|
|
||
|
|
$duplicates = $qb->getQuery()->getResult();
|
||
|
|
|
||
|
|
return count($duplicates) > 0;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3. API جدید برای بررسی وضعیت
|
||
|
|
|
||
|
|
#### Endpoint: `/api/accounting/check-duplicate-codes`
|
||
|
|
- **Method**: GET
|
||
|
|
- **Access**: فقط ادمین
|
||
|
|
- **Function**: بررسی وجود کدهای تکراری
|
||
|
|
|
||
|
|
#### مثال استفاده:
|
||
|
|
```bash
|
||
|
|
GET /api/accounting/check-duplicate-codes?part=accounting
|
||
|
|
```
|
||
|
|
|
||
|
|
#### پاسخ:
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"result": 1,
|
||
|
|
"has_duplicates": true,
|
||
|
|
"message": "کدهای تکراری یافت شد"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## نحوه استفاده
|
||
|
|
|
||
|
|
### 1. بررسی وضعیت کدهای تکراری:
|
||
|
|
```bash
|
||
|
|
GET /api/accounting/check-duplicate-codes?part=accounting
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. ترمیم کدهای تکراری:
|
||
|
|
```bash
|
||
|
|
POST /api/accounting/fix-duplicate-codes
|
||
|
|
Content-Type: application/json
|
||
|
|
|
||
|
|
{
|
||
|
|
"part": "accounting"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3. حذف سند (خودکار ترمیم میکند):
|
||
|
|
```bash
|
||
|
|
POST /api/accounting/remove
|
||
|
|
Content-Type: application/json
|
||
|
|
|
||
|
|
{
|
||
|
|
"code": "1001"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## مزایای راهحل
|
||
|
|
|
||
|
|
1. **جلوگیری از خطا**: خطای `NonUniqueResultException` دیگر رخ نمیدهد
|
||
|
|
2. **ترمیم خودکار**: سیستم خودکار کدهای تکراری را ترمیم میکند
|
||
|
|
3. **بررسی وضعیت**: امکان بررسی وجود کدهای تکراری قبل از عملیات
|
||
|
|
4. **Backward Compatibility**: با کدهای موجود سازگار است
|
||
|
|
5. **امنیت**: فقط ادمین میتواند عملیات ترمیم را انجام دهد
|
||
|
|
|
||
|
|
## نکات مهم
|
||
|
|
|
||
|
|
1. **عملکرد خودکار**: حذف سند اکنون خودکار کدهای تکراری را ترمیم میکند
|
||
|
|
2. **بررسی قبل از عملیات**: میتوانید وضعیت کدهای تکراری را بررسی کنید
|
||
|
|
3. **ترمیم انتخابی**: میتوانید فقط کدهای تکراری را ترمیم کنید
|
||
|
|
4. **لاگ عملیات**: تمام عملیات ترمیم در لاگ ثبت میشود
|
||
|
|
5. **Backup**: قبل از ترمیم، از دیتابیس backup بگیرید
|
||
|
|
|
||
|
|
## تست
|
||
|
|
|
||
|
|
برای تست عملکرد:
|
||
|
|
|
||
|
|
1. **ایجاد کدهای تکراری** (در محیط تست):
|
||
|
|
```sql
|
||
|
|
UPDATE hesabdari_doc SET code = 1001 WHERE id IN (1, 2);
|
||
|
|
```
|
||
|
|
|
||
|
|
2. **بررسی وضعیت**:
|
||
|
|
```bash
|
||
|
|
GET /api/accounting/check-duplicate-codes
|
||
|
|
```
|
||
|
|
|
||
|
|
3. **حذف سند** (خودکار ترمیم میکند):
|
||
|
|
```bash
|
||
|
|
POST /api/accounting/remove
|
||
|
|
```
|
||
|
|
|
||
|
|
4. **بررسی مجدد**:
|
||
|
|
```bash
|
||
|
|
GET /api/accounting/check-duplicate-codes
|
||
|
|
```
|
||
|
|
|
||
|
|
این راهحل مشکل `NonUniqueResultException` را به طور کامل حل میکند و سیستم را در برابر کدهای تکراری محافظت میکند.
|