ownerGetIds($params["owner_id"]); if ($ids)$builder->whereIn("id",$ids); unset($params["owner_id"]); } $columnQueryRules = [ "name" => ["like"=>""] ]; return app(QueryService::class)->query($params, $builder, $columnQueryRules); } public function paginate(array $params, array $withs = []) { return $this->query(OwnerPriceOperation::query()->orderByDesc('id')->with($withs),$params) ->paginate($params["paginate"] ?? 50); } private function ownerGetIds(string $owner_id) { if (!$owner_id)return []; $arr = DB::select(DB::raw("SELECT owner_price_operation_id AS id FROM owner_price_operation_owner WHERE owner_id in (".$owner_id.")")); return array_column($arr,"id"); } public function destroy($id) { OwnerOutStorageRule::query()->where("owner_price_operation_id",$id)->delete(); OwnerInStorageRule::query()->where("owner_price_operation_id",$id)->delete(); DB::table("owner_price_operation_owner")->where("owner_price_operation_id",$id)->delete(); return OwnerPriceOperation::destroy($id); } /** * @param array $params * @return Model */ public function create(array $params) { return OwnerPriceOperation::query()->create($params); } public function insertRule(array $params, $type = '出库') { if ($type == '出库')OwnerOutStorageRule::query()->insert($params); else OwnerInStorageRule::query()->insert($params); } public function find($id, $isGetRule = false, $withs = []) { $query = OwnerPriceOperation::query()->with($withs)->find($id); if ($isGetRule){ if ($query->operation_type == '入库'){ $query->load("ownerInStorageRule"); $query->rules = $query->ownerInStorageRule ? json_encode([$query->ownerInStorageRule]) : null; }else{ $query->load("ownerOutStorageRules"); $query->rules = json_encode($query->ownerOutStorageRules); } } return $query; } public function destroyRule($id, $type) { if ($type=="入库")OwnerInStorageRule::query()->where("owner_price_operation_id",$id)->delete(); else OwnerOutStorageRule::query()->where("owner_price_operation_id",$id)->delete(); } public function findUpdate(OwnerPriceOperation $model, array $params) { return $model->update($params); } /** 参数顺序: 数量 匹配对象 列映射 货主ID 单位ID 类型 SKU . * 匹配顺序: 类型 货主 策略 单位 特征 ..多对多匹配规则废弃,1对1,设单位必定为件,对应规则必然只有一项存在 * 单位匹配: 件,箱,单 由小到大,依次换算匹配 . * * 2:没有总数量存在,都为子项内数量 * * @param array|object $matchObject key-val * @param array $columnMapping key-val * @param string $owner_id * @param string $type * @return double * 错误代码: -1:无匹配对象 -2:无计费模型 -3:未知单位 -4:sku为空 -5:货主未找到 -6:无箱规 -7:未匹配到计费模型 */ public function matchRule($matchObject, $columnMapping, $owner_id, $type = '出库') { $unitModels = Unit::query()->whereIn("name",["件","箱","单"])->get(); $units = []; foreach ($unitModels as $unitModel)$units[$unitModel->id] = $unitModel->name; $withs = $type=='出库' ? ['ownerOutStorageRules'=>function($query){ /** @var Builder $query */ $query->orderByRaw("CASE strategy WHEN '起步' THEN 1 WHEN '默认' THEN 2 WHEN '特征' THEN 3 END DESC,priority DESC"); }] : ['ownerInStorageRule'] ; $rules = OwnerPriceOperation::query()->with($withs) ->where("operation_type",$type) ->whereHas("ownerPriceOperationOwners",function ($query)use($owner_id){ /** @var Builder $query */ $query->where("id",$owner_id); }) ->orderByRaw("strategy desc,priority desc")->get(); //货主下的全部规则 if (!$rules)return -2; if ($type == '入库'){ $amountColumn = $columnMapping["amount"] ?? "amount"; $packageColumn = $columnMapping["packages"] ?? "packages"; $packages = $matchObject[$packageColumn] ?? false; if (!$packages)return -1; $amount = 0; foreach ($packages as $package)$amount += $package[$amountColumn] ?? 0; if (!$amount)return -1; foreach ($rules as $rule){ $sum = $amount; if (!$rule->ownerInStorageRule)continue; if ($rule->strategy == '特征'){ $bool = app("FeatureService")->matchFeature($rule->feature,$columnMapping,$matchObject); if ($bool === true){ if (!isset($units[$rule->ownerInStorageRule->unit_id])) return -3; if ($units[$rule->ownerInStorageRule->unit_id] == '箱'){ //为箱时同步商品寻找箱规 $sumTemp = 0; $packageColumn = $columnMapping["packages"] ?? "packages"; foreach ($matchObject[$packageColumn] as $commodity){ $sumTemp += $this->changeUnit($sum,$owner_id,$commodity["sku"]); } $sum = $sumTemp; if ($sum<0)return $sum; } if ($units[$rule->ownerInStorageRule->unit_id] == '单')$sum = 1; //为单时数量设为1; return ceil($sum/$rule->ownerInStorageRule->amount)*$rule->ownerInStorageRule->unit_price; }; }else{ if (!isset($units[$rule->ownerInStorageRule->unit_id])) return -3; if ($units[$rule->ownerInStorageRule->unit_id] == '箱'){ //为箱时同步商品寻找箱规 $sumTemp = 0; $packageColumn = $columnMapping["packages"] ?? "packages"; foreach ($matchObject[$packageColumn] as $commodity){ $sumTemp += $this->changeUnit($sum,$owner_id,$commodity["sku"]); } $sum = $sumTemp; if ($sum<0)return $sum; } if ($units[$rule->ownerInStorageRule->unit_id] == '单')$sum = 1; //为单时数量设为1; return ceil($sum/$rule->ownerInStorageRule->amount)*$rule->ownerInStorageRule->unit_price; }; } return -7; } //出库 foreach ($rules as $rule){ if (!$rule->ownerOutStorageRules)continue; if ($rule->strategy == '特征'){ $bool = app("FeatureService")->matchFeature($rule->feature,$columnMapping,$matchObject);//匹配特征 if ($bool === true){ $money = $this->matchOutStorage($rule->ownerOutStorageRules,$columnMapping,$matchObject,$units,$owner_id); if ($money>0)return $money; }; }else{ $money = $this->matchOutStorage($rule->ownerOutStorageRules,$columnMapping,$matchObject,$units,$owner_id); if ($money>0)return $money; }; } return -7; } private function changeUnit($amount,$owner_id,$sku) { if (!$sku)return -4; $pack = app("CommodityService")->getPack($owner_id,$sku); if (!$pack)return -6; return ceil($amount/$pack); } private function matchOutStorage($rules, $columnMapping, $matchObject, $units, $owner_id) { $amountColumn = $columnMapping["amount"] ?? "amount"; $packageColumn = $columnMapping["packages"] ?? "packages"; $packages = $matchObject[$packageColumn] ?? false; $commodityColumn = $columnMapping["商品名称"] ?? 'commodity'; if (!$packages)return -1; $unitName = ""; foreach ($rules as $rule){ switch ($rule->strategy){ case "特征": foreach ($packages as &$package){ if ($package["price"] ?? false)continue; if (!app("FeatureService")->matchFeature($rule->feature,["商品名称"=>$commodityColumn],["commodity"=>$package[$commodityColumn] ?? ''])) continue; if (!$unitName)$unitName = $units[$rule->unit_id]; else { if ($unitName != $units[$rule->unit_id]) return -3; } $package["price"] = $rule->unit_price; if (!isset($units[$rule->unit_id]) || $units[$rule->unit_id] == '单')return -3; if ($units[$rule->unit_id] == '箱'){ //为箱时同步商品寻找箱规 $sumTemp = 0; $packageColumn = $columnMapping["packages"] ?? "packages"; foreach ($matchObject[$packageColumn] as $commodity){ $sumTemp += $this->changeUnit($package[$amountColumn],$owner_id,$commodity["sku"]); } $amount = $sumTemp; if ($amount<0)return $amount; $package[$amountColumn] = $amount; } } break; case "默认": foreach ($packages as &$package){ if ($package["price"] ?? false)continue; //校验是否已匹配到 if (!$unitName)$unitName = $units[$rule->unit_id]; //校验单位是否一致 else { if ($unitName != $units[$rule->unit_id]) return -3; } $package["price"] = $rule->unit_price; if (!isset($units[$rule->unit_id]) || $units[$rule->unit_id] == '单')return -3; if ($units[$rule->unit_id] == '箱'){ //为箱时同步商品寻找箱规 $sumTemp = 0; $packageColumn = $columnMapping["packages"] ?? "packages"; foreach ($matchObject[$packageColumn] as $commodity){ $sumTemp += $this->changeUnit($package[$amountColumn],$owner_id,$commodity["sku"]); } $amount = $sumTemp; if ($amount<0)return $amount; $package[$amountColumn] = $amount; } } break; default: if ($unitName && $unitName != $units[$rule->unit_id])return -3; //校验单位是否一致 $money = $rule->amount * $rule->unit_price; $startNumber = $rule->amount; $packages = $this->settingCount($packages,$amountColumn,$startNumber); if ($packages){ foreach ($packages as $package){ $money += $package[$amountColumn] * $package["price"]; } } return $money; } } return -7; } //设置数量 private function settingCount($packages,$amountColumn,$startNumber) { if (!$packages) return null; $maxPrice = 0; $index = null; foreach ($packages as $i => $package){ if ($package[$amountColumn] <= 0){ unset($packages[$i]);continue; } if ($package["price"] > $maxPrice){ $maxPrice = $package["price"]; $index = $i; } } if ($packages[$index][$amountColumn] >= $startNumber){ $packages[$index][$amountColumn] -= $startNumber; return $packages; }else{ unset($packages[$index]); $startNumber -= $packages[$index][$amountColumn]; $this->settingCount($packages,$amountColumn,$startNumber); } } }