fix some bugs from accounting 5
This commit is contained in:
@@ -272,13 +272,18 @@ class ZarinController extends Controller
|
||||
|
||||
/**
|
||||
* پیدا کردن کار/کالای محصول در زرین.
|
||||
* اول infokarbarcodi (اگر روی آن سرور فعال باشد)؛ وگرنه infosakhte (لیست کامل).
|
||||
* اولویت: listKarSakhte (کاتالوگ کار ساخته) → infosakhte → infokarbarcodi.
|
||||
*/
|
||||
private function findZarinKarForProduct(Product $product, $goroheKar = null, bool $exactOnly = false)
|
||||
{
|
||||
$goroheKar = $goroheKar ?: $this->zarinDefaultGoroheKar();
|
||||
$productName = $this->normalizeZarinName($product->title);
|
||||
|
||||
$fromList = $this->findZarinKarInListKarSakhte($productName, $exactOnly);
|
||||
if ($fromList) {
|
||||
return $fromList;
|
||||
}
|
||||
|
||||
$fromBarcode = $this->findZarinKarInInfokarbarcodi($productName, $goroheKar, $exactOnly);
|
||||
if ($fromBarcode) {
|
||||
return $fromBarcode;
|
||||
@@ -287,6 +292,73 @@ class ZarinController extends Controller
|
||||
return $this->findZarinKarInInfosakhte($productName, $goroheKar, $exactOnly);
|
||||
}
|
||||
|
||||
/**
|
||||
* کاتالوگ کارهای ساخته (لیست ۴۷ زرین) — id همین idKar سند تعدادی است.
|
||||
*/
|
||||
private function findZarinKarInListKarSakhte(string $productName, bool $exactOnly = false): ?array
|
||||
{
|
||||
$response = $this->zarinRequest([
|
||||
'kind' => 'listKarSakhte',
|
||||
], 30);
|
||||
|
||||
if (!$response || !$response->successful()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$rows = $this->zarinRowsFromBody($response->json());
|
||||
if (empty($rows)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$exact = null;
|
||||
$fuzzy = null;
|
||||
|
||||
foreach ($rows as $row) {
|
||||
if (!is_array($row)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$name = $row['namFelezsakhthe']
|
||||
?? $row['nam_kar_sakhte']
|
||||
?? $row['nameKar']
|
||||
?? $row['nam']
|
||||
?? $row['name']
|
||||
?? '';
|
||||
$rowName = $this->normalizeZarinName($name);
|
||||
$idKar = $this->extractUsableZarinKarId($row);
|
||||
if (!$idKar || $rowName === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($rowName === $productName) {
|
||||
$exact = [
|
||||
'idKar' => $idKar,
|
||||
'row' => $row,
|
||||
'match' => 'exact',
|
||||
'source' => 'listKarSakhte',
|
||||
];
|
||||
break;
|
||||
}
|
||||
|
||||
if (
|
||||
!$exactOnly
|
||||
&& (
|
||||
$this->containsText($rowName, $productName)
|
||||
|| $this->containsText($productName, $rowName)
|
||||
)
|
||||
) {
|
||||
$fuzzy ??= [
|
||||
'idKar' => $idKar,
|
||||
'row' => $row,
|
||||
'match' => 'fuzzy',
|
||||
'source' => 'listKarSakhte',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $exact ?? ($exactOnly ? null : $fuzzy);
|
||||
}
|
||||
|
||||
private function matchZarinKarRow(string $productName, array $row, bool $exactOnly = false): ?array
|
||||
{
|
||||
$name = $row['nameKar']
|
||||
@@ -558,6 +630,32 @@ class ZarinController extends Controller
|
||||
}
|
||||
|
||||
$body = $response->json();
|
||||
if (is_array($body) && array_key_exists('state', $body) && filter_var($body['state'], FILTER_VALIDATE_BOOLEAN) === false) {
|
||||
// ممکن است کالا از قبل باشد و idKar در پیام آمده باشد
|
||||
$createdIdKar = $this->extractIdKarFromCreateResponse($body);
|
||||
if ($createdIdKar) {
|
||||
$product->finance_p_name = (string) $createdIdKar;
|
||||
$product->save();
|
||||
|
||||
return [
|
||||
'ok' => true,
|
||||
'source' => 'create_response_idKar_despite_state',
|
||||
'idKar' => $createdIdKar,
|
||||
'product' => $product->fresh(),
|
||||
'zarin_response' => $body,
|
||||
'sent_params_success' => $params,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'ok' => false,
|
||||
'message' => (string) ($body['detail'] ?? $body['msg'] ?? $body['message'] ?? 'ساخت کد کار در زرین ناموفق بود.'),
|
||||
'status_code' => 422,
|
||||
'zarin_response' => $body,
|
||||
'sent_params' => $params,
|
||||
];
|
||||
}
|
||||
|
||||
$createdIdKar = $this->extractIdKarFromCreateResponse(is_array($body) ? $body : null);
|
||||
|
||||
// اولویت با idKar برگشتی از ساخت — جستجوی فازی نام میتواند کالای اشتباه بچسباند
|
||||
@@ -607,7 +705,35 @@ class ZarinController extends Controller
|
||||
$currentIdKar = $product->finance_p_name;
|
||||
$productName = $this->normalizeZarinName($product->title);
|
||||
|
||||
if (!$forceCreate && !empty($currentIdKar) && is_numeric($currentIdKar)) {
|
||||
// بعد از «کد کار اشتباه»: کالای تازه بساز؛ اگر ساخت نشد، exact از کاتالوگ
|
||||
if ($forceCreate) {
|
||||
$this->clearProductZarinKar($product);
|
||||
$product->refresh();
|
||||
|
||||
$created = $this->createZarinKarForProduct($product);
|
||||
if (!empty($created['ok']) && !empty($created['idKar'])) {
|
||||
return $created;
|
||||
}
|
||||
|
||||
$found = $this->findZarinKarForProduct($product, $this->zarinDefaultGoroheKar(), true);
|
||||
if ($found && !empty($found['idKar']) && is_numeric($found['idKar'])) {
|
||||
$product->finance_p_name = (string) $found['idKar'];
|
||||
$product->save();
|
||||
|
||||
return [
|
||||
'ok' => true,
|
||||
'source' => 'found_exact_after_create_failed',
|
||||
'idKar' => (int) $found['idKar'],
|
||||
'product' => $product->fresh(),
|
||||
'zarin_row' => $found['row'],
|
||||
'create_error' => $created,
|
||||
];
|
||||
}
|
||||
|
||||
return $created;
|
||||
}
|
||||
|
||||
if (!empty($currentIdKar) && is_numeric($currentIdKar)) {
|
||||
$existingRow = $this->getZarinKarById($currentIdKar);
|
||||
|
||||
if ($existingRow) {
|
||||
@@ -641,15 +767,14 @@ class ZarinController extends Controller
|
||||
];
|
||||
}
|
||||
} else {
|
||||
// finance_p_name کهنه / اشتباه — پاک کن تا دوباره پیدا یا ساخته شود
|
||||
$this->clearProductZarinKar($product);
|
||||
$product->refresh();
|
||||
}
|
||||
}
|
||||
|
||||
// بعد از خطای «کد کار اشتباه»: فقط تطبیق دقیق نام، نه فازی
|
||||
$exactOnly = (bool) $forceCreate;
|
||||
$found = $this->findZarinKarForProduct($product, $this->zarinDefaultGoroheKar(), $exactOnly);
|
||||
// اول فقط exact؛ اگر نبود fuzzy از listKarSakhte/infosakhte
|
||||
$found = $this->findZarinKarForProduct($product, $this->zarinDefaultGoroheKar(), true)
|
||||
?? $this->findZarinKarForProduct($product, $this->zarinDefaultGoroheKar(), false);
|
||||
|
||||
if ($found && !empty($found['idKar']) && is_numeric($found['idKar'])) {
|
||||
$product->finance_p_name = (string) $found['idKar'];
|
||||
@@ -657,11 +782,12 @@ class ZarinController extends Controller
|
||||
|
||||
return [
|
||||
'ok' => true,
|
||||
'source' => $exactOnly ? 'found_exact_after_invalid' : 'found_by_name',
|
||||
'source' => 'found_by_name',
|
||||
'idKar' => (int) $found['idKar'],
|
||||
'product' => $product->fresh(),
|
||||
'zarin_row' => $found['row'],
|
||||
'match' => $found['match'] ?? null,
|
||||
'list_source' => $found['source'] ?? null,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1690,10 +1816,11 @@ class ZarinController extends Controller
|
||||
return false;
|
||||
}
|
||||
|
||||
$idKar = (int) $kar['idKar'];
|
||||
$http = $this->zarinRequest([
|
||||
'kind' => 'sabtSanadTedadi',
|
||||
'idHesab' => $customer->moshtari_code,
|
||||
'idKar' => (int) $kar['idKar'],
|
||||
'idKar' => $idKar,
|
||||
'fi' => $fi,
|
||||
'tedad' => $tedad,
|
||||
'parDar' => $parDar,
|
||||
@@ -1707,11 +1834,21 @@ class ZarinController extends Controller
|
||||
}
|
||||
|
||||
[$response, $httpError] = $this->zarinDecodeResponse($http);
|
||||
$diag = 'idKar=' . $idKar
|
||||
. ' noeKar=' . $this->zarinDefaultNoeKar()
|
||||
. ' goroheKar=' . $this->zarinDefaultGoroheKar()
|
||||
. ' product=' . ($product->title ?? '')
|
||||
. ' source=' . ($kar['source'] ?? '');
|
||||
|
||||
if (
|
||||
!$retriedInvalidKar
|
||||
&& $this->isInvalidZarinKarError($response, $httpError)
|
||||
) {
|
||||
Log::warning('zarin sabtSanadTedadi invalid idKar, recreating', [
|
||||
'diag' => $diag,
|
||||
'response' => $response,
|
||||
'httpError' => $httpError,
|
||||
]);
|
||||
$this->clearProductZarinKar($product);
|
||||
$product->refresh();
|
||||
$retriedInvalidKar = true;
|
||||
@@ -1719,7 +1856,11 @@ class ZarinController extends Controller
|
||||
}
|
||||
|
||||
if ($httpError) {
|
||||
$this->sync()->markFailed($zarin, $response ?? $httpError, $httpError);
|
||||
$this->sync()->markFailed(
|
||||
$zarin,
|
||||
$response ?? $httpError,
|
||||
$httpError . ' | ' . $diag
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1733,13 +1874,21 @@ class ZarinController extends Controller
|
||||
!$retriedInvalidKar
|
||||
&& $this->isInvalidZarinKarError($response)
|
||||
) {
|
||||
Log::warning('zarin sabtSanadTedadi invalid idKar (HTTP 200), recreating', [
|
||||
'diag' => $diag,
|
||||
'response' => $response,
|
||||
]);
|
||||
$this->clearProductZarinKar($product);
|
||||
$product->refresh();
|
||||
$retriedInvalidKar = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->sync()->markFailed($zarin, $response, 'ثبت سند تعدادی در زرین ناموفق بود');
|
||||
$this->sync()->markFailed(
|
||||
$zarin,
|
||||
$response,
|
||||
'ثبت سند تعدادی در زرین ناموفق بود | ' . $diag
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,7 +236,13 @@ class ZarinSyncService
|
||||
|
||||
$desc = (string) $row->desc;
|
||||
|
||||
if (str_contains($desc, 'شارژ کیف') || str_contains($desc, 'برداشت از کیف')) {
|
||||
if (str_contains($desc, 'شارژ') || str_contains($desc, 'دشارژ') || str_contains($desc, 'برداشت از کیف') || str_contains($desc, 'شارژ کیف')) {
|
||||
return 'walletGold';
|
||||
}
|
||||
|
||||
// نوع تعدادی ذخیرهشده روی ردیف sync
|
||||
$type = (string) $row->type;
|
||||
if (in_array($type, ['سکه', 'شمش', 'کارساخته'], true)) {
|
||||
return 'walletGold';
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user