Pv.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. <?php
  2. namespace app\common\utils;
  3. use app\common\dao\profit\ProductPvDao;
  4. use app\common\dao\store\order\StoreCartDao;
  5. use app\common\dao\store\order\StoreOrderDao;
  6. use app\common\dao\user\UserDao;
  7. use app\common\enum\store\StoreOrderEnum;
  8. /**
  9. * PV业绩计算工具类
  10. *
  11. * 用于计算用户的业绩(PV)值,基于订单和购物车数据进行统计
  12. * PV值根据商品配置的PV系数和购买数量计算得出
  13. */
  14. class Pv
  15. {
  16. /**
  17. * 商户ID,默认为496
  18. * @var int
  19. */
  20. private $merId = 496;
  21. /**
  22. * 订单状态数组,包含有效的订单状态值
  23. * 0,1,2,3 可能代表:待付款、已付款、已发货、已完成等状态
  24. * @var array
  25. */
  26. private $status = [
  27. StoreOrderEnum::STATUS['WAITING_SHIPMENT']['code'],
  28. StoreOrderEnum::STATUS['WAITING_RECEIVE']['code'],
  29. StoreOrderEnum::STATUS['WAITING_EVALUATION']['code'],
  30. StoreOrderEnum::STATUS['COMPLETED']['code']
  31. ];
  32. /**
  33. * 需要排除的测试用户ID列表
  34. * 在计算业绩时需要过滤掉的测试用户
  35. * @var array
  36. */
  37. private $removeUserIdList;
  38. /**
  39. * 订单数据访问对象
  40. * @var StoreOrderDao
  41. */
  42. public $storeOrderDao;
  43. /**
  44. * 购物车数据访问对象
  45. * @var StoreCartDao
  46. */
  47. public $cartDao;
  48. /**
  49. * 用户数据访问对象
  50. * @var UserDao
  51. */
  52. public $userDao;
  53. public $pvDao;
  54. /**
  55. * 构造函数
  56. * 初始化数据访问对象和测试用户列表
  57. */
  58. public function __construct()
  59. {
  60. $this->storeOrderDao = new StoreOrderDao();
  61. $this->cartDao = new StoreCartDao();
  62. $this->userDao = new UserDao();
  63. $this->pvDao = new ProductPvDao();
  64. $this->removeUserIdList = $this->getRemoveUserIdList();
  65. }
  66. /**
  67. * 获取商品PV配置
  68. *
  69. * 返回商品ID到PV系数的映射数组
  70. * PV系数表示每个商品对应的业绩值
  71. *
  72. * @return int[] 商品PV配置数组,格式:[商品ID => PV系数]
  73. */
  74. public function getPvConfig(): array
  75. {
  76. return $this->pvDao->getData();
  77. }
  78. /**
  79. * 计算用户业绩(PV)
  80. *
  81. * 根据用户ID和时间范围计算业绩值
  82. * 流程:获取订单数据 → 获取购物车数据 → 统计商品数量 → 计算PV总值
  83. *
  84. * @param array $userId 用户ID数组,默认为空数组
  85. * @param int $startTime 开始时间戳,0表示无限制
  86. * @param int $endTime 结束时间戳,0表示无限制
  87. * @return void 直接输出计算结果(使用dd函数)
  88. */
  89. public function countPv($userId = [], $startTime = 0, $endTime = 0): void
  90. {
  91. // 测试用户id(硬编码,实际应该使用传入的参数)
  92. // $userId = [1592];
  93. // 时间范围示例(注释掉的代码)
  94. // $startTime = '2025-9-8';
  95. // $endTime = '2025-9-11';
  96. // 获取订单数据(过滤掉测试用户)
  97. $orderData = $this->storeOrderDao->getDataForPv(
  98. $userId,
  99. $startTime,
  100. $endTime,
  101. $this->merId,
  102. $this->status,
  103. $this->removeUserIdList
  104. );
  105. // 提取所有购物车ID
  106. $cartIds = array_column($orderData, 'cart_id');
  107. // 根据购物车ID获取购物车数据
  108. $cartData = $this->cartDao->getDataByIds($cartIds);
  109. // 统计每个商品的出现次数
  110. $productCount = $this->countProductIds($cartData);
  111. // 根据商品数量和PV配置计算总PV值
  112. $pv = $this->countResult($productCount);
  113. // 输出计算结果(调试用)
  114. dd($pv);
  115. }
  116. /**
  117. * 获取需要排除的测试用户ID列表
  118. *
  119. * 从用户DAO获取标记为测试用户的ID列表
  120. * 这些用户在计算业绩时会被排除
  121. *
  122. * @return array 测试用户ID数组
  123. */
  124. private function getRemoveUserIdList(): array
  125. {
  126. return $this->userDao->getTestUser();
  127. }
  128. /**
  129. * 统计购物车数据中商品ID的出现次数
  130. *
  131. * 遍历购物车数据,统计每个商品ID的购买次数
  132. *
  133. * @param array $cartData 购物车数据数组,包含商品信息
  134. * @return array 商品ID统计结果,格式:[商品ID => 购买次数]
  135. */
  136. private function countProductIds(array $cartData): array
  137. {
  138. $productIdCounts = [];
  139. foreach ($cartData as $cartItem) {
  140. $productId = $cartItem['product_id'];
  141. if (isset($productIdCounts[$productId])) {
  142. // 如果商品已存在,增加计数
  143. $productIdCounts[$productId]++;
  144. } else {
  145. // 如果商品不存在,初始化计数为1
  146. $productIdCounts[$productId] = 1;
  147. }
  148. }
  149. return $productIdCounts;
  150. }
  151. /**
  152. * 计算最终PV结果
  153. *
  154. * 根据商品购买次数和PV配置计算总业绩值
  155. * 公式:总PV = Σ(商品购买次数 × 商品PV系数)
  156. *
  157. * @param array $productCount 商品购买次数数组,格式:[商品ID => 购买次数]
  158. * @return float|int 总PV值
  159. */
  160. private function countResult(array $productCount)
  161. {
  162. // 获取PV配置
  163. $pvConfig = $this->getPvConfig();
  164. $totalPv = 0;
  165. // 遍历每个商品计算PV贡献
  166. foreach ($productCount as $productId => $count) {
  167. if (isset($pvConfig[$productId])) {
  168. // 如果商品有配置PV系数,计算该商品的PV贡献
  169. $totalPv += $count * $pvConfig[$productId];
  170. }
  171. // 如果没有配置PV系数的商品,不计入业绩
  172. }
  173. return $totalPv;
  174. }
  175. }