Add formula-based product pricing (P/W/MG) for Parsian-style unit prices.
Port FormulaPriceService from colleague app so admins can compute a single unit price from reference mid, weight, and wage instead of offset coefficients. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -15,11 +15,13 @@ use Illuminate\Support\Facades\Http;
|
||||
use \App\Http\Controllers\Customer\FundController;
|
||||
use App\Http\Controllers\Site\ReportController;
|
||||
use App\Services\ConfigService;
|
||||
use App\Services\FormulaPriceService;
|
||||
use App\Services\ProductDisplayPriceService;
|
||||
use App\Services\ProductPriceService;
|
||||
use App\Services\ProductPriceSyncService;
|
||||
use App\Services\PriceBroadcastService;
|
||||
use App\Services\CategoryService;
|
||||
use App\Services\ZaarboxPriceService;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
|
||||
@@ -117,6 +119,11 @@ class ProductController extends SuperController
|
||||
$data = $this->filterProductData($request->all());
|
||||
|
||||
$product = Product::create($data);
|
||||
|
||||
if (FormulaPriceService::isEnabled($product) && $product->reading_method) {
|
||||
app(ZaarboxPriceService::class)->syncProductFromApi($product);
|
||||
}
|
||||
|
||||
$this->broadcastPricesAfterResponse(true);
|
||||
|
||||
return $this->resultCreate($product->id);
|
||||
@@ -134,7 +141,10 @@ class ProductController extends SuperController
|
||||
}
|
||||
// قیمت دستی ⇒ تعدیل مرجع بیمعناست و صفر میشود.
|
||||
// قیمت اپ در filterProductData عمداً price=0 میگذارد؛ نباید تعدیل را پاک کند.
|
||||
if (isset($data['price']) && empty($data['app_price'])) {
|
||||
// قیمت فرمولی reading_method میخواهد — با وجود price ذخیرهشده مرجع را پاک نکن.
|
||||
$formulaEnabled = Product::hasPriceFormulaColumns()
|
||||
&& filter_var($data['price_formula_enabled'] ?? false, FILTER_VALIDATE_BOOLEAN);
|
||||
if (isset($data['price']) && empty($data['app_price']) && ! $formulaEnabled) {
|
||||
$data['reading_method'] = null;
|
||||
if (Product::hasPriceOffsetColumn()) {
|
||||
$data['price_offset_percent'] = 0;
|
||||
@@ -166,6 +176,7 @@ class ProductController extends SuperController
|
||||
&& $product->reading_method
|
||||
&& array_key_exists('price_offset_percent', $data)
|
||||
&& !$clearingReadingMethod
|
||||
&& ! $formulaEnabled
|
||||
) {
|
||||
ProductPriceService::reapplyOffsetPercent(
|
||||
$product,
|
||||
@@ -176,6 +187,12 @@ class ProductController extends SuperController
|
||||
}
|
||||
|
||||
$product->update($data);
|
||||
$product->refresh();
|
||||
|
||||
if (FormulaPriceService::isEnabled($product) && $product->reading_method) {
|
||||
app(ZaarboxPriceService::class)->syncProductFromApi($product);
|
||||
}
|
||||
|
||||
$this->broadcastPricesAfterResponse(true);
|
||||
|
||||
return response()->json(true);
|
||||
@@ -659,6 +676,35 @@ class ProductController extends SuperController
|
||||
}
|
||||
$data['price'] = 0;
|
||||
$data['price_profit'] = 0;
|
||||
if (Product::hasPriceFormulaColumns()) {
|
||||
$data['price_formula_enabled'] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!Product::hasPriceFormulaColumns()) {
|
||||
unset($data['price_formula_enabled'], $data['price_formula']);
|
||||
} else {
|
||||
$formulaEnabled = filter_var($data['price_formula_enabled'] ?? false, FILTER_VALIDATE_BOOLEAN);
|
||||
$data['price_formula_enabled'] = $formulaEnabled;
|
||||
$formula = trim((string) ($data['price_formula'] ?? ''));
|
||||
if ($formulaEnabled) {
|
||||
if ($formula === '') {
|
||||
$formula = FormulaPriceService::DEFAULT_FORMULA;
|
||||
}
|
||||
$data['price_formula'] = $formula;
|
||||
$data['app_price'] = false;
|
||||
if (Product::hasDirectPriceColumn()) {
|
||||
$data['direct_price'] = 1;
|
||||
}
|
||||
if (Product::hasPriceOffsetColumn()) {
|
||||
$data['price_offset_percent'] = 0;
|
||||
}
|
||||
if (empty($data['reading_method'])) {
|
||||
throw new UnprocessableEntityHttpException('برای قیمت فرمولی، یک مرجع قیمت انتخاب کنید');
|
||||
}
|
||||
} else {
|
||||
$data['price_formula'] = $formula !== '' ? $formula : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -773,8 +773,14 @@ class Controller extends BaseController
|
||||
'direct_price' => is_object($product) ? ($product->direct_price ?? null) : null,
|
||||
'group_type' => is_object($product) ? ($product->group_type ?? null) : null,
|
||||
'reading_method' => is_object($product) ? ($product->reading_method ?? null) : null,
|
||||
'price_formula_enabled' => is_object($product) ? ($product->price_formula_enabled ?? null) : null,
|
||||
];
|
||||
|
||||
// قیمت فرمولی = قیمت واحد هر عدد (وزن داخل فرمول است)
|
||||
if (! empty($payload['price_formula_enabled'])) {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
if (! empty($payload['reading_method'])) {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ use App\Services\MontzarService;
|
||||
use App\Services\ConfigService;
|
||||
use App\Services\ProductPriceService;
|
||||
use App\Services\ProductDisplayPriceService;
|
||||
use App\Services\FormulaPriceService;
|
||||
use App\Services\ReferralGiftService;
|
||||
use App\Services\WalletBroadcastService;
|
||||
|
||||
@@ -127,7 +128,8 @@ class SingleOrderController extends Controller
|
||||
$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);
|
||||
$data['total_price_original'] = $this->resolveProductOrderPricingAmount($data['product'], 1.0)
|
||||
* ($data['price_original'] ?? 0);
|
||||
|
||||
// Check if the method is cash
|
||||
if ($data['method'] == "cash") {
|
||||
@@ -147,7 +149,8 @@ class SingleOrderController extends Controller
|
||||
$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);
|
||||
$data['total_price_original'] = $this->resolveProductOrderPricingAmount($data['product'], 1.0)
|
||||
* ($data['price_original'] ?? 0);
|
||||
|
||||
$this->assertMinimumSellCash($data);
|
||||
|
||||
@@ -394,7 +397,7 @@ class SingleOrderController extends Controller
|
||||
{
|
||||
// همان قیمت پایهٔ سفارش (price_original / قیمت اپ) — نه ستون کهنهٔ products.price
|
||||
$data['price'] = $this->resolveProductOrderUnitPrice($data) + (float) ($data['difference'] ?? 0);
|
||||
$data['amount'] = $data['number'] * $data['product']['amount'];
|
||||
$data['amount'] = $this->resolveProductOrderPricingAmount($data['product'], (float) $data['number']);
|
||||
// محصول تعدادی: کارمزد فقط از ریال (fee_service_charge_percentage)
|
||||
$feeRate = isset($data['fee_free']) && $data['fee_free'] === true
|
||||
? 0.0
|
||||
@@ -452,7 +455,7 @@ class SingleOrderController extends Controller
|
||||
{
|
||||
|
||||
$data['price'] += $data['difference'];
|
||||
$data['amount'] = $data['number'] * $data['product']['amount'];
|
||||
$data['amount'] = $this->resolveProductOrderPricingAmount($data['product'], (float) $data['number']);
|
||||
// محصول تعدادی: کارمزد از ریال (fee_service_charge_percentage)
|
||||
$feeRate = isset($data['fee_free']) && $data['fee_free'] === true
|
||||
? 0.0
|
||||
@@ -670,7 +673,7 @@ class SingleOrderController extends Controller
|
||||
{
|
||||
// همان قیمت پایهٔ سفارش (price_original / قیمت اپ) — نه ستون کهنهٔ products.price
|
||||
$data['price'] = max(0.0, $this->resolveProductOrderUnitPrice($data) - (float) ($data['difference'] ?? 0));
|
||||
$data['amount'] = $data['number'] * $data['product']['amount'];
|
||||
$data['amount'] = $this->resolveProductOrderPricingAmount($data['product'], (float) $data['number']);
|
||||
// محصول تعدادی: کارمزد فقط از ریال
|
||||
$feeRate = isset($data['fee_free']) && $data['fee_free'] === true
|
||||
? 0.0
|
||||
@@ -723,7 +726,7 @@ class SingleOrderController extends Controller
|
||||
private function processSellTransactionProductByGold(&$data, $wallet, $wallet_interface)
|
||||
{
|
||||
$data['price'] -= $data['difference'];
|
||||
$data['amount'] = $data['number'] * $data['product']['amount'];
|
||||
$data['amount'] = $this->resolveProductOrderPricingAmount($data['product'], (float) $data['number']);
|
||||
// محصول تعدادی: کارمزد فقط از ریال
|
||||
$feeRate = isset($data['fee_free']) && $data['fee_free'] === true
|
||||
? 0.0
|
||||
@@ -1100,7 +1103,7 @@ class SingleOrderController extends Controller
|
||||
if (!empty($data['product_id']) && isset($data['number'])) {
|
||||
$product = $data['product'] ?? Product::find($data['product_id']);
|
||||
if ($product) {
|
||||
return (float) $data['number'] * (float) $product->amount;
|
||||
return $this->resolveProductOrderPricingAmount($product, (float) $data['number']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1161,7 +1164,7 @@ class SingleOrderController extends Controller
|
||||
$product = $data['product'] ?? Product::find($data['product_id']);
|
||||
if ($product) {
|
||||
$difference = (float) ($data['difference'] ?? 0);
|
||||
$amount = (float) $data['number'] * (float) $product->amount;
|
||||
$amount = $this->resolveProductOrderPricingAmount($product, (float) $data['number']);
|
||||
$sellUnitPrice = max(0.0, $this->resolveProductOrderUnitPrice($data) - $difference);
|
||||
|
||||
return $amount * $sellUnitPrice;
|
||||
|
||||
Reference in New Issue
Block a user