From de34b30dbc5fcb0c1ac49232e828166aa08cbd69 Mon Sep 17 00:00:00 2001 From: lewis <604446095@qq.com> Date: Thu, 3 Apr 2025 16:25:57 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=95=86=E5=93=81=E6=94=B9?= =?UTF-8?q?=E4=BB=B7=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/common/model/psi/product/StoreProduct.php | 20 ++ .../model/psi/product/StoreProductPrice.php | 21 ++ .../psi/product/StoreProductPriceList.php | 19 ++ .../model/psi/product/StoreProductUnit.php | 15 + app/common/model/psi/warehouse/Warehouse.php | 5 +- .../StoreProductPriceController.php | 114 +++++++ app/psi/lists/StoreProductPriceLists.php | 103 ++++++ app/psi/logic/StoreProductPriceLogic.php | 295 ++++++++++++++++++ .../validate/StoreProductPriceValidate.php | 82 +++++ config/thinkorm.php | 48 +++ 10 files changed, 719 insertions(+), 3 deletions(-) create mode 100644 app/common/model/psi/product/StoreProduct.php create mode 100644 app/common/model/psi/product/StoreProductPrice.php create mode 100644 app/common/model/psi/product/StoreProductPriceList.php create mode 100644 app/common/model/psi/product/StoreProductUnit.php create mode 100644 app/psi/controller/StoreProductPriceController.php create mode 100644 app/psi/lists/StoreProductPriceLists.php create mode 100644 app/psi/logic/StoreProductPriceLogic.php create mode 100644 app/psi/validate/StoreProductPriceValidate.php diff --git a/app/common/model/psi/product/StoreProduct.php b/app/common/model/psi/product/StoreProduct.php new file mode 100644 index 0000000..f1c5953 --- /dev/null +++ b/app/common/model/psi/product/StoreProduct.php @@ -0,0 +1,20 @@ +hasOne(StoreProductUnit::class,'id','unit')->bind(['unit_name'=>'name','is_bulk']); + } + +} \ No newline at end of file diff --git a/app/common/model/psi/product/StoreProductPrice.php b/app/common/model/psi/product/StoreProductPrice.php new file mode 100644 index 0000000..d5d9b11 --- /dev/null +++ b/app/common/model/psi/product/StoreProductPrice.php @@ -0,0 +1,21 @@ +dataLists(new StoreProductPriceLists()); + } + + + /** + * @notes 添加 + * @author admin + * @date 2025/04/03 15:19 + */ + public function add() + { + $params = (new StoreProductPriceValidate())->post()->goCheck('add'); + $result = StoreProductPriceLogic::add($params); + if (true === $result) { + return $this->success('添加成功', [], 1, 1); + } + return $this->fail(StoreProductPriceLogic::getError()); + } + + + /** + * @notes 编辑 + * @author admin + * @date 2025/04/03 15:19 + */ + public function edit() + { + $params = (new StoreProductPriceValidate())->post()->goCheck('edit'); + $result = StoreProductPriceLogic::edit($params); + if (true === $result) { + return $this->success('编辑成功', [], 1, 1); + } + return $this->fail(StoreProductPriceLogic::getError()); + } + + + /** + * @notes 删除 + * @author admin + * @date 2025/04/03 15:19 + */ + public function delete() + { + $params = (new StoreProductPriceValidate())->post()->goCheck('delete'); + StoreProductPriceLogic::delete($params); + return $this->success('删除成功', [], 1, 1); + } + + + /** + * @notes 获取详情 + * @author admin + * @date 2025/04/03 15:19 + */ + public function detail() + { + $params = (new StoreProductPriceValidate())->goCheck('detail'); + $result = StoreProductPriceLogic::detail($params); + return $this->data($result); + } + + /** + * @notes 确认改价 + */ + public function enterPrice() + { + $params = $this->request->post(); + $result = StoreProductPriceLogic::enterPrice($params); + return $this->success('设置成功', [], 1, 1); + + } + + public function export() + { + $params = $this->request->post(); + $file_path = StoreProductPriceLogic::export($params); + return $this->success('导出成功', ['url' => $file_path]); + } + + public function chart() + { + $params = $this->request->get(); + $data = StoreProductPriceLogic::chart($params); + return $this->data($data); + } + +} \ No newline at end of file diff --git a/app/psi/lists/StoreProductPriceLists.php b/app/psi/lists/StoreProductPriceLists.php new file mode 100644 index 0000000..a2e7511 --- /dev/null +++ b/app/psi/lists/StoreProductPriceLists.php @@ -0,0 +1,103 @@ + ['status'], + + ]; + } + + /** + * @notes 获取列表 + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + * @author admin + * @date 2025/04/03 15:19 + */ + public function lists(): array + { + $store_name = $this->request->get('store_name'); + if ($store_name) { + $store_id = StoreProduct::where('store_name', 'like', '%' . $store_name . '%')->column('id'); + $this->searchWhere[] = ['product_id', 'in', $store_id]; + } + if (!empty($this->params['start_time'])) { + $this->searchWhere[] = ['create_time', '>=', strtotime($this->params['start_time'])]; + } + if (!empty($this->params['end_time'])) { + $this->searchWhere[] = ['create_time', '<=', strtotime($this->params['end_time'])]; + } + $list = StoreProductPrice::where($this->searchWhere) + ->field(['id', 'bhoid', 'offer_id', 'product_id', 'purchase_price', 'purchase_lv', 'purchase', 'cost_lv', 'cost', 'price_lv', 'price', 'vip_lv', 'vip_price', 'price_config', 'status', 'create_time', 'mark', 'warehouse_id']) + ->limit($this->limitOffset, $this->limitLength) + ->order(['id' => 'desc']) + ->select()->each(function ($item) { + $find = StoreProduct::with('unitName')->where('id', $item['product_id'])->field('image,purchase,cost,price,store_name,store_info,unit')->withTrashed()->find(); + $item['warehouse'] = Warehouse::where('id', $item['warehouse_id'])->value('name'); + $item['unit_name'] = $find['unitName']['name'] ?? ''; + $item['store_name'] = $find['store_name']; + $item['store_info'] = $find['store_info']; + $item['image'] = $find['image']; + $item['current_purchase'] = $find['purchase']; + $item['current_cost'] = $find['cost']; + $item['current_price'] = $find['price']; + $item['status_name'] = $item['status'] == 0 ? "未设置" : "已设置"; + }) + ->toArray(); + $productIds = array_unique(array_column($list, 'product_id')); + $priceList = StoreProductPriceList::whereIn('product_id', $productIds)->select()->toArray(); + $priceList = reset_index($priceList, 'product_id'); + foreach ($list as &$item) { + $productPrice = $priceList[$item['product_id']] ?? []; + if (empty($productPrice) || $item['status'] == 1) { + continue; + } + $priceArray = StoreProductPriceLogic::setProductPrice($item['purchase_price'], $productPrice); + $item = array_merge($item, $priceArray); + } + return $list; + } + + + /** + * @notes 获取数量 + * @return int + * @author admin + * @date 2025/04/03 15:19 + */ + public function count(): int + { + return StoreProductPrice::where($this->searchWhere)->count(); + } + +} \ No newline at end of file diff --git a/app/psi/logic/StoreProductPriceLogic.php b/app/psi/logic/StoreProductPriceLogic.php new file mode 100644 index 0000000..80a7a83 --- /dev/null +++ b/app/psi/logic/StoreProductPriceLogic.php @@ -0,0 +1,295 @@ + $params['bhoid'], + 'offer_id' => $params['offer_id'], + 'warehouse_id' => $params['warehouse_id'], + 'warehouse_product_id' => $params['warehouse_product_id'], + 'product_id' => $params['product_id'], + 'purchase_price' => $params['purchase_price'], + 'purchase_lv' => $params['purchase_lv'], + 'purchase' => $params['purchase'], + 'cost_lv' => $params['cost_lv'], + 'cost' => $params['cost'], + 'price_lv' => $params['price_lv'], + 'price' => $params['price'], + 'vip_lv' => $params['vip_lv'], + 'vip_price' => $params['vip_price'], + 'price_config' => $params['price_config'], + 'mark' => $params['mark'], + 'status' => $params['status'], + ]); + + Db::commit(); + return true; + } catch (\Throwable $e) { + Db::rollback(); + throw new Exception($e->getMessage()); + } + } + + + /** + * @notes 编辑 + * @param array $params + * @return bool + * @author admin + * @date 2025/04/03 15:19 + */ + public static function edit(array $params): bool + { + Db::startTrans(); + try { + $find = StoreProductPrice::where('id', $params['id'])->find(); + if ($find) { + $productPriceListAttrs = []; + if ($find['purchase_lv'] != $params['purchase_lv']) { + $productPriceListAttrs['supply_rate'] = $params['purchase_lv'] * 100; + } + if ($find['cost_lv'] != $params['cost_lv']) { + $productPriceListAttrs['merchant_rate'] = $params['cost_lv'] * 100; + } + if ($find['vip_lv'] != $params['vip_lv']) { + $productPriceListAttrs['vip_rate'] = $params['vip_lv'] * 100; + } + if ($find['price_lv'] != $params['price_lv']) { + $productPriceListAttrs['price_rate'] = $params['price_lv'] * 100; + } + if (!empty($productPriceListAttrs)) { + $id = StoreProductPriceList::where('product_id', $find['product_id'])->value('id'); + if (empty($id)) { + $productPriceListAttrs = array_merge($productPriceListAttrs, ['product_id' => $find['product_id']]); + StoreProductPriceList::create($productPriceListAttrs); + } else { + StoreProductPriceList::where('id', $id)->update($productPriceListAttrs); + } + } + + $find->save([ + 'status' => 1, + 'purchase' => $params['purchase'], + 'purchase_lv' => $params['purchase_lv'], + 'cost' => $params['cost'], + 'cost_lv' => $params['cost_lv'], + 'vip_price' => $params['vip_price'], + 'vip_lv' => $params['vip_lv'], + 'price' => $params['price'], + 'price_lv' => $params['price_lv'], + 'price_config' => $params['price_config'], + ]); + + // TODO 请求多门店系统,更新商品价格 +// $productPrice = StoreProduct::where('id', $find['product_id'])->value('vip_price'); +// if ($productPrice != $find['vip_price']) { +// SqlChannelPriceLog($find['product_id'], 43, $productPrice, $find['vip_price']); +// } +// StoreProduct::where('id', $find['product_id'])->update([ +// 'purchase' => $find['purchase'], +// 'cost' => $find['cost'], +// 'vip_price' => $find['vip_price'], +// 'price' => $find['vip_price'], +// 'ot_price' => $find['price'] +// ]); +// StoreBranchProduct::where('product_id', $find['product_id'])->update([ +// 'purchase' => $find['purchase'], +// 'cost' => $find['cost'], +// 'vip_price' => $find['vip_price'], +// 'price' => $find['vip_price'], +// 'ot_price' => $find['price'] +// ]); +// +// $productSourceLinkInfoLogic = new ProductSourceLinkInfoLogic(); +// $productSourceLinkInfoLogic->storeProductPrice = $find; +// $productSourceLinkInfoLogic->updateSupplyPrice(); + } + Db::commit(); + return true; + } catch (\Throwable $e) { + Db::rollback(); + throw new BusinessException($e->getMessage()); + } + } + + public static function enterPrice(array $params): bool + { + Db::startTrans(); + try { + $find = StoreProductPrice::where('id', $params['id'])->find(); + if ($find) { + $productPriceRate = StoreProductPriceList::whereIn('product_id', $find['product_id'])->findOrEmpty()->toArray(); + $update = ['status' => 1]; + if (!empty($productPriceRate)) { + $update = self::setProductPrice($find['purchase_price'], $productPriceRate); + $update['status'] = 1; + } + $find->save($update); + + // TODO 请求多门店系统,更新商品价格 +// $productPrice = StoreProduct::where('id', $find['product_id'])->value('vip_price'); +// if ($productPrice != $find['vip_price']) { +// SqlChannelPriceLog($find['product_id'], 43, $productPrice, $find['vip_price']); +// } +// StoreProduct::where('id', $find['product_id'])->update([ +// 'purchase' => $find['purchase'] ?? 0, +// 'cost' => $find['cost'] ?? 0, +// 'vip_price' => $find['vip_price'] ?? 0, +// 'price' => $find['vip_price'] ?? 0, +// 'ot_price' => $find['price'] ?? 0, +// ]); +// StoreBranchProduct::where('product_id', $find['product_id'])->update([ +// 'purchase' => $find['purchase'] ?? 0, +// 'cost' => $find['cost'] ?? 0, +// 'vip_price' => $find['vip_price'] ?? 0, +// 'price' => $find['vip_price'] ?? 0, +// 'ot_price' => $find['price'] ?? 0, +// ]); + } + Db::commit(); + return true; + } catch (\Throwable $e) { + Db::rollback(); + throw new BusinessException($e->getMessage()); + } + } + + /** + * @notes 删除 + * @param array $params + * @return bool + * @author admin + * @date 2025/04/03 15:19 + */ + public static function delete(array $params): bool + { + return StoreProductPrice::destroy($params['id']); + } + + + /** + * @notes 获取详情 + * @param $params + * @return array + * @author admin + * @date 2025/04/03 15:19 + */ + public static function detail($params): array + { + return StoreProductPrice::findOrEmpty($params['id'])->toArray(); + } + + /** + * 设置商品价格 + * @param $purchasePrice float 采购价 + * @param $productPriceRate array 价格比例 + * @return array + */ + public static function setProductPrice(float $purchasePrice, array $productPriceRate) + { + $result = []; + $result['purchase_lv'] = bcdiv($productPriceRate['supply_rate'], 100, 2); + $result['purchase'] = bcmul($purchasePrice, $result['purchase_lv'], 2); + $result['cost_lv'] = bcdiv($productPriceRate['merchant_rate'], 100, 2); + $result['cost'] = bcmul($result['purchase'], $result['cost_lv'], 2); + $result['vip_lv'] = bcdiv($productPriceRate['vip_rate'], 100, 2); + $result['vip_price'] = bcmul($result['purchase'], $result['vip_lv'], 2); + $result['price_lv'] = bcdiv($productPriceRate['price_rate'], 100, 2); + $result['price'] = bcmul($result['purchase'], $result['price_lv'], 2); + // 暂时不处理零售价,零售价使用会员价 +// $lastNum = substr($result['price'], -1); +// if ($lastNum > 0) { +// $result['price'] = ceil($result['price'] * 10); +// $result['price'] = bcdiv($result['price'], 10, 2); +// } + $lastNum = substr($result['vip_price'], -1); + if ($lastNum > 0) { + $result['vip_price'] = ceil($result['vip_price'] * 10); + $result['vip_price'] = bcdiv($result['vip_price'], 10, 2); + } + return $result; + } + + public static function export($params) + { + $query = StoreProductPrice::field('*'); + if (!empty($params['store_name'])) { + $productIds = StoreProduct::where('store_name', 'like', "%{$params['store_name']}%")->column('id'); + $query->whereIn('product_id', $productIds); + } + if ($params['status'] != '') { + $query->where('status', $params['status']); + } + if (!empty($params['start_time'])) { + $query->where('create_time', '>=', strtotime($params['start_time'])); + } + if (!empty($params['end_time'])) { + $query->where('create_time', '<=', strtotime($params['end_time'])); + } + $data = $query->order('id desc')->select()->toArray(); + $warehouses = Warehouse::field('id,name')->whereIn('id', array_unique(array_column($data, 'warehouse_id')))->select()->toArray(); + $warehouses = reset_index($warehouses, 'id'); + $products = StoreProduct::field('id,store_name')->whereIn('id', array_unique(array_column($data, 'product_id')))->select()->toArray(); + $products = reset_index($products, 'id'); + foreach ($data as &$item) { + $item['warehouse'] = $warehouses[$item['warehouse_id']]['name'] ?? ''; + $item['store_name'] = $products[$item['product_id']]['store_name'] ?? ''; + } + return (new StoreProductPriceXlsx())->export($data); + } + + public static function chart($params) + { + $list = StoreProductPrice::where('product_id', $params['product_id']) + ->field('id,purchase_price,purchase,create_time') + ->order('id desc')->limit(30) + ->select()->toArray(); + foreach ($list as &$item) { + $item['date'] = date('m-d', strtotime($item['create_time'])); + if ($params['type'] == 1) { + $item['price'] = $item['purchase_price']; + } else { + $item['price'] = $item['purchase']; + } + } + asort($list); + return [ + 'name' => '价格趋势', + 'series' => [['name' => '价格', 'value' => array_column($list, 'price')]], + 'x' => array_column($list, 'date'), + ]; + } + +} \ No newline at end of file diff --git a/app/psi/validate/StoreProductPriceValidate.php b/app/psi/validate/StoreProductPriceValidate.php new file mode 100644 index 0000000..691642a --- /dev/null +++ b/app/psi/validate/StoreProductPriceValidate.php @@ -0,0 +1,82 @@ + 'require', + ]; + + + /** + * 参数描述 + * @var string[] + */ + protected $field = [ + 'id' => 'id', + ]; + + + /** + * @notes 添加场景 + * @return StoreProductPriceValidate + * @author admin + * @date 2025/04/03 15:19 + */ + public function sceneAdd() + { + return $this->remove('id', true); + } + + + /** + * @notes 编辑场景 + * @return StoreProductPriceValidate + * @author admin + * @date 2025/04/03 15:19 + */ + public function sceneEdit() + { + return $this->only(['id']); + } + + + /** + * @notes 删除场景 + * @return StoreProductPriceValidate + * @author admin + * @date 2025/04/03 15:19 + */ + public function sceneDelete() + { + return $this->only(['id']); + } + + + /** + * @notes 详情场景 + * @return StoreProductPriceValidate + * @author admin + * @date 2025/04/03 15:19 + */ + public function sceneDetail() + { + return $this->only(['id']); + } + +} \ No newline at end of file diff --git a/config/thinkorm.php b/config/thinkorm.php index 87668ed..9783c8c 100644 --- a/config/thinkorm.php +++ b/config/thinkorm.php @@ -47,5 +47,53 @@ return [ // 数据库表前缀 'prefix' => 'la_', ], + 'store' => [ + // 数据库类型 + 'type' => 'mysql', + // 服务器地址 + 'hostname' => '47.109.71.135', + // 数据库名 + 'database' => 'multi_store', + // 数据库用户名 + 'username' => 'multi_store', + // 数据库密码 + 'password' => 'N4SiNcemsmcQrAca', + // 数据库连接端口 + 'hostport' => 3306, + // 数据库编码默认采用utf8 + 'charset' => 'utf8mb4', + // 数据库表前缀 + 'prefix' => 'la_', + // 断线重连 + 'break_reconnect' => true, + // 关闭SQL监听日志 + 'trigger_sql' => false, + // 自定义分页类 + 'bootstrap' => '' + ], + 'erp' => [ + // 数据库类型 + 'type' => 'mysql', + // 服务器地址 + 'hostname' => '47.109.71.135', + // 数据库名 + 'database' => 'multi_store', + // 数据库用户名 + 'username' => 'multi_store', + // 数据库密码 + 'password' => 'N4SiNcemsmcQrAca', + // 数据库连接端口 + 'hostport' => 3306, + // 数据库编码默认采用utf8 + 'charset' => 'utf8mb4', + // 数据库表前缀 + 'prefix' => 'la_', + // 断线重连 + 'break_reconnect' => true, + // 关闭SQL监听日志 + 'trigger_sql' => false, + // 自定义分页类 + 'bootstrap' => '' + ], ], ];