Pv.php 5.5 KB

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