192 lines
6.6 KiB
PHP
192 lines
6.6 KiB
PHP
<?php
|
|||
|
|
|
||
|
|
namespace App\Services;
|
||
|
|
|
||
|
|
use App\Http\Controllers\Admin\TahesabController;
|
||
|
|
use App\Http\Controllers\Admin\ZarinController;
|
||
|
|
use App\Models\Order;
|
||
|
|
use App\Models\PargarSyncLog;
|
||
|
|
use App\Models\Tahesab;
|
||
|
|
use App\Models\Zarin;
|
||
|
|
use Illuminate\Support\Facades\Schema;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* سند حسابداری سمت همکار (Montzar) — جدا از سند مشتری.
|
||
|
|
* کد حساب از settings: montzar_account_{zarin|tahesab|pargar}
|
||
|
|
*/
|
||
|
|
class ColleagueAccountingService
|
||
|
|
{
|
||
|
|
public function __construct(
|
||
|
|
private ConfigService $config,
|
||
|
|
) {}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* بعد از پوشش سفارش روی همکار، سند را روی کد حساب همکار ثبت/صف میکند.
|
||
|
|
*
|
||
|
|
* @param array<string, mixed> $data
|
||
|
|
*/
|
||
|
|
public function recordCoveredTrade(array $data): void
|
||
|
|
{
|
||
|
|
if (! $this->config->usesMontzarPricing()) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
$order = $data['order'] ?? null;
|
||
|
|
if (! $order instanceof Order || ! $order->id) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (! $this->orderCoveredByColleague($order, $data)) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
$provider = $this->config->accountingProvider();
|
||
|
|
$accountCode = $this->colleagueAccountCode($provider);
|
||
|
|
if ($accountCode === null) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if ($this->alreadyQueued($order, $provider)) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
$payload = $this->buildColleaguePayload($data, $order, $accountCode);
|
||
|
|
|
||
|
|
try {
|
||
|
|
match ($provider) {
|
||
|
|
ConfigService::ACCOUNTING_ZARIN => app(ZarinController::class)->storeTrade($payload),
|
||
|
|
ConfigService::ACCOUNTING_TAHESAB => app(TahesabController::class)->storeTrade($payload),
|
||
|
|
ConfigService::ACCOUNTING_PARGAR => $this->queuePargarColleagueTrade($order, $payload, $accountCode),
|
||
|
|
default => null,
|
||
|
|
};
|
||
|
|
} catch (\Throwable $e) {
|
||
|
|
report($e);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public function colleagueAccountCode(string $provider): ?string
|
||
|
|
{
|
||
|
|
$key = match ($provider) {
|
||
|
|
ConfigService::ACCOUNTING_ZARIN => 'montzar_account_zarin',
|
||
|
|
ConfigService::ACCOUNTING_TAHESAB => 'montzar_account_tahesab',
|
||
|
|
ConfigService::ACCOUNTING_PARGAR => 'montzar_account_pargar',
|
||
|
|
default => null,
|
||
|
|
};
|
||
|
|
if ($key === null) {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
$code = trim($this->config->getString($key, ''));
|
||
|
|
if ($code === '' || in_array($code, ['0', '-1'], true)) {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
return $code;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param array<string, mixed> $data
|
||
|
|
*/
|
||
|
|
private function orderCoveredByColleague(Order $order, array $data): bool
|
||
|
|
{
|
||
|
|
if (Schema::hasColumn('orders', 'provider_id') && ! empty($order->provider_id)) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (! empty($data['provider_id'])) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
return Schema::hasColumn('orders', 'total_price_montzar')
|
||
|
|
&& $order->total_price_montzar !== null
|
||
|
|
&& (float) $order->total_price_montzar > 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
private function alreadyQueued(Order $order, string $provider): bool
|
||
|
|
{
|
||
|
|
return match ($provider) {
|
||
|
|
ConfigService::ACCOUNTING_ZARIN => Zarin::query()
|
||
|
|
->where('order_id', $order->id)
|
||
|
|
->where('desc', 'like', '%همکار%')
|
||
|
|
->exists(),
|
||
|
|
ConfigService::ACCOUNTING_TAHESAB => Tahesab::query()
|
||
|
|
->where('order_id', $order->id)
|
||
|
|
->where('desc', 'like', '%همکار%')
|
||
|
|
->exists(),
|
||
|
|
ConfigService::ACCOUNTING_PARGAR => PargarSyncLog::query()
|
||
|
|
->where('order_id', $order->id)
|
||
|
|
->where('data', 'like', '%"colleague_leg":true%')
|
||
|
|
->exists(),
|
||
|
|
default => true,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param array<string, mixed> $data
|
||
|
|
* @return array<string, mixed>
|
||
|
|
*/
|
||
|
|
private function buildColleaguePayload(array $data, Order $order, string $accountCode): array
|
||
|
|
{
|
||
|
|
$amount = abs((float) ($order->amount ?? $data['amount'] ?? 0));
|
||
|
|
$montzarUnit = Schema::hasColumn('orders', 'total_price_montzar')
|
||
|
|
? (float) ($order->total_price_montzar ?? 0)
|
||
|
|
: 0.0;
|
||
|
|
$price = $montzarUnit > 0
|
||
|
|
? $montzarUnit
|
||
|
|
: (float) ($order->price ?? $data['price'] ?? 0);
|
||
|
|
$total = $amount * $price;
|
||
|
|
$direction = (int) ($order->direction ?? $data['direction'] ?? 0);
|
||
|
|
$action = $direction === 1 ? 'خرید' : 'فروش';
|
||
|
|
$sharh = "{$action} از اپلیکیشن همکار";
|
||
|
|
|
||
|
|
$payload = $data;
|
||
|
|
$payload['order'] = $order;
|
||
|
|
$payload['customer_id'] = (int) ($order->customer_id ?? $data['customer_id'] ?? 0);
|
||
|
|
$payload['amount'] = $amount;
|
||
|
|
$payload['price'] = $price;
|
||
|
|
$payload['total_price'] = $total;
|
||
|
|
$payload['direction'] = $direction;
|
||
|
|
$payload['product_id'] = $order->product_id ?? ($data['product_id'] ?? null);
|
||
|
|
$payload['accounting_account_code'] = $accountCode;
|
||
|
|
$payload['colleague_leg'] = true;
|
||
|
|
$payload['sharh_override'] = $sharh;
|
||
|
|
$payload['pay_at'] = $order->pay_at ?? $order->created_at ?? ($data['pay_at'] ?? now());
|
||
|
|
|
||
|
|
return $payload;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param array<string, mixed> $payload
|
||
|
|
*/
|
||
|
|
private function queuePargarColleagueTrade(Order $order, array $payload, string $accountCode): void
|
||
|
|
{
|
||
|
|
if (! $this->config->isPargarAccounting()) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
$direction = (int) ($payload['direction'] ?? 0);
|
||
|
|
$desc = (string) ($payload['sharh_override'] ?? 'معامله با اپلیکیشن همکار');
|
||
|
|
|
||
|
|
PargarSyncLog::create([
|
||
|
|
'customer_id' => $order->customer_id,
|
||
|
|
'amount' => $payload['amount'] ?? $order->amount,
|
||
|
|
'desc' => $desc,
|
||
|
|
'order_id' => $order->id,
|
||
|
|
'date' => $order->pay_at ?? $order->created_at,
|
||
|
|
'type' => PargarSyncService::TYPE_ORDER,
|
||
|
|
'sync_status' => PargarSyncService::STATUS_PENDING,
|
||
|
|
'data' => json_encode([
|
||
|
|
'handler' => 'exportColleagueOrder',
|
||
|
|
'colleague_leg' => true,
|
||
|
|
'colleague_account_id' => $accountCode,
|
||
|
|
'direction' => $direction,
|
||
|
|
'price' => $payload['price'] ?? $order->price,
|
||
|
|
'total_price' => $payload['total_price'] ?? $order->total_price,
|
||
|
|
'payment_kind' => PargarSyncService::PAYMENT_CASH,
|
||
|
|
'product_id' => $order->product_id,
|
||
|
|
'from_cart' => false,
|
||
|
|
], JSON_UNESCAPED_UNICODE),
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
}
|