87 lines
3.8 KiB
PHP
87 lines
3.8 KiB
PHP
<?php
|
||
|
||
namespace App\Http\Requests\Product;
|
||
|
||
use App\Models\ProductCategoryModel;
|
||
use App\Models\ProductPriceModel;
|
||
use App\Models\SupplierModel;
|
||
use Closure;
|
||
use Illuminate\Validation\Rules\Exists;
|
||
use Illuminate\Validation\Validator;
|
||
use Modules\Common\Http\Requests\BaseFormRequest;
|
||
use Modules\SystemTool\Models\SysFileModel;
|
||
|
||
/**
|
||
* 商品档案 创建/编辑 验证(含多等级价格 prices 数组)
|
||
*/
|
||
class ProductFormRequest extends BaseFormRequest
|
||
{
|
||
protected $stopOnFirstFailure = true;
|
||
|
||
public function rules(): array
|
||
{
|
||
return [
|
||
'category_id' => ['required','integer', new Exists(ProductCategoryModel::class,'id')],
|
||
'supplier_id' => ['nullable','integer', 'exclude_if:supplier_id,0', new Exists(SupplierModel::class,'id')],
|
||
'name' => 'required|string|max:100',
|
||
'spec' => 'nullable|string|max:100',
|
||
'unit' => 'nullable|string|max:20',
|
||
'image_ids' => 'nullable|array|max:255',
|
||
'image_ids.*' => ['integer', new Exists(SysFileModel::class, 'id')],
|
||
'content' => 'nullable|string',
|
||
'sort' => 'nullable|integer',
|
||
'shelf_life' => 'nullable|integer|min:0',
|
||
'stock' => 'nullable|integer|min:0',
|
||
'status' => 'nullable|integer|in:0,1',
|
||
'cost_price' => 'nullable|numeric|min:0|max:99999999',
|
||
'remark' => 'nullable|string|max:255',
|
||
'prices' => 'nullable|array',
|
||
'prices.*.level_id' => 'required|integer|exists:customer_level,id',
|
||
'prices.*.price_type' => 'nullable|integer|in:0,1',
|
||
'prices.*.price' => 'required|numeric|min:0|max:99999999',
|
||
'prices.*.percent' => 'nullable|numeric|min:0|max:999.99',
|
||
];
|
||
}
|
||
|
||
/**
|
||
* 交叉校验:按成本百分比计价(price_type=1)时上浮百分点必填
|
||
* (Laravel 12 FormRequest 的 after() 需返回单个 Closure,由容器 call 后注册到 Validator)
|
||
*/
|
||
public function after(): Closure
|
||
{
|
||
return function (Validator $validator): void {
|
||
$data = (array) $validator->getData();
|
||
foreach ((array) ($data['prices'] ?? []) as $index => $row) {
|
||
$priceType = (int) ($row['price_type'] ?? ProductPriceModel::PRICE_TYPE_FIXED);
|
||
if ($priceType === ProductPriceModel::PRICE_TYPE_PERCENT
|
||
&& (! array_key_exists('percent', (array) $row) || $row['percent'] === null || $row['percent'] === '')) {
|
||
$validator->errors()->add("prices.{$index}.percent", '按成本百分比计价时必须填写上浮百分点');
|
||
}
|
||
}
|
||
};
|
||
}
|
||
|
||
public function messages(): array
|
||
{
|
||
return [
|
||
'name.required' => '商品名称不能为空',
|
||
'name.max' => '商品名称最长 100 个字符',
|
||
'category_id.required' => '请选择商品分类',
|
||
'category_id.exists' => '商品分类不存在',
|
||
'supplier_id.exists' => '供应商不存在',
|
||
'status.in' => '状态值不正确',
|
||
'prices.*.level_id.required' => '价格行缺少客户等级',
|
||
'prices.*.level_id.exists' => '客户等级不存在',
|
||
'prices.*.price.required' => '价格行缺少单价',
|
||
'prices.*.price.numeric' => '单价必须为数字',
|
||
'prices.*.price.min' => '单价不能小于 0',
|
||
'cost_price.numeric' => '成本价必须为数字',
|
||
'cost_price.min' => '成本价不能小于 0',
|
||
'prices.*.price_type.in' => '计价类型不正确',
|
||
'prices.*.percent.numeric' => '上浮百分点必须为数字',
|
||
'prices.*.percent.min' => '上浮百分点不能小于 0',
|
||
'prices.*.percent.max' => '上浮百分点不能超过 999.99',
|
||
];
|
||
}
|
||
}
|