2026-01-24 14:03:11 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace App\Http\Controllers\Admin;
|
|
|
|
|
|
|
|
|
|
use App\Http\Controllers\Controller;
|
|
|
|
|
use App\Http\Controllers\SuperController;
|
2026-05-25 20:55:05 +03:30
|
|
|
use App\Models\Cnt;
|
2026-01-24 14:03:11 +00:00
|
|
|
use App\Models\Product;
|
2026-06-02 11:18:05 +03:30
|
|
|
use App\Models\Setting;
|
2026-01-24 14:03:11 +00:00
|
|
|
use App\DB\Te\TableEngine;
|
|
|
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
|
use Illuminate\Http\Request;
|
|
|
|
|
use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
|
|
|
|
|
use Illuminate\Support\Facades\Http;
|
|
|
|
|
use \App\Http\Controllers\Customer\FundController;
|
2026-06-01 18:46:57 +03:30
|
|
|
use App\Http\Controllers\Site\ReportController;
|
|
|
|
|
use App\Services\ConfigService;
|
2026-06-02 16:00:33 +03:30
|
|
|
use App\Services\ProductPriceService;
|
2026-05-25 20:55:05 +03:30
|
|
|
|
2026-01-24 14:03:11 +00:00
|
|
|
|
|
|
|
|
class ProductController extends SuperController
|
|
|
|
|
{
|
|
|
|
|
public function __construct()
|
|
|
|
|
{
|
2026-05-17 16:39:53 +00:00
|
|
|
$this->with = ['file'/*, 'price', 'default', 'sub'*/];
|
2026-05-25 20:55:05 +03:30
|
|
|
// $this->with = [];
|
2026-01-24 14:03:11 +00:00
|
|
|
parent::__construct(Product::class, $this->with, ['*'], null, null, ['title']);
|
|
|
|
|
}
|
|
|
|
|
public function tableProduct(Request $request)
|
|
|
|
|
{
|
|
|
|
|
$data = $request->all();
|
2026-05-25 20:55:05 +03:30
|
|
|
if (isset($data["select"]) && is_null($data["select"])){
|
2026-01-24 14:03:11 +00:00
|
|
|
$data["select"] = [];
|
|
|
|
|
}
|
2026-05-25 20:55:05 +03:30
|
|
|
if (is_null($this->query)){
|
2026-01-24 14:03:11 +00:00
|
|
|
$query_table = $this->model::with($this->with);
|
|
|
|
|
//*******کداضافه شده
|
|
|
|
|
// ->where('active', '<=', now()) // فیلتر محصولات فعال
|
|
|
|
|
// ->get();
|
|
|
|
|
//*********
|
2026-05-25 20:55:05 +03:30
|
|
|
}else{
|
2026-01-24 14:03:11 +00:00
|
|
|
$query_table = $this->query;
|
|
|
|
|
// $query_table = $query_table->where('active', '<=', now());
|
|
|
|
|
}
|
|
|
|
|
TableEngine::create($query_table, $data)
|
|
|
|
|
->initSearch($this->search)
|
|
|
|
|
->select($this->select)
|
|
|
|
|
->export($query_table);
|
|
|
|
|
$query_table['auto_open_at'] = Product::selectRaw(
|
|
|
|
|
'SEC_TO_TIME(AVG(TIME_TO_SEC(TIME(auto_open_at)))) as avg_time'
|
2026-05-25 20:55:05 +03:30
|
|
|
)->value('avg_time'); $query_table['auto_close_at'] = Product::selectRaw(
|
|
|
|
|
'SEC_TO_TIME(AVG(TIME_TO_SEC(TIME(auto_close_at)))) as avg_time'
|
|
|
|
|
)->value('avg_time');
|
2026-01-24 14:03:11 +00:00
|
|
|
|
|
|
|
|
// $query_table['11'] = $avgDuration;
|
|
|
|
|
// $query_table['11'] = Product::avg('auto_open_at');
|
|
|
|
|
// $query_table['112'] = Product::avg('auto_close_at');
|
|
|
|
|
return $query_table;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function editProducts(Request $request)
|
|
|
|
|
{
|
|
|
|
|
if (isset($request->auto_open_at, $request->auto_close_at)) {
|
|
|
|
|
Product::query()->update([
|
|
|
|
|
'auto_open_at' => $request->auto_open_at,
|
|
|
|
|
'auto_close_at' => $request->auto_close_at,
|
|
|
|
|
]);
|
|
|
|
|
return response()->json(['message' => 'Products updated successfully.']);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return response()->json(['error' => 'auto_open_at and auto_close_at must be set'], 400);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function store(Request $request)
|
|
|
|
|
{
|
2026-06-02 16:00:33 +03:30
|
|
|
$data = $this->filterProductData($request->all());
|
2026-01-24 14:03:11 +00:00
|
|
|
|
|
|
|
|
$product = Product::create($data);
|
|
|
|
|
return $this->resultCreate($product->id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function update(Request $request, $id)
|
|
|
|
|
{
|
|
|
|
|
// return 1;
|
|
|
|
|
|
2026-06-02 16:00:33 +03:30
|
|
|
$data = $this->filterProductData($request->all());
|
2026-05-25 20:55:05 +03:30
|
|
|
if (isset($data["price"])){
|
2026-05-25 19:42:48 +03:30
|
|
|
$data["reading_method"] = null;
|
2026-06-02 16:00:33 +03:30
|
|
|
if (Product::hasPriceOffsetColumn()) {
|
|
|
|
|
$data['price_offset_percent'] = 0;
|
|
|
|
|
}
|
2026-05-25 19:42:48 +03:30
|
|
|
}
|
2026-05-25 20:55:05 +03:30
|
|
|
if (isset($data["auto_close_at"]) and isset($data["auto_close_at"])){
|
|
|
|
|
if ($data["auto_close_at"] == $data["auto_open_at"]){
|
|
|
|
|
unset($data["auto_open_at"]);
|
|
|
|
|
unset($data["auto_close_at"]);
|
2026-05-25 19:42:48 +03:30
|
|
|
}
|
|
|
|
|
}
|
2026-01-24 14:03:11 +00:00
|
|
|
|
|
|
|
|
// return $data['price'];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if(!isset($data['default'])){
|
|
|
|
|
// throw new UnprocessableEntityHttpException('مقادیر اعتبارات را وارد کنید');
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// $data['auto_open_at'] = Carbon::parse($data['auto_open_at'])->format('Y-m-d H:i:s');
|
|
|
|
|
// $data['auto_close_at'] = Carbon::parse($data['auto_close_at'])->format('Y-m-d H:i:s');
|
2026-06-02 16:00:33 +03:30
|
|
|
$product = Product::findOrFail($id);
|
|
|
|
|
$oldOffsetPercent = (float) ($product->price_offset_percent ?? 0);
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
Product::hasPriceOffsetColumn()
|
|
|
|
|
&& $product->reading_method
|
|
|
|
|
&& array_key_exists('price_offset_percent', $data)
|
|
|
|
|
) {
|
|
|
|
|
ProductPriceService::reapplyOffsetPercent(
|
|
|
|
|
$product,
|
|
|
|
|
(float) $data['price_offset_percent'],
|
|
|
|
|
$oldOffsetPercent
|
|
|
|
|
);
|
|
|
|
|
unset($data['price'], $data['price_profit']);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$product->update($data);
|
2026-01-24 14:03:11 +00:00
|
|
|
|
|
|
|
|
return response()->json(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function destroy($id)
|
|
|
|
|
{
|
|
|
|
|
Product::findOrFail($id)->delete();
|
|
|
|
|
return response()->json(true);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function listProduct()
|
|
|
|
|
{
|
2026-05-25 20:55:05 +03:30
|
|
|
// $this->getPrice();
|
|
|
|
|
// $this->auto_close_open();
|
2026-06-02 16:00:33 +03:30
|
|
|
$products = Product::with(['file'])->where('active', 1)->get();
|
|
|
|
|
|
|
|
|
|
if (Product::hasPriceOffsetColumn() && str_contains(request()->path(), '/customer/')) {
|
|
|
|
|
$products->each->makeHidden(['price_offset_percent']);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return response()->json($products);
|
2026-01-24 14:03:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function getPrice()
|
|
|
|
|
{
|
2026-05-25 20:55:05 +03:30
|
|
|
// $RPrices =Http::timeout(40)->get('http://212.23.201.173:8381/price_list', [])->json();
|
|
|
|
|
$RPrices = Http::timeout(40)->get('http://109.122.246.48:4949/api/free', [])->json();
|
2026-03-31 18:28:27 +03:30
|
|
|
|
2026-05-25 20:55:05 +03:30
|
|
|
// try{
|
|
|
|
|
// $cooper =Http::timeout(40)->get('https://www.livedata.ir/main/static/p.json', [])->json();
|
|
|
|
|
// if(isset($cooper['s_301006']) && isset($cooper['s_200103'])){
|
|
|
|
|
// $CP = (($cooper['s_301006']/1000000)*$cooper['s_200103'])*10;
|
|
|
|
|
//// Cnt::where('key', 'cu_price')
|
|
|
|
|
// }
|
|
|
|
|
// }catch (\Exception $e){}
|
2026-05-25 19:42:48 +03:30
|
|
|
|
2026-06-01 18:46:57 +03:30
|
|
|
$config = app(ConfigService::class);
|
2026-06-02 11:18:05 +03:30
|
|
|
$mainProductId = Cnt::where('key', 'main_product')->value('value');
|
|
|
|
|
$hasExtremeKeys = Setting::whereIn('key', ['up_price', 'down_price'])->count() === 2;
|
2026-05-25 19:42:48 +03:30
|
|
|
$products = Product::with([])->whereNotNull('reading_method')->get();
|
|
|
|
|
foreach ($products as $product) {
|
2026-05-25 20:55:05 +03:30
|
|
|
$collection = collect($RPrices);
|
|
|
|
|
$RPrice = $collection->firstWhere('key', $product->reading_method);
|
|
|
|
|
if (!empty($RPrice)) {
|
|
|
|
|
// foreach ($RPrices as $RPrice) {
|
|
|
|
|
// if ($product->reading_method == $RPrice['name']) {
|
|
|
|
|
if ($RPrice['name'] == 'TGJU فلز مس') {
|
|
|
|
|
$copper = $RPrice['price'] + $RPrice['profit'];
|
|
|
|
|
}
|
|
|
|
|
if ($RPrice['name'] == 'TGJU دلار') {
|
|
|
|
|
$dollar = $RPrice['price'] + $RPrice['profit'];
|
|
|
|
|
}
|
|
|
|
|
if ($RPrice['name'] == 'گلد دات ای از آبشده - رسمی - نقد فردا') {
|
|
|
|
|
$RPrice['price'] = $RPrice['price'] / 4.3318;
|
|
|
|
|
}
|
2026-06-02 16:00:33 +03:30
|
|
|
ProductPriceService::syncFromReference(
|
|
|
|
|
$product,
|
|
|
|
|
(int) $RPrice['price'],
|
|
|
|
|
(int) ($RPrice['profit'] ?? 0)
|
|
|
|
|
);
|
|
|
|
|
$productPrice = (float) ProductPriceService::adjustedTotal(
|
|
|
|
|
(int) $RPrice['price'],
|
|
|
|
|
(int) ($RPrice['profit'] ?? 0),
|
|
|
|
|
ProductPriceService::offsetPercent($product)
|
|
|
|
|
);
|
2026-06-02 11:18:05 +03:30
|
|
|
if (
|
|
|
|
|
$hasExtremeKeys
|
|
|
|
|
&& $mainProductId
|
|
|
|
|
&& (int) $product->id === (int) $mainProductId
|
|
|
|
|
) {
|
|
|
|
|
$config->trackDailyPriceExtreme($productPrice);
|
|
|
|
|
}
|
2026-05-25 19:42:48 +03:30
|
|
|
|
2026-05-25 20:55:05 +03:30
|
|
|
if ($product->bubble == 1) {
|
|
|
|
|
$ReportController = new ReportController();
|
|
|
|
|
$liquidGold = $ReportController->lastPrice();
|
2026-05-25 19:42:48 +03:30
|
|
|
$p = Product::find($product->id);
|
2026-05-25 20:55:05 +03:30
|
|
|
$p->amount = $RPrice['price'] / $liquidGold['price'];
|
2026-05-25 19:42:48 +03:30
|
|
|
$p->save();
|
2026-05-25 20:55:05 +03:30
|
|
|
|
2026-05-25 19:42:48 +03:30
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-05-25 20:55:05 +03:30
|
|
|
if (isset($copper) && isset($dollar)) {
|
2026-06-02 16:00:33 +03:30
|
|
|
$cp = (int) round(($copper / 1000000) * $dollar);
|
|
|
|
|
$copperProducts = Product::where('metal_id', 3)->get();
|
|
|
|
|
foreach ($copperProducts as $copperProduct) {
|
|
|
|
|
ProductPriceService::syncFromReference($copperProduct, $cp, 0);
|
|
|
|
|
}
|
|
|
|
|
Product::where('metal_id', 3)->update([
|
2026-05-25 20:55:05 +03:30
|
|
|
'updated_at' => \Carbon\Carbon::now()->format('Y-m-d H:i:s'),
|
2026-05-25 19:42:48 +03:30
|
|
|
]);
|
2026-06-02 11:18:05 +03:30
|
|
|
if (
|
|
|
|
|
$hasExtremeKeys
|
|
|
|
|
&& $mainProductId
|
|
|
|
|
&& Product::where('id', $mainProductId)->where('metal_id', 3)->exists()
|
|
|
|
|
) {
|
2026-06-02 16:00:33 +03:30
|
|
|
$mainCopper = Product::find($mainProductId);
|
|
|
|
|
$extremePrice = $mainCopper
|
|
|
|
|
? (float) ($mainCopper->price + ($mainCopper->price_profit ?? 0))
|
|
|
|
|
: (float) $cp;
|
|
|
|
|
$config->trackDailyPriceExtreme($extremePrice);
|
2026-06-02 11:18:05 +03:30
|
|
|
}
|
2026-05-25 19:42:48 +03:30
|
|
|
}
|
|
|
|
|
|
2026-05-25 20:55:05 +03:30
|
|
|
return response()->json(true);
|
2026-05-25 19:42:48 +03:30
|
|
|
}
|
|
|
|
|
|
2026-01-24 14:03:11 +00:00
|
|
|
public function auto_close_open()
|
|
|
|
|
{
|
|
|
|
|
$products = Product::with([])->get();
|
|
|
|
|
$current_time = now()->format('H:i:s');
|
|
|
|
|
foreach ($products as $product) {
|
|
|
|
|
$show = ($current_time >= $product->auto_open_at && $current_time <= $product->auto_close_at);
|
|
|
|
|
Product::where('id', $product->id)->update([
|
|
|
|
|
'show' => $show,
|
|
|
|
|
]);
|
|
|
|
|
}
|
2026-05-25 20:55:05 +03:30
|
|
|
return response()->json(true);
|
2026-01-24 14:03:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function getProduct($id)
|
|
|
|
|
{
|
|
|
|
|
$product = Product::with($this->with)->where('id', $id)->first();
|
|
|
|
|
return response()->json($product);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param $id
|
|
|
|
|
* @return \Illuminate\Http\JsonResponse
|
|
|
|
|
*/
|
|
|
|
|
public function hide($id)
|
|
|
|
|
{
|
|
|
|
|
$query = Product::findOrFail($id);
|
|
|
|
|
$query->update([
|
|
|
|
|
'show' => !$query->show
|
|
|
|
|
]);
|
|
|
|
|
return response()->json(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function openSell($id)
|
|
|
|
|
{
|
|
|
|
|
return $this->toggleBooleanStatus($id, 'open_sell');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function openBuy($id)
|
|
|
|
|
{
|
|
|
|
|
return $this->toggleBooleanStatus($id, 'open_buy');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function auto_buy($id)
|
|
|
|
|
{
|
|
|
|
|
return $this->toggleBooleanStatus($id, 'auto_buy');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function auto_sell($id)
|
|
|
|
|
{
|
|
|
|
|
return $this->toggleBooleanStatus($id, 'auto_sell');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function toggleBooleanStatus($id, $field)
|
|
|
|
|
{
|
|
|
|
|
$product = Product::findOrFail($id);
|
|
|
|
|
$product->$field = !$product->$field;
|
|
|
|
|
$product->save();
|
|
|
|
|
if (!$product->open_buy and !$product->open_sell) {
|
|
|
|
|
$product->show = false;
|
|
|
|
|
$product->active = false;
|
|
|
|
|
} else {
|
|
|
|
|
$product->show = true;
|
|
|
|
|
$product->active = true;
|
|
|
|
|
}
|
|
|
|
|
$product->save();
|
|
|
|
|
return response()->json($product->$field);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function auto_group($action, $method)
|
|
|
|
|
{
|
|
|
|
|
// Define valid actions and methods
|
|
|
|
|
$validActions = ['sell' => 'auto_sell', 'buy' => 'auto_buy', 'all' => ['auto_buy', 'auto_sell']];
|
|
|
|
|
$validMethods = ['true' => 1, 'false' => 0];
|
|
|
|
|
// Validate action and method
|
|
|
|
|
if (!isset($validActions[$action]) || !array_key_exists($method, $validMethods)) {
|
|
|
|
|
return response()->json(['error' => 'Invalid action or method'], 400);
|
|
|
|
|
}
|
|
|
|
|
// Get fields to update and value to set
|
|
|
|
|
$fields = $validActions[$action];
|
|
|
|
|
$value = $validMethods[$method];
|
|
|
|
|
// Update products
|
|
|
|
|
Product::query()->update(array_fill_keys((array)$fields, $value));
|
|
|
|
|
return response()->json(true);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-25 20:55:05 +03:30
|
|
|
public function updatePrice(Request $request){
|
|
|
|
|
|
2026-01-24 14:03:11 +00:00
|
|
|
|
|
|
|
|
}
|
2026-06-02 16:00:33 +03:30
|
|
|
|
|
|
|
|
private function filterProductData(array $data): array
|
|
|
|
|
{
|
|
|
|
|
if (!Product::hasPriceOffsetColumn()) {
|
|
|
|
|
unset($data['price_offset_percent']);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $data;
|
|
|
|
|
}
|
2026-01-24 14:03:11 +00:00
|
|
|
}
|