fix profit value after each order 2
This commit is contained in:
@@ -17,6 +17,7 @@ class OrderController extends Controller
|
||||
|
||||
$records = Order::with([
|
||||
'customer',
|
||||
'product:id,title,unit,metal_id,group_type,amount,trade_by_quantity,direct_price',
|
||||
'transactions.product:id,title,unit,metal_id,group_type,amount,trade_by_quantity,direct_price',
|
||||
]);
|
||||
TableEngine::create($records, $request->all())
|
||||
@@ -43,6 +44,7 @@ class OrderController extends Controller
|
||||
|
||||
$records = Order::with([
|
||||
'customer',
|
||||
'product:id,title,unit,metal_id,group_type,amount,trade_by_quantity,direct_price',
|
||||
'transactions.product:id,title,unit,metal_id,group_type,amount,trade_by_quantity,direct_price',
|
||||
])->where('type',2);
|
||||
TableEngine::create($records, $request->all())
|
||||
|
||||
@@ -118,9 +118,9 @@ class SingleOrderController extends Controller
|
||||
if ($data['direction'] == 1) {
|
||||
|
||||
$data['service_charge_percentage'] = isset($data['fee_free']) && $data['fee_free'] === true ? 0 : ($data['product']['percent_fee_buy']) * $data['number'];
|
||||
$data['difference'] = $data['fee'] = $this->resolveCashPriceDiff($config, $data['product'], 1);
|
||||
$data['total_fee'] = $data['number'] * $data['fee'];
|
||||
$data['price_original'] = $this->resolveProductUnitBasePrice($data['product']);
|
||||
$this->applyCashPriceDiff($config, $data['product'], 1, $data, (float) $data['price_original']);
|
||||
$data['total_fee'] = $data['number'] * $data['fee'];
|
||||
$data['total_price_original'] = $data['product']['amount'] * ($data['price_original'] ?? 0);
|
||||
|
||||
// Check if the method is cash
|
||||
@@ -136,9 +136,9 @@ class SingleOrderController extends Controller
|
||||
} // Check if the user wants to sell
|
||||
else if ($data['direction'] == 2) {
|
||||
$data['service_charge_percentage'] = isset($data['fee_free']) && $data['fee_free'] === true ? 0 : ($data['product']['percent_fee_sell']) * $data['number'];
|
||||
$data['difference'] = $data['fee'] = $this->resolveCashPriceDiff($config, $data['product'], 2);
|
||||
$data['total_fee'] = $data['number'] * $data['fee'];
|
||||
$data['price_original'] = $this->resolveProductUnitBasePrice($data['product']);
|
||||
$this->applyCashPriceDiff($config, $data['product'], 2, $data, (float) $data['price_original']);
|
||||
$data['total_fee'] = $data['number'] * $data['fee'];
|
||||
$data['total_price_original'] = $data['product']['amount'] * ($data['price_original'] ?? 0);
|
||||
|
||||
$this->assertMinimumSellCash($data);
|
||||
@@ -164,14 +164,13 @@ class SingleOrderController extends Controller
|
||||
}
|
||||
$config->assertProductTradingOpen($data['product']);
|
||||
if ($data['direction'] == 1) {
|
||||
$data['difference'] = $this->resolveCashPriceDiff($config, $data['product'], 1);
|
||||
$this->applyCashPriceDiff($config, $data['product'], 1, $data, (float) ($data['price_original'] ?? 0));
|
||||
$data['service_charge_percentage'] = $data['product']['percent_fee_buy'];
|
||||
} elseif ($data['direction'] == 2) {
|
||||
$data['difference'] = $this->resolveCashPriceDiff($config, $data['product'], 2);
|
||||
$this->applyCashPriceDiff($config, $data['product'], 2, $data, (float) ($data['price_original'] ?? 0));
|
||||
$data['service_charge_percentage'] = $data['product']['percent_fee_sell'];
|
||||
}
|
||||
// fee اولیه از orderPriceDiffRial ممکن است با اختلاف واقعی محصول فرق کند
|
||||
$data['fee'] = $data['difference'];
|
||||
$data['total_fee'] = $data['amount'] * $data['difference'];
|
||||
$data['product_id'] = $data['product']->id;
|
||||
// Check if the user wants to buy
|
||||
@@ -1160,29 +1159,160 @@ class SingleOrderController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* گلد علی / zaarbox / main_product: اختلاف سفارش = buy_fee/sell_fee نمایش (مثل /api/price/last).
|
||||
* montzar و بقیه: همان cash_fee_buy/sell محصول (رفتار قبلی ابشدهخانگی).
|
||||
* اختلاف قیمت سفارش:
|
||||
* - محصول با «قیمت اپ»: اختلاف پایه تنظیمات (sell_fee/buy_fee/fee_single) + تب اختلاف محصول
|
||||
* - بدون قیمت اپ: فقط تب اختلاف محصول (cash_fee) — بدون ۱M تنظیمات اپ
|
||||
*
|
||||
* @return array{
|
||||
* amount: float,
|
||||
* source: string,
|
||||
* key: string,
|
||||
* label: string,
|
||||
* uses_app_price: bool,
|
||||
* base_price: float,
|
||||
* lines: list<array<string, mixed>>
|
||||
* }
|
||||
*/
|
||||
private function resolveCashPriceDiff(ConfigService $config, Product $product, int $direction): float
|
||||
{
|
||||
$provider = $config->priceProvider();
|
||||
$alignWithDisplay = in_array($provider, ['zaarbox', 'main_product'], true);
|
||||
private function resolveCashPriceDiffMeta(
|
||||
ConfigService $config,
|
||||
Product $product,
|
||||
int $direction,
|
||||
?float $basePriceRial = null
|
||||
): array {
|
||||
$display = app(ProductDisplayPriceService::class);
|
||||
$usesAppPrice = $display->usesAppPrice($product);
|
||||
$isBuy = $direction === 1;
|
||||
$side = $isBuy ? 'خرید' : 'فروش';
|
||||
|
||||
if ($alignWithDisplay) {
|
||||
$display = $direction === 1
|
||||
? $config->displayBuyPriceDiffRial()
|
||||
: $config->displaySellPriceDiffRial();
|
||||
$base = (float) ($basePriceRial ?? 0);
|
||||
if ($base <= 0) {
|
||||
$base = (float) $this->resolveProductUnitBasePrice($product);
|
||||
}
|
||||
if ($base <= 0) {
|
||||
$base = ProductPriceService::productBasePriceRial($product);
|
||||
}
|
||||
|
||||
if ($display > 0) {
|
||||
return $display;
|
||||
$lines = [];
|
||||
$amount = 0.0;
|
||||
$keys = [];
|
||||
|
||||
if ($usesAppPrice) {
|
||||
$feeSingle = (float) $config->get('fee_single', 0);
|
||||
if ($isBuy) {
|
||||
$buyFee = (float) $config->get('buy_fee', $feeSingle);
|
||||
$settingsAmt = $buyFee > 0 ? $buyFee : $feeSingle;
|
||||
$settingsKey = $buyFee > 0 ? 'buy_fee' : 'fee_single';
|
||||
$settingsTitle = $buyFee > 0
|
||||
? 'اختلاف پایه اپ · اضافه قیمت خرید (buy_fee)'
|
||||
: 'اختلاف پایه اپ · اختلاف پایه (fee_single)';
|
||||
} else {
|
||||
$sellFee = (float) $config->get('sell_fee', $feeSingle);
|
||||
$settingsAmt = $sellFee > 0 ? $sellFee : $feeSingle;
|
||||
$settingsKey = $sellFee > 0 ? 'sell_fee' : 'fee_single';
|
||||
$settingsTitle = $sellFee > 0
|
||||
? 'اختلاف پایه اپ · کسر قیمت فروش (sell_fee)'
|
||||
: 'اختلاف پایه اپ · اختلاف پایه (fee_single)';
|
||||
}
|
||||
|
||||
if ($settingsAmt > 0) {
|
||||
$amount += $settingsAmt;
|
||||
$keys[] = $settingsKey;
|
||||
$lines[] = [
|
||||
'kind' => 'app_spread',
|
||||
'key' => $settingsKey,
|
||||
'label' => $settingsTitle,
|
||||
'is_percent' => false,
|
||||
'raw' => $settingsAmt,
|
||||
'per_unit' => $settingsAmt,
|
||||
'detail' => number_format($settingsAmt) . ' ریال / گرم',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return ProductPriceService::resolveCashFeeRial(
|
||||
$product,
|
||||
$direction,
|
||||
ProductPriceService::productBasePriceRial($product)
|
||||
);
|
||||
$productAmt = ProductPriceService::resolveCashFeeRial($product, $direction, $base);
|
||||
$productKey = $isBuy ? 'cash_fee_buy' : 'cash_fee_sell';
|
||||
$isPercent = $isBuy
|
||||
? (bool) ($product->cash_fee_buy_is_percent ?? false)
|
||||
: (bool) ($product->cash_fee_sell_is_percent ?? false);
|
||||
$raw = (float) ($isBuy ? ($product->cash_fee_buy ?? 0) : ($product->cash_fee_sell ?? 0));
|
||||
|
||||
if ($raw != 0.0 || $productAmt > 0) {
|
||||
$amount += $productAmt;
|
||||
$keys[] = $productKey;
|
||||
$rawLabel = $isPercent
|
||||
? (rtrim(rtrim(number_format($raw, 4, '.', ''), '0'), '.') . '%')
|
||||
: (number_format($raw) . ' ریال');
|
||||
$detail = $isPercent
|
||||
? ($rawLabel . ' از ' . number_format($base) . ' ≈ ' . number_format($productAmt) . ' ریال / گرم')
|
||||
: (number_format($productAmt) . ' ریال / گرم');
|
||||
|
||||
$lines[] = [
|
||||
'kind' => 'product_spread',
|
||||
'key' => $productKey,
|
||||
'label' => 'تب اختلاف محصول · هزینه ' . $side,
|
||||
'is_percent' => $isPercent,
|
||||
'raw' => $raw,
|
||||
'percent_of' => $isPercent ? $base : null,
|
||||
'per_unit' => $productAmt,
|
||||
'detail' => $detail,
|
||||
];
|
||||
}
|
||||
|
||||
$hasApp = collect($lines)->contains(fn ($l) => ($l['kind'] ?? '') === 'app_spread');
|
||||
$hasProduct = collect($lines)->contains(fn ($l) => ($l['kind'] ?? '') === 'product_spread');
|
||||
|
||||
if ($hasApp && $hasProduct) {
|
||||
$source = 'app+product';
|
||||
$label = 'قیمت اپ + تب اختلاف محصول = ' . number_format($amount) . ' ریال / گرم';
|
||||
} elseif ($hasApp) {
|
||||
$source = 'settings';
|
||||
$label = ($lines[0]['label'] ?? 'اختلاف پایه اپ') . ' = ' . number_format($amount) . ' ریال';
|
||||
} elseif ($hasProduct) {
|
||||
$source = 'product';
|
||||
$label = ($lines[0]['label'] ?? 'تب اختلاف محصول')
|
||||
. (isset($lines[0]['detail']) ? ' (' . $lines[0]['detail'] . ')' : '');
|
||||
} else {
|
||||
$source = 'none';
|
||||
$label = 'بدون اختلاف قیمت';
|
||||
}
|
||||
|
||||
return [
|
||||
'amount' => $amount,
|
||||
'source' => $source,
|
||||
'key' => implode('+', $keys) ?: 'none',
|
||||
'label' => $label,
|
||||
'uses_app_price' => $usesAppPrice,
|
||||
'base_price' => $base,
|
||||
'lines' => $lines,
|
||||
];
|
||||
}
|
||||
|
||||
private function resolveCashPriceDiff(
|
||||
ConfigService $config,
|
||||
Product $product,
|
||||
int $direction,
|
||||
?float $basePriceRial = null
|
||||
): float {
|
||||
return $this->resolveCashPriceDiffMeta($config, $product, $direction, $basePriceRial)['amount'];
|
||||
}
|
||||
|
||||
/** اختلاف + منبع + اقلام فاکتور را روی $data مینشاند. */
|
||||
private function applyCashPriceDiff(
|
||||
ConfigService $config,
|
||||
Product $product,
|
||||
int $direction,
|
||||
array &$data,
|
||||
?float $basePriceRial = null
|
||||
): void {
|
||||
$meta = $this->resolveCashPriceDiffMeta($config, $product, $direction, $basePriceRial);
|
||||
$data['difference'] = $meta['amount'];
|
||||
$data['fee'] = $meta['amount'];
|
||||
$data['fee_source'] = $meta['source'];
|
||||
$data['fee_source_key'] = $meta['key'];
|
||||
$data['fee_source_label'] = $meta['label'];
|
||||
$data['_fee_spread_lines'] = $meta['lines'];
|
||||
$data['_fee_uses_app_price'] = $meta['uses_app_price'];
|
||||
$data['_fee_base_price'] = $meta['base_price'];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1201,12 +1331,28 @@ class SingleOrderController extends Controller
|
||||
return (int) (($product->price ?? 0) + ($product->price_profit ?? 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* product_id سفارش را برای ذخیره روی جدول orders تثبیت کن.
|
||||
*/
|
||||
private function ensureOrderProductId(array &$data): void
|
||||
{
|
||||
$productId = (int) ($data['product_id'] ?? $data['abshode_id'] ?? 0);
|
||||
if ($productId <= 0) {
|
||||
$productId = (int) (app(ConfigService::class)->mainProductId() ?? 0);
|
||||
}
|
||||
if ($productId > 0) {
|
||||
$data['product_id'] = $productId;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* سود هر گرم / سود کل را از قیمت نهایی و قیمت بدون سود همگام کن
|
||||
* (بعد از نهایی شدن amount و اعمال difference روی price).
|
||||
* و فاکتور اقلام (مثل فاکتور رستوران) را کامل کن.
|
||||
*/
|
||||
private function syncOrderProfitFields(array &$data): void
|
||||
{
|
||||
$this->ensureOrderProductId($data);
|
||||
|
||||
$price = (float) ($data['price'] ?? 0);
|
||||
$priceOriginal = (float) ($data['price_original'] ?? 0);
|
||||
$amount = (float) ($data['amount'] ?? 0);
|
||||
@@ -1214,6 +1360,98 @@ class SingleOrderController extends Controller
|
||||
$data['fee'] = abs($price - $priceOriginal);
|
||||
$data['total_price_original'] = $amount * $priceOriginal;
|
||||
$data['total_fee'] = $amount * $data['fee'];
|
||||
|
||||
$spreadLines = is_array($data['_fee_spread_lines'] ?? null) ? $data['_fee_spread_lines'] : [];
|
||||
$receiptLines = [];
|
||||
$spreadTotal = 0.0;
|
||||
|
||||
foreach ($spreadLines as $line) {
|
||||
$perUnit = (float) ($line['per_unit'] ?? 0);
|
||||
$total = $perUnit * $amount;
|
||||
$spreadTotal += $total;
|
||||
$receiptLines[] = array_merge($line, [
|
||||
'amount_units' => $amount,
|
||||
'total' => $total,
|
||||
'line_text' => ($line['detail'] ?? number_format($perUnit) . ' ریال / گرم')
|
||||
. ($amount > 0
|
||||
? (' × ' . rtrim(rtrim(number_format($amount, 4, '.', ''), '0'), '.') . ' گرم = ' . number_format($total) . ' ریال')
|
||||
: ''),
|
||||
]);
|
||||
}
|
||||
|
||||
// اگر اقلام ذخیره نشده بود، حداقل یک خط از اختلاف واقعی بساز
|
||||
if ($receiptLines === [] && $data['fee'] > 0) {
|
||||
$receiptLines[] = [
|
||||
'kind' => 'spread',
|
||||
'key' => $data['fee_source_key'] ?? 'fee',
|
||||
'label' => $data['fee_source_label'] ?? 'اختلاف قیمت',
|
||||
'is_percent' => false,
|
||||
'per_unit' => $data['fee'],
|
||||
'amount_units' => $amount,
|
||||
'total' => $data['total_fee'],
|
||||
'detail' => number_format($data['fee']) . ' ریال / گرم',
|
||||
'line_text' => number_format($data['fee']) . ' ریال / گرم × '
|
||||
. rtrim(rtrim(number_format($amount, 4, '.', ''), '0'), '.')
|
||||
. ' گرم = ' . number_format($data['total_fee']) . ' ریال',
|
||||
];
|
||||
$spreadTotal = (float) $data['total_fee'];
|
||||
}
|
||||
|
||||
$scGold = (float) ($data['service_charge'] ?? 0);
|
||||
$scRial = (float) ($data['service_charge_price'] ?? 0);
|
||||
$scPct = (float) ($data['service_charge_percentage'] ?? 0);
|
||||
|
||||
if ($scGold > 0 || $scRial > 0) {
|
||||
$goldLabel = rtrim(rtrim(number_format($scGold, 4, '.', ''), '0'), '.') . ' گرم';
|
||||
$detailParts = [];
|
||||
if ($scPct > 0) {
|
||||
$detailParts[] = rtrim(rtrim(number_format($scPct, 4, '.', ''), '0'), '.') . '%';
|
||||
}
|
||||
if ($scGold > 0 && $priceOriginal > 0) {
|
||||
$detailParts[] = $goldLabel . ' × ' . number_format($priceOriginal) . ' = ' . number_format($scRial) . ' ریال';
|
||||
} elseif ($scRial > 0 && $priceOriginal > 0) {
|
||||
$goldEquiv = $scRial / $priceOriginal;
|
||||
$detailParts[] = number_format($scRial) . ' ریال ≈ '
|
||||
. rtrim(rtrim(number_format($goldEquiv, 4, '.', ''), '0'), '.') . ' گرم';
|
||||
} else {
|
||||
$detailParts[] = number_format($scRial) . ' ریال';
|
||||
}
|
||||
|
||||
$receiptLines[] = [
|
||||
'kind' => 'service_charge',
|
||||
'key' => 'service_charge',
|
||||
'label' => 'کارمزد معامله',
|
||||
'is_percent' => $scPct > 0,
|
||||
'raw' => $scPct,
|
||||
'gold' => $scGold,
|
||||
'rial' => $scRial,
|
||||
'per_unit' => $amount > 0 ? ($scRial / $amount) : 0,
|
||||
'amount_units' => $amount,
|
||||
'total' => $scRial,
|
||||
'detail' => implode(' · ', $detailParts),
|
||||
'line_text' => implode(' · ', $detailParts),
|
||||
];
|
||||
}
|
||||
|
||||
$grandTotal = $spreadTotal + $scRial;
|
||||
$data['fee_breakdown'] = [
|
||||
'uses_app_price' => (bool) ($data['_fee_uses_app_price'] ?? false),
|
||||
'amount_units' => $amount,
|
||||
'price_original' => $priceOriginal,
|
||||
'price_customer' => $price,
|
||||
'spread_per_unit' => (float) $data['fee'],
|
||||
'spread_total' => $spreadTotal,
|
||||
'service_charge_gold' => $scGold,
|
||||
'service_charge_rial' => $scRial,
|
||||
'grand_total' => $grandTotal,
|
||||
'lines' => $receiptLines,
|
||||
];
|
||||
|
||||
unset(
|
||||
$data['_fee_spread_lines'],
|
||||
$data['_fee_uses_app_price'],
|
||||
$data['_fee_base_price']
|
||||
);
|
||||
}
|
||||
|
||||
private function bonusGift($customer, $referrer)
|
||||
|
||||
Reference in New Issue
Block a user