372 lines
15 KiB
PHP
372 lines
15 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Finance;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Http\Controllers\Admin\TahesabController;
|
|
use App\Models\Customer;
|
|
use App\Models\Order;
|
|
use App\Models\Price;
|
|
use App\Models\Product;
|
|
use App\Models\TransactionsAdmin;
|
|
use App\Models\User;
|
|
use App\Models\Withdraw;
|
|
use App\Models\Tahesab;
|
|
use App\Services\TahesabSyncService;
|
|
use App\DB\Te\TableEngine;
|
|
use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
|
|
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Rooyesh\Wallet\interfaces\TransactionInterface;
|
|
use Rooyesh\Wallet\interfaces\WalletInterface;
|
|
use Rooyesh\Wallet\models\Wallet;
|
|
|
|
class FinanceController extends Controller
|
|
{
|
|
public function fall(Request $request)
|
|
{
|
|
$transactions_admins = TransactionsAdmin::with(['withdraw','order',"user",'customerTo','customer']);
|
|
TableEngine::create($transactions_admins, $request)
|
|
->initSearch(['price'])
|
|
->select(['*'])
|
|
->export($transactions_admins);
|
|
|
|
if (isset($transactions_admins['rows']) && is_array($transactions_admins['rows']) && $this->Config('send_to_tahesab') === 'true') {
|
|
$this->enrichRowsWithTahesab($transactions_admins['rows']);
|
|
}
|
|
|
|
return response()->json($transactions_admins);
|
|
}
|
|
|
|
/**
|
|
* هر ردیف دفترکل را با وضعیت سند تهحساب مرتبط غنی میکند.
|
|
* لینک: ابتدا از طریق withdraw_id (کیفپول/پاداش) و سپس order_id (معامله).
|
|
*
|
|
* @param array<int, array<string, mixed>> $rows با ارجاع تغییر میکند
|
|
*/
|
|
private function enrichRowsWithTahesab(array &$rows): void
|
|
{
|
|
$withdrawIds = collect($rows)->pluck('withdraw_id')->filter()->unique()->values()->all();
|
|
$orderIds = collect($rows)->pluck('order_id')->filter()->unique()->values()->all();
|
|
|
|
if ($withdrawIds === [] && $orderIds === []) {
|
|
return;
|
|
}
|
|
|
|
$tahesabByWithdraw = $withdrawIds === []
|
|
? collect()
|
|
: Tahesab::query()->whereIn('withdraw_id', $withdrawIds)
|
|
->orderByDesc('id')->get()->unique('withdraw_id')->keyBy('withdraw_id');
|
|
|
|
$tahesabByOrder = $orderIds === []
|
|
? collect()
|
|
: Tahesab::query()->whereIn('order_id', $orderIds)
|
|
->orderByDesc('id')->get()->unique('order_id')->keyBy('order_id');
|
|
|
|
foreach ($rows as &$row) {
|
|
$tahesab = $tahesabByWithdraw->get($row['withdraw_id'] ?? null)
|
|
?? $tahesabByOrder->get($row['order_id'] ?? null);
|
|
|
|
if (! $tahesab) {
|
|
// ردیف دفترکل بدون سند تهحساب — یعنی هنوز به حسابداری ارسال نشده
|
|
$row['tahesab_record_id'] = null;
|
|
$row['tahesab_sync_status'] = TahesabSyncService::STATUS_PENDING;
|
|
$row['tahesab_failed_id'] = null;
|
|
continue;
|
|
}
|
|
|
|
$row['tahesab_record_id'] = $tahesab->id;
|
|
$row['tahesab_sync_status'] = $tahesab->sync_status
|
|
?? (empty($tahesab->tahesab_id) ? TahesabSyncService::STATUS_PENDING : TahesabSyncService::STATUS_SUCCESS);
|
|
|
|
if (empty($tahesab->tahesab_id) || $row['tahesab_sync_status'] === TahesabSyncService::STATUS_FAILED) {
|
|
$row['tahesab_failed_id'] = $tahesab->id;
|
|
}
|
|
}
|
|
unset($row);
|
|
}
|
|
|
|
/**
|
|
* سینک یک ردیف دفترکل با حسابداری (فعلاً تهحساب).
|
|
* اگر سند تهحساب مرتبط موجود باشد → retry؛ وگرنه از روی منبع (معامله) ساخته و ارسال میشود.
|
|
*/
|
|
public function sync(int $id)
|
|
{
|
|
if ($this->Config('send_to_tahesab') !== 'true') {
|
|
throw new UnprocessableEntityHttpException('حسابداری تهحساب فعال نیست');
|
|
}
|
|
|
|
$row = TransactionsAdmin::find($id);
|
|
if (! $row) {
|
|
throw new UnprocessableEntityHttpException('سند دفترکل یافت نشد');
|
|
}
|
|
|
|
$tahesab = $this->findLinkedTahesab($row);
|
|
|
|
if ($tahesab) {
|
|
$result = app(TahesabSyncService::class)->retry($tahesab);
|
|
$status = ($result['ok'] ?? false) ? 200 : 422;
|
|
|
|
return response()->json($result, $status);
|
|
}
|
|
|
|
// سند تهحساب وجود ندارد — اگر معامله است، از روی سفارش بساز و ارسال کن
|
|
if ($row->order_id) {
|
|
return $this->syncTradeFromOrder((int) $row->order_id);
|
|
}
|
|
|
|
throw new UnprocessableEntityHttpException(
|
|
'برای این ردیف سند تهحسابی یافت نشد و امکان ساخت خودکار آن وجود ندارد'
|
|
);
|
|
}
|
|
|
|
private function findLinkedTahesab(TransactionsAdmin $row): ?Tahesab
|
|
{
|
|
if ($row->withdraw_id) {
|
|
$byWithdraw = Tahesab::where('withdraw_id', $row->withdraw_id)->orderByDesc('id')->first();
|
|
if ($byWithdraw) {
|
|
return $byWithdraw;
|
|
}
|
|
}
|
|
|
|
if ($row->order_id) {
|
|
return Tahesab::where('order_id', $row->order_id)->orderByDesc('id')->first();
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private function syncTradeFromOrder(int $orderId)
|
|
{
|
|
$order = Order::find($orderId);
|
|
if (! $order) {
|
|
throw new UnprocessableEntityHttpException('سفارش مرتبط یافت نشد');
|
|
}
|
|
|
|
$product = Product::find($order->product_id);
|
|
if (! $product) {
|
|
throw new UnprocessableEntityHttpException('محصول سفارش یافت نشد — امکان ساخت سند تهحساب نیست');
|
|
}
|
|
|
|
$data = [
|
|
'customer_id' => $order->customer_id,
|
|
'direction' => (int) $order->direction,
|
|
'price' => $order->price,
|
|
'total_price' => $order->total_price,
|
|
'amount' => $order->amount,
|
|
'pay_at' => $order->pay_at ?? $order->created_at,
|
|
'product' => $product,
|
|
'order' => ['id' => $order->id],
|
|
];
|
|
|
|
$result = app(TahesabController::class)->storeTrade($data);
|
|
$ok = $result !== false && ! is_string($result);
|
|
|
|
return response()->json([
|
|
'ok' => $ok,
|
|
'message' => $ok ? 'سند معامله در تهحساب ثبت شد' : (is_string($result) ? $result : 'ارسال به تهحساب ناموفق بود'),
|
|
], $ok ? 200 : 422);
|
|
}
|
|
|
|
public function index()
|
|
{
|
|
$tallaPrice = Price::latest()->first();
|
|
// $talla->update_date = Verta::instance(Carbon::parse($talla->updated_at))->format('Y/n/j-H:i');
|
|
$new_customer_major = Customer::where('type',1)->whereDate('created_at','<=',now())->whereDate('created_at','>=',now()->subMonths(3))
|
|
->count();
|
|
$new_customer_single = Customer::where('type',2)->whereDate('created_at','<=',now())->whereDate('created_at','>=',now()->subMonths(3))
|
|
->count();
|
|
$all_customer_major = Customer::where('type',1)->count();
|
|
$all_customer_single = Customer::where('type',2)->count();
|
|
$archive_customer_major = Customer::where('type',1)->where('is_archive',true)->count();
|
|
$archive_customer_single = Customer::where('type',2)->where('is_archive',true)->count();
|
|
$all_gold = Order::where('direction',2)->where('type',1)->sum('amount');// جمع طلاهایی که از مشتری خریدیم
|
|
$all_gold_single = Order::where('direction',2)->where('type',2)->sum('amount');// جمع طلاهایی که از مشتری خریدیم
|
|
$await_list = Order::where('direction',1)->where('sts',1)->get();
|
|
$best_customer_major=Order::with('customer')->where('type',1)->where('sts',2)->select('customer_id',DB::raw('sum(amount) as amount'))
|
|
->groupBy('customer_id')->limit(10)->get();
|
|
$best_customer_single=Wallet::with('customer')->whereNull('fund_id')->where('owner_type',2)->orderBy('gold','desc')->limit(10)->get();
|
|
|
|
|
|
// GT
|
|
$GT_all_customers = Customer::where('type',2)->where('is_archive',false)->count();
|
|
$GT_no_login_customers = Customer::where('type',2)->where('is_archive',false)->where('last_seen_at',null)->count();
|
|
$GT_no_valid_customers = Customer::where('type',2)->where('is_archive',false)->where('is_legal',0)->count();
|
|
$GT_no_valid_customers_data = Customer::where('type',2)->where('is_archive',false)->where('is_legal',0)->get(['id','name','mobile']);
|
|
$GT_active_customers = Customer::where('type', 2)
|
|
->where('is_archive', false)
|
|
->whereIn('id', function($query) {
|
|
$query->select('owner')
|
|
->from('wallets');
|
|
})->count();
|
|
$GT_active_customers_data = Customer::where('type', 2)
|
|
->where('is_archive', false)
|
|
->whereIn('id', function($query) {
|
|
$query->select('owner')
|
|
->from('wallets');
|
|
})->get(['id','name','mobile']);
|
|
|
|
$transactions_admins = TransactionsAdmin::with(['withdraw','order',"user",'customerTo','customer'])->get();
|
|
|
|
return view('app', compact(
|
|
'GT_all_customers',
|
|
'GT_no_login_customers',
|
|
'GT_no_valid_customers',
|
|
'GT_no_valid_customers_data',
|
|
'GT_active_customers',
|
|
'GT_active_customers_data',
|
|
'transactions_admins',
|
|
'tallaPrice',
|
|
'new_customer_major',
|
|
'new_customer_single',
|
|
'all_customer_major',
|
|
'all_customer_single',
|
|
'archive_customer_major',
|
|
'archive_customer_single',
|
|
'all_gold',
|
|
'all_gold_single',
|
|
'await_list',
|
|
'best_customer_major',
|
|
'best_customer_single'
|
|
))->with('GT_deActive_customers', $GT_all_customers - $GT_active_customers)
|
|
->with('price', $tallaPrice->price);
|
|
|
|
|
|
}
|
|
public function startTransation(Request $request)
|
|
{
|
|
|
|
$user = auth()->user();
|
|
// riyal to tomman
|
|
$tomman = $request->value;
|
|
$riyal = (int)($request->value / 10);
|
|
$riyal .= 0;
|
|
$request->value = (int)($request->value / 10);
|
|
|
|
$Withdraw = Withdraw::create([
|
|
'customer_id' => auth('customer')->id(),
|
|
"cash" => $riyal,
|
|
'sts' => 1,
|
|
]);
|
|
|
|
$url = 'https://zify.ir/api/order/v2/create';
|
|
|
|
$payload = [
|
|
"payer" => [
|
|
"first_name" => $user->fname,
|
|
"last_name" => $user->lname,
|
|
"phone" => $user->mobile,
|
|
"email" => "",
|
|
"state" => $user->city,
|
|
"city" => $user->province,
|
|
"address_1" => $user->id,
|
|
"address_2" => $user->shop_name
|
|
],
|
|
"products" => [
|
|
[
|
|
"code" => "1",
|
|
"sellQuantity" => 1,
|
|
"title" => "IRR",
|
|
"amount" => $request->value,
|
|
"unlimited" => true,
|
|
"quantity" => $request->value,
|
|
"description" => "charge_account"
|
|
]
|
|
],
|
|
"returnUrl" => "https://api.gholaktala.ir/customer/charge_account_verify",
|
|
"clientRefId" => "$Withdraw->id",
|
|
"shipping_total" => 0,
|
|
"off_total" => 0,
|
|
"tax_total" => 0
|
|
];
|
|
|
|
$response = Http::withToken(env('ZIFI_TOKEN_GHOLAKTALLA'))
|
|
->post($url, $payload);
|
|
if ($response->successful()) {
|
|
$responseData = $response->json();
|
|
|
|
$orderCode = $responseData['data']['order'] ?? null;
|
|
if ($orderCode) {
|
|
$Withdraw->tracked_number = $orderCode;
|
|
$Withdraw->save();
|
|
return "https://zify.ir/order/accept/{$orderCode}";
|
|
} else {
|
|
return response()->json([
|
|
'message' => 'Order created successfully but order code is missing',
|
|
'data' => $responseData
|
|
]);
|
|
}
|
|
} else {
|
|
$response = $response->json();
|
|
return response()->json([$response][0], 422);
|
|
}
|
|
}
|
|
|
|
public function verifyTransation()
|
|
{
|
|
|
|
$Withdraw = Withdraw::with('customer')->where('id', $_GET['clientrefid'])->first();
|
|
|
|
$User = Customer::where('id', $Withdraw->customer_id)->first();
|
|
$url = 'https://zify.ir/api/order/v2/verify';
|
|
$payload = [
|
|
"order" => "$Withdraw->tracked_number",
|
|
];
|
|
$verifyResponse = Http::withToken(env('ZIFI_TOKEN_GHOLAKTALLA'))
|
|
->post($url, $payload);
|
|
$decodedResponse = json_decode($verifyResponse, true);
|
|
$verifyMessage = $decodedResponse['message'];
|
|
// return $decodedResponse['data'];
|
|
|
|
if (isset($decodedResponse['data']['refid']) || $verifyMessage == []) {
|
|
if ($Withdraw->cash == $decodedResponse['data']['amount'] * 10) {
|
|
$Withdraw->zify_code = $Withdraw->tracked_number;//ok
|
|
$Withdraw->tracked_number = $decodedResponse['data']['refid'];//ok
|
|
$Withdraw->sts = 2;//ok
|
|
$Withdraw->save();
|
|
|
|
$wallet_interface_fund = new WalletInterface($User->id, $User->type);
|
|
$transaction = new TransactionInterface($wallet_interface_fund, $_inp = [
|
|
"cash" => $decodedResponse['data']['amount'] * 10,
|
|
'expire_at' => now(),
|
|
'withdraw_id' => $_GET['clientrefid'],
|
|
'active' => true
|
|
], 3, false, true);
|
|
|
|
//----------sms
|
|
// User information
|
|
$userMobile = $Withdraw->customer->mobile; // User's mobile number
|
|
$userName = $Withdraw->customer->name; // User's name
|
|
$chargedAmount = $Withdraw->cash; // Charged amount
|
|
// Company name
|
|
$companyName = $this->Config('name_fa'); // Company name from configuration
|
|
|
|
// Constructing the SMS message
|
|
$message = "کاربر $userName با شماره موبایل $userMobile حساب خود را به مقدار " . number_format($chargedAmount) . " ریال شارژ کرد. با تشکر، $companyName";
|
|
|
|
// Getting admin mobile numbers and sending the SMS
|
|
User::where('active', 1)->get()->each(function($admin) use ($message) {
|
|
$this->Send($admin->mobile, $message);
|
|
});
|
|
|
|
|
|
|
|
return view('showTransactionReport', compact('Withdraw'));
|
|
return redirect('https://app.gholaktala.ir/transactions');
|
|
|
|
}
|
|
return "مبلغ پرداختی دستکاری شده !";
|
|
} else {
|
|
|
|
$Withdraw->tracked_number;
|
|
$Withdraw->sts = 3;//no
|
|
$Withdraw->save();
|
|
return view('showTransactionReport', compact('Withdraw'));
|
|
}
|
|
|
|
|
|
}
|
|
}
|