| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- <?php
- /**
- * 用途:分销规则业务(xhDistributionRule / Tier / Scope)
- * 谁用:hdApp 应用-门店设置-分销规则
- */
- namespace bizHd\distribution\classes;
- use bizHd\base\classes\BaseClass;
- use Yii;
- class DistributionRuleClass extends BaseClass
- {
- public static $baseFile = '\bizHd\distribution\models\DistributionRule';
- /**
- * 获取门店分销规则(无则返回默认结构)
- * @param int $shopId
- * @param int $mainId
- * @return array
- */
- public static function getRule($shopId, $mainId)
- {
- $rule = self::getByCondition(['shopId' => $shopId]);
- if (empty($rule)) {
- return self::defaultRule($shopId, $mainId);
- }
- $ruleId = (int)$rule['id'];
- $tiers = DistributionRuleTierClass::getAllByCondition(['ruleId' => $ruleId], 'sort ASC, id ASC');
- $scopes = DistributionRuleScopeClass::getAllByCondition(['ruleId' => $ruleId], 'id ASC');
- $goodsIds = [];
- $categoryIds = [];
- foreach ($scopes as $row) {
- if ((int)$row['scopeType'] === 1) {
- $goodsIds[] = (int)$row['targetId'];
- } elseif ((int)$row['scopeType'] === 2) {
- $categoryIds[] = (int)$row['targetId'];
- }
- }
- $rule['tiers'] = $tiers ?: self::defaultTiers(false);
- $rule['goodsIds'] = $goodsIds;
- $rule['categoryIds'] = $categoryIds;
- return $rule;
- }
- /**
- * 保存分销规则
- * @param int $shopId
- * @param int $mainId
- * @param array $data
- * @throws \Exception
- */
- public static function saveRule($shopId, $mainId, $data)
- {
- self::validateRulePayload($data);
- $existing = self::getByCondition(['shopId' => $shopId], true);
- $saveData = [
- 'shopId' => $shopId,
- 'mainId' => $mainId,
- 'status' => isset($data['status']) ? (int)$data['status'] : 0,
- 'settleDays' => isset($data['settleDays']) ? (int)$data['settleDays'] : 0,
- 'bonusType' => isset($data['bonusType']) ? (int)$data['bonusType'] : 1,
- 'bonusRate' => isset($data['bonusRate']) ? round((float)$data['bonusRate'], 2) : 0,
- 'durationType' => isset($data['durationType']) ? (int)$data['durationType'] : 1,
- 'durationDays' => isset($data['durationDays']) ? (int)$data['durationDays'] : 0,
- 'timeStartType' => isset($data['timeStartType']) ? (int)$data['timeStartType'] : 1,
- 'productScope' => isset($data['productScope']) ? (int)$data['productScope'] : 1,
- ];
- $transaction = Yii::$app->db->beginTransaction();
- try {
- if (empty($existing)) {
- $model = self::add($saveData, true);
- $ruleId = (int)$model->id;
- } else {
- self::updateByCondition(['id' => $existing->id], $saveData);
- $ruleId = (int)$existing->id;
- }
- DistributionRuleTierClass::deleteByCondition(['ruleId' => $ruleId]);
- if ((int)$saveData['bonusType'] === 2) {
- $tierRows = [];
- foreach ($data['tiers'] as $index => $tier) {
- $tierRows[] = [
- 'ruleId' => $ruleId,
- 'minDays' => (int)$tier['minDays'],
- 'maxDays' => (int)$tier['maxDays'],
- 'bonusRate' => round((float)$tier['bonusRate'], 2),
- 'sort' => isset($tier['sort']) ? (int)$tier['sort'] : $index,
- ];
- }
- if (!empty($tierRows)) {
- DistributionRuleTierClass::batchAdd($tierRows);
- }
- }
- DistributionRuleScopeClass::deleteByCondition(['ruleId' => $ruleId]);
- $scopeRows = [];
- $productScope = (int)$saveData['productScope'];
- if ($productScope === 2 && !empty($data['goodsIds']) && is_array($data['goodsIds'])) {
- foreach ($data['goodsIds'] as $gid) {
- $gid = (int)$gid;
- if ($gid > 0) {
- $scopeRows[] = ['ruleId' => $ruleId, 'scopeType' => 1, 'targetId' => $gid];
- }
- }
- }
- if ($productScope === 3 && !empty($data['categoryIds']) && is_array($data['categoryIds'])) {
- foreach ($data['categoryIds'] as $cid) {
- $cid = (int)$cid;
- if ($cid > 0) {
- $scopeRows[] = ['ruleId' => $ruleId, 'scopeType' => 2, 'targetId' => $cid];
- }
- }
- }
- if (!empty($scopeRows)) {
- DistributionRuleScopeClass::batchAdd($scopeRows);
- }
- $transaction->commit();
- } catch (\Exception $e) {
- $transaction->rollBack();
- throw $e;
- }
- }
- /**
- * 校验提交参数
- * @param array $data
- * @throws \Exception
- */
- protected static function validateRulePayload($data)
- {
- $settleDays = isset($data['settleDays']) ? (int)$data['settleDays'] : 0;
- if ($settleDays < 0) {
- throw new \Exception('佣金发放天数不能为负');
- }
- $bonusType = isset($data['bonusType']) ? (int)$data['bonusType'] : 1;
- if ($bonusType === 1) {
- $rate = isset($data['bonusRate']) ? (float)$data['bonusRate'] : 0;
- if ($rate <= 0 || $rate > 100) {
- throw new \Exception('请填写正确的固定佣金比例(0-100)');
- }
- $durationType = isset($data['durationType']) ? (int)$data['durationType'] : 1;
- if ($durationType === 2) {
- $durationDays = isset($data['durationDays']) ? (int)$data['durationDays'] : 0;
- if ($durationDays <= 0) {
- throw new \Exception('请填写分红限制天数');
- }
- }
- } else {
- $tiers = isset($data['tiers']) && is_array($data['tiers']) ? $data['tiers'] : [];
- if (empty($tiers)) {
- throw new \Exception('请至少添加一个时间阶梯');
- }
- self::validateTiers($tiers);
- }
- $productScope = isset($data['productScope']) ? (int)$data['productScope'] : 1;
- if ($productScope === 2) {
- $goodsIds = isset($data['goodsIds']) && is_array($data['goodsIds']) ? $data['goodsIds'] : [];
- if (empty($goodsIds)) {
- throw new \Exception('请选择参与分红的商品');
- }
- }
- if ($productScope === 3) {
- $categoryIds = isset($data['categoryIds']) && is_array($data['categoryIds']) ? $data['categoryIds'] : [];
- if (empty($categoryIds)) {
- throw new \Exception('请选择参与分红的分类');
- }
- }
- }
- /**
- * 校验时间阶梯:不可重叠、不可留空
- * @param array $tiers
- * @throws \Exception
- */
- protected static function validateTiers($tiers)
- {
- $normalized = [];
- foreach ($tiers as $tier) {
- $minDays = isset($tier['minDays']) ? (int)$tier['minDays'] : -1;
- $maxDays = isset($tier['maxDays']) ? (int)$tier['maxDays'] : -1;
- $rate = isset($tier['bonusRate']) ? (float)$tier['bonusRate'] : 0;
- if ($minDays < 0) {
- throw new \Exception('时间阶梯起始天数不能为空');
- }
- if ($maxDays > 0 && $maxDays < $minDays) {
- throw new \Exception('时间阶梯结束天数不能小于起始天数');
- }
- if ($rate <= 0 || $rate > 100) {
- throw new \Exception('请填写正确的阶梯佣金比例');
- }
- $normalized[] = ['min' => $minDays, 'max' => $maxDays, 'rate' => $rate];
- }
- usort($normalized, function ($a, $b) {
- return $a['min'] - $b['min'];
- });
- $unlimitedCount = 0;
- for ($i = 0; $i < count($normalized); $i++) {
- $cur = $normalized[$i];
- if ($cur['max'] === 0) {
- $unlimitedCount++;
- if ($i !== count($normalized) - 1) {
- throw new \Exception('「及以上」阶梯只能放在最后一行');
- }
- }
- if ($i > 0) {
- $prev = $normalized[$i - 1];
- if ($prev['max'] <= 0) {
- throw new \Exception('时间阶梯区间不可重叠');
- }
- if ($cur['min'] <= $prev['max']) {
- throw new \Exception('时间阶梯区间不可重叠');
- }
- }
- }
- }
- /**
- * 默认规则(未保存过)
- */
- protected static function defaultRule($shopId, $mainId)
- {
- return [
- 'id' => 0,
- 'shopId' => $shopId,
- 'mainId' => $mainId,
- 'status' => 0,
- 'settleDays' => 5,
- 'bonusType' => 1,
- 'bonusRate' => '0.00',
- 'durationType' => 1,
- 'durationDays' => 0,
- 'timeStartType' => 1,
- 'productScope' => 1,
- 'tiers' => self::defaultTiers(true),
- 'goodsIds' => [],
- 'categoryIds' => [],
- ];
- }
- /**
- * 默认递减阶梯示例
- */
- protected static function defaultTiers($asNew = true)
- {
- $rows = [
- ['minDays' => 0, 'maxDays' => 30, 'bonusRate' => '10.00', 'sort' => 0],
- ['minDays' => 31, 'maxDays' => 60, 'bonusRate' => '5.00', 'sort' => 1],
- ['minDays' => 61, 'maxDays' => 0, 'bonusRate' => '2.00', 'sort' => 2],
- ];
- if (!$asNew) {
- return $rows;
- }
- return array_map(function ($row) {
- return array_merge($row, ['id' => 0]);
- }, $rows);
- }
- }
|