fix zarin duplicate hesab and convert mesghal unit price to gram before cash/weight.
Reuse an existing Zarin hesab instead of a second addhesab, and stop rial-locked orders from treating mesghal as per-gram. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -11,6 +11,7 @@ use App\Models\Zarin;
|
||||
use App\Services\AccountingProductDocMapper;
|
||||
use App\Services\ZarinSyncService;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Contracts\Cache\LockTimeoutException;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
@@ -1146,6 +1147,79 @@ class ZarinController extends Controller
|
||||
return '';
|
||||
}
|
||||
|
||||
/** کد حساب زرین از پاسخ addhesab / listhesabha — OK و Code هم مثل idHesab معتبرند */
|
||||
private function extractZarinHesabId(array $row): ?int
|
||||
{
|
||||
foreach (['idHesab', 'idhesab', 'Code', 'code', 'OK', 'id'] as $key) {
|
||||
if (! array_key_exists($key, $row)) {
|
||||
continue;
|
||||
}
|
||||
$value = $row[$key];
|
||||
if ($value === null || $value === '' || $value === false || $value === true) {
|
||||
continue;
|
||||
}
|
||||
if (is_numeric($value) && (int) $value > 0) {
|
||||
return (int) $value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/** حساب از قبل ساختهشده در زرین — با موبایل، تا addhesab دوم نسازیم */
|
||||
private function findExistingZarinHesabId(?string $mobile): ?int
|
||||
{
|
||||
$want = Customer::normalizeMobile($mobile ?? '');
|
||||
if ($want === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$fetched = $this->fetchAllZarinCustomers();
|
||||
$rows = $fetched['rows'] ?? [];
|
||||
if ($rows === []) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$groupFilter = $this->zarinCustomerGroupName();
|
||||
$sameGroup = null;
|
||||
$any = null;
|
||||
|
||||
foreach ($rows as $item) {
|
||||
if (! is_array($item)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$phone = $this->extractZarinPhone($item);
|
||||
$got = Customer::normalizeMobile($phone);
|
||||
if ($got === null || $got !== $want) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$id = $this->extractZarinHesabId($item);
|
||||
if ($id === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$g = $this->extractZarinGroup($item);
|
||||
if ($groupFilter !== '' && $g !== '' && $this->zarinGroupNamesMatch($g, $groupFilter)) {
|
||||
$sameGroup = $id;
|
||||
break;
|
||||
}
|
||||
|
||||
$any ??= $id;
|
||||
}
|
||||
|
||||
return $sameGroup ?? $any;
|
||||
}
|
||||
|
||||
private function bindCustomerZarinHesab(Customer $customer, int $idHesab): int
|
||||
{
|
||||
$customer->moshtari_code = $idHesab;
|
||||
$customer->save();
|
||||
|
||||
return $idHesab;
|
||||
}
|
||||
|
||||
public function syncPanelToZarin(): \Illuminate\Http\JsonResponse
|
||||
{
|
||||
$customers = Customer::whereNull('deleted_at')
|
||||
@@ -1450,7 +1524,7 @@ class ZarinController extends Controller
|
||||
$isColleagueLeg = ! empty($data['colleague_leg']) && $accountOverride !== '';
|
||||
|
||||
if (! $isColleagueLeg) {
|
||||
if ($customer && ($customer->moshtari_code === null)) {
|
||||
if ($customer && ! $customer->hasValidMoshtariCode()) {
|
||||
$this->createCustomerInZarin($customer->id);
|
||||
$customer = Customer::where('id', $data['customer_id'])->first();
|
||||
}
|
||||
@@ -1472,6 +1546,9 @@ class ZarinController extends Controller
|
||||
$count = $mapper->accountingQty($product, $rawAmount, $data);
|
||||
$vazn = $mapper->accountingWeight($product, $rawAmount, $data);
|
||||
$isBuy = (int) ($data['direction'] ?? 0) === 1;
|
||||
// زرین korf/parDar از دید حساب مشتری است، نه فروشگاه:
|
||||
// خرید مشتری → k / +1 : طلا بستانکار (سوت اضافه) + ریال بدهکار (پول کم)
|
||||
// فروش مشتری → f / −1 : طلا بدهکار + ریال بستانکار
|
||||
$orderId = is_object($data['order'] ?? null)
|
||||
? ($data['order']->id ?? null)
|
||||
: ($data['order']['id'] ?? ($existing->order_id ?? null));
|
||||
@@ -1530,7 +1607,7 @@ class ZarinController extends Controller
|
||||
$accountCustomer,
|
||||
$product,
|
||||
$count,
|
||||
$isBuy ? -1 : 1,
|
||||
$isBuy ? 1 : -1,
|
||||
$fi,
|
||||
$sharh,
|
||||
$this->zarinUid($uidKind, $uidSource ?? $zarin->id)
|
||||
@@ -1541,7 +1618,7 @@ class ZarinController extends Controller
|
||||
$data,
|
||||
$accountCustomer,
|
||||
$vazn,
|
||||
$isBuy ? 'f' : 'k',
|
||||
$isBuy ? 'k' : 'f',
|
||||
(float) ($data['price'] ?? 0),
|
||||
$sharh,
|
||||
$mapper->jensFelez($product) ?? 0,
|
||||
@@ -1576,7 +1653,7 @@ class ZarinController extends Controller
|
||||
|
||||
$customer = Customer::where('id', $data['customer_id'])->first();
|
||||
|
||||
if ($customer && ($customer->moshtari_code === null)) {
|
||||
if ($customer && ! $customer->hasValidMoshtariCode()) {
|
||||
$this->createCustomerInZarin($customer->id);
|
||||
$customer = Customer::where('id', $data['customer_id'])->first();
|
||||
}
|
||||
@@ -1698,7 +1775,7 @@ class ZarinController extends Controller
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($customer->moshtari_code === null) {
|
||||
if (! $customer->hasValidMoshtariCode()) {
|
||||
$this->createCustomerInZarin($customer->id);
|
||||
$customer = Customer::where('id', $data['customer_id'])->first();
|
||||
}
|
||||
@@ -1806,7 +1883,7 @@ class ZarinController extends Controller
|
||||
|
||||
$customer = Customer::where('id', $data['customer_id'])->first();
|
||||
|
||||
if ($customer && ($customer->moshtari_code === null)) {
|
||||
if ($customer && ! $customer->hasValidMoshtariCode()) {
|
||||
$this->createCustomerInZarin($customer->id);
|
||||
$customer = Customer::where('id', $data['customer_id'])->first();
|
||||
}
|
||||
@@ -2066,16 +2143,18 @@ class ZarinController extends Controller
|
||||
{
|
||||
$customer = Customer::findOrFail($customer_id);
|
||||
|
||||
if ($customer->moshtari_code != null) {
|
||||
if ($customer->hasValidMoshtariCode()) {
|
||||
return $customer->moshtari_code;
|
||||
}
|
||||
|
||||
$lock = Cache::lock('zarin:register-customer:' . $customer->id, 30);
|
||||
$lock = Cache::lock('zarin:register-customer:' . $customer->id, 90);
|
||||
|
||||
if (!$lock->get()) {
|
||||
try {
|
||||
$lock->block(25);
|
||||
} catch (LockTimeoutException $e) {
|
||||
$customer->refresh();
|
||||
|
||||
if ($customer->moshtari_code != null) {
|
||||
if ($customer->hasValidMoshtariCode()) {
|
||||
return $customer->moshtari_code;
|
||||
}
|
||||
|
||||
@@ -2085,10 +2164,15 @@ class ZarinController extends Controller
|
||||
try {
|
||||
$customer->refresh();
|
||||
|
||||
if ($customer->moshtari_code != null) {
|
||||
if ($customer->hasValidMoshtariCode()) {
|
||||
return $customer->moshtari_code;
|
||||
}
|
||||
|
||||
$existingId = $this->findExistingZarinHesabId($customer->mobile);
|
||||
if ($existingId !== null) {
|
||||
return $this->bindCustomerZarinHesab($customer, $existingId);
|
||||
}
|
||||
|
||||
$name = $customer->fname ?: ($customer->name ?? ('مشتری ' . $customer->id));
|
||||
$family = $customer->lname ?: '';
|
||||
$mobile = $customer->mobile ?? '';
|
||||
@@ -2119,14 +2203,15 @@ class ZarinController extends Controller
|
||||
}
|
||||
|
||||
$data = $this->extractResponseRow($response);
|
||||
$idHesab = $data['idHesab'] ?? null;
|
||||
$idHesab = $this->extractZarinHesabId($data);
|
||||
|
||||
if (!empty($idHesab)) {
|
||||
$customer->moshtari_code = $idHesab;
|
||||
$customer->save();
|
||||
if ($idHesab !== null) {
|
||||
return $this->bindCustomerZarinHesab($customer, $idHesab);
|
||||
}
|
||||
|
||||
// int برگردان تا با پیام خطای string اشتباه نشود
|
||||
return is_numeric($idHesab) ? (0 + $idHesab) : $idHesab;
|
||||
$existingId = $this->findExistingZarinHesabId($customer->mobile);
|
||||
if ($existingId !== null) {
|
||||
return $this->bindCustomerZarinHesab($customer, $existingId);
|
||||
}
|
||||
|
||||
$detail = $data['msg'] ?? $data['message'] ?? $data['detail'] ?? null;
|
||||
|
||||
Reference in New Issue
Block a user