ShMethodClass.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. <?php
  2. /**
  3. * 用途:配送方式配置业务逻辑类
  4. * 谁用:供货商系统
  5. * 解决什么问题:处理配送方式的查询、保存、默认初始化等业务逻辑
  6. */
  7. namespace bizGhs\order\classes;
  8. use bizGhs\base\classes\BaseClass;
  9. use common\components\dict;
  10. use Yii;
  11. class ShMethodClass extends BaseClass
  12. {
  13. public static $baseFile = '\bizGhs\order\models\ShMethod';
  14. /**
  15. * 获取所有配送方式的排序和别名信息
  16. * @param int $mainId 商户ID
  17. * @return array
  18. */
  19. public static function getSorts($mainId)
  20. {
  21. $list = [];
  22. $aliases = [
  23. 0 => '送货',
  24. 1 => '自取',
  25. 2 => '跑腿',
  26. 3 => '物流',
  27. 4 => '快递'
  28. ];
  29. for ($style = 0; $style <= 4; $style++) {
  30. $config = self::getByCondition(['mainId' => $mainId, 'style' => $style]);
  31. $sort = 0;
  32. $alias = $aliases[$style];
  33. $status = 1;
  34. if (!empty($config)) {
  35. $sort = isset($config['sort']) ? (int)$config['sort'] : 0;
  36. $alias = !empty($config['name']) ? $config['name'] : $aliases[$style];
  37. $status = isset($config['status']) ? (int)$config['status'] : 1;
  38. }
  39. $list[] = [
  40. 'style' => $style,
  41. 'name' => $alias,
  42. 'sort' => $sort,
  43. 'status' => $status
  44. ];
  45. }
  46. return $list;
  47. }
  48. /**
  49. * 获取指定门店和类型的配送方式配置,若不存在则进行默认初始化
  50. * @param int $shopId 门店ID
  51. * @param int $mainId 商户ID
  52. * @param int $style 配送类型 (0: 送货, 1: 自取, 2: 跑腿, 3: 物流, 4: 快递)
  53. * @return array
  54. */
  55. public static function getConfig($shopId, $mainId, $style)
  56. {
  57. // 复杂分支/关键逻辑:优化。后端的查询全部由 shopId 改为 mainId,只根据 mainId 和 style 进行查询。
  58. $config = self::getByCondition(['mainId' => $mainId, 'style' => $style]);
  59. if (empty($config)) {
  60. // 从字典配置中读取对应类型的默认配置
  61. $defaultConfig = dict::getDict('shMethod', $style);
  62. $initData = array_merge([
  63. 'shopId' => $shopId, // shopId 仅作为保存预留字段存入
  64. 'mainId' => $mainId,
  65. 'style' => $style,
  66. ], $defaultConfig);
  67. $config = self::add($initData, true);
  68. $config = $config->toArray();
  69. }
  70. // 获取关联的说明项
  71. $config['explains'] = ShExplainClass::getAllByCondition(
  72. ['methodId' => $config['id']],
  73. 'sort ASC, id ASC'
  74. );
  75. // 如果 is_跑腿 (style为2),获取关联的满减规则
  76. if ($style == 2) {
  77. $config['reduceRules'] = ShReduceRuleClass::getAllByCondition(
  78. ['methodId' => $config['id']],
  79. 'sort ASC, id ASC'
  80. );
  81. } else {
  82. $config['reduceRules'] = [];
  83. }
  84. return $config;
  85. }
  86. /**
  87. * 一次性获取商户所有的5种配送方式配置,减少数据库查询交互。
  88. * 如果数据库里没有对应配置,则自动采用 dict.php 里的默认参数进行填充并完成入库。
  89. * @param int $shopId 门店ID
  90. * @param int $mainId 商户ID
  91. * @return array
  92. */
  93. public static function getAllConfigs($shopId, $mainId)
  94. {
  95. // 1. 一次性从数据库中查询当前商户的所有配送方式配置
  96. $configsMap = self::getAllByCondition(['mainId' => $mainId], 'sort asc', '*', 'style', true);
  97. // 2. 补齐缺失的配送方式,并做初始化入库
  98. for ($style = 0; $style <= 4; $style++) {
  99. if (!isset($configsMap[$style])) {
  100. $defaultConfig = dict::getDict('shMethod', $style);
  101. $initData = array_merge([
  102. 'shopId' => $shopId, // shopId 仅作为保存预留字段存入
  103. 'mainId' => $mainId,
  104. 'style' => $style,
  105. ], $defaultConfig);
  106. $configObj = self::add($initData, true);
  107. $configsMap[$style] = $configObj;
  108. }
  109. }
  110. // 将 ActiveRecord 统一转换为 array,并提取 methodIds 用于批量子表查询
  111. $configsArray = [];
  112. $methodIds = [];
  113. foreach ($configsMap as $style => $configObj) {
  114. $configArr = $configObj instanceof \yii\db\ActiveRecord ? $configObj->toArray() : $configObj;
  115. $configsArray[$style] = $configArr;
  116. $methodIds[] = (int)$configArr['id'];
  117. }
  118. // 3. 批量查询所有的说明项 (xhShExplain) - 仅 1 次查询
  119. $allExplains = [];
  120. if (!empty($methodIds)) {
  121. $allExplains = ShExplainClass::getAllByCondition(['methodId' => ['in', $methodIds]], 'sort ASC, id ASC');
  122. }
  123. $explainsMap = [];
  124. foreach ($allExplains as $exp) {
  125. $explainsMap[(int)$exp['methodId']][] = $exp;
  126. }
  127. // 4. 批量查询所有的跑腿满减规则 (xhShReduceRule) - 仅 1 次查询
  128. $allReduceRules = [];
  129. if (!empty($methodIds)) {
  130. $allReduceRules = ShReduceRuleClass::getAllByCondition(['methodId' => ['in', $methodIds]], 'sort ASC, id ASC');
  131. }
  132. $reduceRulesMap = [];
  133. foreach ($allReduceRules as $rule) {
  134. $reduceRulesMap[(int)$rule['methodId']][] = $rule;
  135. }
  136. // 5. 将批量查出的说明项和规则,合并填充到 5 个配送方式中
  137. $result = [];
  138. for ($style = 0; $style <= 4; $style++) {
  139. $config = $configsArray[$style];
  140. $methodId = (int)$config['id'];
  141. $config['explains'] = $explainsMap[$methodId] ?? [];
  142. $config['reduceRules'] = ($style == 2) ? ($reduceRulesMap[$methodId] ?? []) : [];
  143. $result[] = $config;
  144. }
  145. // 按 sort 升序返回,供 hd/ghs GetAllConfig 等接口展示自定义排序
  146. usort($result, function ($a, $b) {
  147. $sortCompare = (int)($a['sort'] ?? 0) <=> (int)($b['sort'] ?? 0);
  148. if ($sortCompare !== 0) {
  149. return $sortCompare;
  150. }
  151. // sort 相同时按 style 稳定排序,避免顺序抖动
  152. return (int)($a['style'] ?? 0) <=> (int)($b['style'] ?? 0);
  153. });
  154. return $result;
  155. }
  156. /**
  157. * 保存配送方式配置,包含说明项和满减规则
  158. * @param int $shopId 门店ID
  159. * @param int $mainId 商户ID
  160. * @param array $data 配置数据
  161. * @return bool
  162. * @throws \Exception
  163. */
  164. public static function saveConfig($shopId, $mainId, $data)
  165. {
  166. $id = $data['id'] ?? 0;
  167. $style = $data['style'] ?? 0;
  168. $config = null;
  169. if ($id > 0) {
  170. // 复杂分支/关键逻辑:优化。后端的查询全部由 shopId 改为 mainId。
  171. $config = self::getByCondition(['id' => $id, 'mainId' => $mainId], true);
  172. }
  173. if (empty($config)) {
  174. // 复杂分支/关键逻辑:优化。后端的查询全部由 shopId 改为 mainId。
  175. $config = self::getByCondition(['mainId' => $mainId, 'style' => $style], true);
  176. }
  177. $saveData = [
  178. 'name' => $data['name'] ?? '',
  179. 'status' => isset($data['status']) ? (int)$data['status'] : 1,
  180. 'sort' => isset($data['sort']) ? (int)$data['sort'] : 0,
  181. 'minAmount' => isset($data['minAmount']) ? (float)$data['minAmount'] : 0.00,
  182. 'minNum' => isset($data['minNum']) ? (int)$data['minNum'] : 0,
  183. 'unMeet' => isset($data['unMeet']) ? (int)$data['unMeet'] : 0,
  184. 'unMeetFee' => isset($data['unMeetFee']) ? (float)$data['unMeetFee'] : 0.00,
  185. 'startKm' => isset($data['startKm']) ? (float)$data['startKm'] : 0.00,
  186. 'startPrice' => isset($data['startPrice']) ? (float)$data['startPrice'] : 0.00,
  187. 'perKmPrice' => isset($data['perKmPrice']) ? (float)$data['perKmPrice'] : 0.00,
  188. 'changeRate' => isset($data['changeRate']) ? (float)$data['changeRate'] : 0.00,
  189. ];
  190. $transaction = Yii::$app->db->beginTransaction();
  191. try {
  192. if (empty($config)) {
  193. $saveData['shopId'] = $shopId; // shopId 作为保存预留字段存入
  194. $saveData['mainId'] = $mainId;
  195. $saveData['style'] = $style;
  196. $config = self::add($saveData, true);
  197. } else {
  198. self::updateByCondition(['id' => $config->id], $saveData);
  199. }
  200. $methodId = $config->id;
  201. // 1. 保存说明项 (xhShExplain)
  202. ShExplainClass::deleteByCondition(['methodId' => $methodId]);
  203. if (!empty($data['explains']) && is_array($data['explains'])) {
  204. $explainRows = [];
  205. foreach ($data['explains'] as $index => $exp) {
  206. if (empty($exp['explain'])) {
  207. continue;
  208. }
  209. $explainRows[] = [
  210. 'methodId' => $methodId,
  211. 'explain' => $exp['explain'],
  212. 'color' => isset($exp['color']) ? (int)$exp['color'] : 1,
  213. 'fontWeight' => isset($exp['fontWeight']) ? (int)$exp['fontWeight'] : 1,
  214. 'sort' => isset($exp['sort']) ? (int)$exp['sort'] : $index,
  215. ];
  216. }
  217. if (!empty($explainRows)) {
  218. ShExplainClass::batchAdd($explainRows);
  219. }
  220. }
  221. // 2. 保存跑腿满减规则 (xhShReduceRule)
  222. ShReduceRuleClass::deleteByCondition(['methodId' => $methodId]);
  223. if ($style == 2 && !empty($data['reduceRules']) && is_array($data['reduceRules'])) {
  224. $ruleRows = [];
  225. foreach ($data['reduceRules'] as $index => $rule) {
  226. $ruleRows[] = [
  227. 'methodId' => $methodId,
  228. 'meetNum' => isset($rule['meetNum']) ? (int)$rule['meetNum'] : 0,
  229. 'meetAmount' => isset($rule['meetAmount']) ? (float)$rule['meetAmount'] : 0.00,
  230. 'freeKm' => isset($rule['freeKm']) ? (float)$rule['freeKm'] : 0.00,
  231. 'sort' => isset($rule['sort']) ? (int)$rule['sort'] : $index,
  232. ];
  233. }
  234. if (!empty($ruleRows)) {
  235. ShReduceRuleClass::batchAdd($ruleRows);
  236. }
  237. }
  238. $transaction->commit();
  239. return true;
  240. } catch (\Exception $e) {
  241. $transaction->rollBack();
  242. throw $e;
  243. }
  244. }
  245. }