UserBillDao.php 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2024 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. namespace app\common\dao\user;
  12. use app\common\dao\BaseDao;
  13. use app\common\model\BaseModel;
  14. use app\common\model\user\UserBill;
  15. /**
  16. * Class UserBillDao
  17. * @package app\common\dao\user
  18. * @author xaboy
  19. * @day 2020/6/22
  20. */
  21. class UserBillDao extends BaseDao
  22. {
  23. /**
  24. * @return BaseModel
  25. * @author xaboy
  26. * @day 2020-03-30
  27. */
  28. protected function getModel(): string
  29. {
  30. return UserBill::class;
  31. }
  32. /**
  33. * 更新用户账单信息
  34. *
  35. * 本函数用于根据指定条件更新用户账单的数据。通过传入更新条件和数据,精确更新数据库中的一条账单记录。
  36. * 这是一个重要的数据维护功能,确保了用户账单数据的准确性和实时性。
  37. *
  38. * @param array $where 更新条件数组,用于指定需要更新的账单记录。数组的键值对形式,键为字段名,值为字段值。
  39. * @param array $data 更新的数据数组,用于指定更新后的值。数组的键值对形式,键为字段名,值为新的字段值。
  40. * @return int 返回影响的行数,如果更新成功,返回1;如果未找到符合条件的记录或者更新失败,则返回0。
  41. */
  42. public function updateBill(array $where, $data)
  43. {
  44. // 获取数据库操作对象
  45. $db = UserBill::getDB();
  46. // 设置更新条件
  47. $db->where($where);
  48. // 限制只更新一条记录
  49. $db->limit(1);
  50. // 执行更新操作,并返回影响的行数
  51. return $db->update($data);
  52. }
  53. /**
  54. * 获取超时未处理的经纪费账单
  55. *
  56. * 本函数用于查询指定时间之前,状态为未处理的经纪费账单。这些账单可以是订单一或订单二类型的经纪费。
  57. * 主要用于统计或管理需要跟进的经纪费账单情况。
  58. *
  59. * @param int $time 查询的时间点,通常为时间戳形式,表示查询小于等于该时间的记录。
  60. * @return Collection|array|\think\Collection|\think\db\BaseQuery[]
  61. */
  62. public function getTimeoutBrokerageBill($time)
  63. {
  64. // 通过UserBill的getDB方法获取数据库实例,并链式调用where方法设置查询条件
  65. // 本行注释解释了为何使用where('create_time', '<=', $time)和where('category', 'brokerage')
  66. // 这两个条件用于限定查询的时间范围和账单类型
  67. return UserBill::getDB()->where('create_time', '<=', $time)->where('category', 'brokerage')
  68. // 使用whereIn方法限定查询的账单类型为'order_one'或'order_two'
  69. // 这一行注释解释了为何使用whereIn('type', ['order_one', 'order_two'])
  70. ->whereIn('type', ['order_one', 'order_two'])->with('user')->where('status', 0)->select();
  71. }
  72. /**
  73. * 获取过期积分账单
  74. *
  75. * 本函数用于查询指定时间之前,类型为锁定积分的账单记录。
  76. * 这些账单处于未处理状态(即状态为0),并关联了相应的用户信息。
  77. * 主要用于处理过期积分的统计和管理。
  78. *
  79. * @param int $time 以时间戳形式表示的截止时间
  80. * @return array|\think\Collection|\think\db\BaseQuery[]
  81. */
  82. public function getTimeoutIntegralBill($time)
  83. {
  84. // 通过UserBill的getDB方法获取数据库实例,并链式调用where方法设置查询条件
  85. // 包括创建时间小于等于指定时间、分类为积分、类型为锁定、状态为0
  86. // 最后使用with方法加载关联的用户信息,并通过select方法执行查询
  87. return UserBill::getDB()->where('create_time', '<=', $time)->where('category', 'integral')
  88. ->where('type', 'lock')->with('user')->where('status', 0)->select();
  89. }
  90. /**
  91. * 获取超时未处理的商家结算账单
  92. *
  93. * 本函数用于查询指定时间之前,且状态为未处理的商家结算账单。
  94. * 这些账单可能是由于订单支付超时或其他原因尚未进行结算。
  95. * 通过筛选创建时间、类别、类型和状态,精确获取目标账单数据。
  96. *
  97. * @param int $time 查询的时间点,通常为时间戳形式。
  98. * @return array 返回符合条件的商家结算账单数据集合。
  99. */
  100. public function getTimeoutMerchantMoneyBill($time)
  101. {
  102. // 使用UserBill类的getDB方法获取数据库实例,并链式调用where方法设置查询条件。
  103. // 查询条件包括:创建时间不晚于指定时间、类别为mer_computed_money、类型为order、状态为0(未处理)。
  104. // 最后调用select方法执行查询并返回结果。
  105. return UserBill::getDB()->where('create_time', '<=', $time)->where('category', 'mer_computed_money')->where('type', 'order')
  106. ->where('status', 0)->select();
  107. }
  108. /**
  109. * 计算商家退款金额
  110. *
  111. * 本函数用于查询指定订单ID和商家ID下的特定类型退款金额。
  112. * 它通过查询用户账单表,筛选出符合条件的退款记录,并计算它们的总数。
  113. * 这样可以方便地获取商家的退款总额,以便进行财务结算。
  114. *
  115. * @param string $order_id 订单ID,用于关联退款记录和订单。
  116. * @param string $type 退款类型,用于区分不同的退款情况。
  117. * @param string $mer_id 商家ID,用于限定查询商家的退款记录。
  118. * @return float 返回符合条件的退款金额总和。
  119. */
  120. public function refundMerchantMoney($order_id, $type, $mer_id)
  121. {
  122. // 使用where子句筛选出特定订单ID、商家ID、类别为'mer_refund_money'且类型为参数$type的记录,然后计算number列的总和。
  123. return UserBill::getDB()->where('link_id', $order_id)->where('mer_id', $mer_id)
  124. ->where('category', 'mer_refund_money')->where('type', $type)->sum('number');
  125. }
  126. /**
  127. * 计算商家锁定的资金总额。
  128. *
  129. * 本函数用于根据指定的商家ID,计算该商家目前被锁定的资金总额。
  130. * 锁定的资金包括:待处理的锁定资金、退款资金和订单计算资金。
  131. *
  132. * @param string|null $merId 商家ID,如果为null,则计算所有商家的锁定资金总额。
  133. * @return float 返回商家锁定的资金总额。
  134. */
  135. public function merchantLickMoney($merId = null)
  136. {
  137. // 查询待处理的商家锁定资金记录,根据商家ID进行过滤。
  138. $lst = UserBill::getDB()->where('category', 'mer_lock_money')->when($merId, function ($query, $val) {
  139. $query->where('mer_id', $val);
  140. })->where('status', 0)->select()->toArray();
  141. // 初始化锁定资金总额为0。
  142. $lockMoney = 0;
  143. // 如果有锁定资金记录,计算已退款金额并从中扣除。
  144. if (count($lst)) {
  145. $lockMoney = -1 * UserBill::getDB()->whereIn('link_id', array_column($lst, 'link_id'))
  146. ->where('category', 'mer_refund_money')->sum('number');
  147. }
  148. // 累加所有的锁定资金到$lockMoney。
  149. foreach ($lst as $bill) {
  150. $lockMoney = bcadd($lockMoney, $bill['number'], 2);
  151. }
  152. // 加上订单计算产生的锁定资金。
  153. $lockMoney = bcadd($lockMoney, UserBill::getDB()
  154. ->where('category', 'mer_computed_money')->when($merId, function ($query, $val) {
  155. $query->where('mer_id', $val);
  156. })->where('status', 0)->where('type', 'order')->sum('number'), 2);
  157. // 返回计算得到的商家锁定资金总额。
  158. return $lockMoney;
  159. }
  160. /**
  161. * 锁定经纪佣金
  162. * 该方法用于计算并返回指定用户ID的待处理(未结算)订单所产生的经纪佣金总和。
  163. * 这里的“锁定”指的是,通过计算这些未结算订单的佣金总额,为后续的佣金结算提供一个预估值。
  164. *
  165. * @param int $uid 用户ID,指定哪个用户的佣金需要被锁定计算。
  166. * @return float 返回计算得到的待处理佣金总和,以浮点数形式表示。
  167. */
  168. public function lockBrokerage($uid)
  169. {
  170. // 查询用户未结算的订单佣金记录,包括一级和二级订单产生的佣金。
  171. $lst = UserBill::getDB()->where('category', 'brokerage')
  172. ->whereIn('type', ['order_one', 'order_two'])->where('uid', $uid)->where('status', 0)->field('link_id,number')->select()->toArray();
  173. // 初始化退款金额为0,用于后续计算已退款的佣金。
  174. $refundPrice = 0;
  175. // 如果存在未结算的佣金记录,则计算已退款的佣金总额。
  176. if (count($lst)) {
  177. // 根据之前的佣金记录,查询相同订单链接ID下的退款佣金记录,并计算其总和。
  178. $refundPrice = -1 * UserBill::getDB()->whereIn('link_id', array_column($lst, 'link_id'))->where('uid', $uid)
  179. ->where('category', 'brokerage')->whereIn('type', ['refund_two', 'refund_one'])->sum('number');
  180. }
  181. // 遍历未结算佣金列表,累加所有未结算的佣金金额。
  182. foreach ($lst as $bill) {
  183. $refundPrice = bcadd($refundPrice, $bill['number'], 2);
  184. }
  185. // 返回计算得到的待处理佣金总和。
  186. return $refundPrice;
  187. }
  188. /**
  189. * 锁定积分的逻辑处理。
  190. * 该方法用于计算指定用户由于订单或其他操作而被锁定的积分总量。
  191. * 如果提供了订单ID,则只考虑与该订单相关的锁定积分;
  192. * 如果提供了用户ID,则返回该用户所有被锁定的积分,无论订单ID是否提供。
  193. *
  194. * @param integer $uid 用户ID。可选参数,用于限定查询的用户。
  195. * @param integer $order_id 订单ID。可选参数,用于限定查询与特定订单相关的锁定积分。
  196. * @return integer 返回锁定的积分总量。如果没有任何积分被锁定,返回0。
  197. */
  198. public function lockIntegral($uid = null, $order_id = null)
  199. {
  200. // 查询已经被锁定的积分记录,这些记录可能是由于不同的订单或其他操作导致的。
  201. $lst = UserBill::getDB()->where('category', 'integral')
  202. ->where('type', 'lock')->when($order_id, function ($query, $order_id) {
  203. // 如果提供了订单ID,则查询与该订单关联的锁定积分记录。
  204. $query->where('link_id', $order_id);
  205. })->when($uid, function ($query, $uid) {
  206. // 如果提供了用户ID,则查询该用户的所有锁定积分记录。
  207. $query->where('uid', $uid);
  208. })->where('status', 0)->field('link_id,number')->select()->toArray();
  209. // 初始化锁定的积分总量为0。
  210. $lockIntegral = 0;
  211. // 如果存在锁定的积分记录,则计算这些记录中的积分总量。
  212. if (count($lst)) {
  213. // 计算所有被退款锁定(即可能由于订单退款导致的积分锁定)的积分总量。
  214. $lockIntegral = -1 * UserBill::getDB()->whereIn('link_id', array_column($lst, 'link_id'))->where('uid', $uid)
  215. ->where('category', 'integral')->where('type', 'refund_lock')->sum('number');
  216. }
  217. // 遍历所有锁定积分记录,累加它们的数值到$lockIntegral中。
  218. foreach ($lst as $bill) {
  219. $lockIntegral = bcadd($lockIntegral, $bill['number'], 0);
  220. }
  221. // 返回锁定的积分总量。
  222. return $lockIntegral;
  223. }
  224. /**
  225. * 计算用户的积分扣除总量
  226. *
  227. * 本函数用于查询指定用户的所有积分扣除记录,并计算其积分扣除的总量。
  228. * 这里的积分扣除包括了正常扣除、退款锁定、超时扣除以及系统扣除等情况。
  229. *
  230. * @param integer $uid 用户ID
  231. * @return integer 用户的积分扣除总量
  232. */
  233. public function deductionIntegral($uid)
  234. {
  235. // 使用UserBill的数据库实例,查询满足条件的积分扣除记录,并计算积分数量的总和
  236. return UserBill::getDB()->where('uid', $uid)
  237. ->where('category', 'integral')
  238. ->where('pm', 0)
  239. ->whereIn('type', ['deduction', 'refund_lock', 'timeout', 'sys_dec'])
  240. ->where('status', 1)
  241. ->sum('number');
  242. }
  243. /**
  244. * 计算用户的积分收益总和
  245. *
  246. * 本函数通过查询用户积分账单,统计指定用户的所有积分收益额。
  247. * 积分收益来自符合条件的账单记录,这些记录代表了用户的积极积分变动,
  248. * 不包括退款、取消、退款锁定等负向操作。
  249. *
  250. * @param int $uid 用户ID
  251. * @return int 用户的积分收益总和
  252. */
  253. public function totalGainIntegral($uid)
  254. {
  255. // 根据用户ID、账单类型、积分变动方向、操作类型和状态,查询用户的积分收益账单
  256. return UserBill::getDB()->where('uid', $uid)
  257. ->where('category', 'integral')
  258. ->where('pm', 1) // 仅选择积分增加的记录
  259. ->whereNotIn('type', ['refund', 'cancel', 'refund_lock']) // 排除退款、取消、退款锁定等类型的操作
  260. ->where('status', 1) // 选择有效的账单记录
  261. ->sum('number'); // 计算符合条件的记录的积分总和
  262. }
  263. /**
  264. * 计算用户的总佣金
  265. *
  266. * 该方法通过查询用户的佣金收入和退款,来计算用户净佣金总额。
  267. * 具体来说,它首先汇总了所有订单产生的佣金(包括一级和二级订单),然后从中减去所有退款产生的佣金损失(包括一级和二级退款)。
  268. * 这样做的目的是为了得到用户实际获得的佣金总额,以精确反映用户的收入情况。
  269. *
  270. * @param int $uid 用户ID
  271. * @return string 返回计算后的总佣金,以字符串形式保持高精度
  272. */
  273. public function totalBrokerage($uid)
  274. {
  275. // 计算用户的佣金收入,包括一级和二级订单的佣金
  276. $income = UserBill::getDB()->where('category', 'brokerage')
  277. ->whereIn('type', ['order_one', 'order_two'])->where('uid', $uid)->sum('number');
  278. // 计算用户的佣金退款,包括一级和二级退款
  279. $refund = UserBill::getDB()->where('uid', $uid)
  280. ->where('category', 'brokerage')->whereIn('type', ['refund_two', 'refund_one'])->sum('number');
  281. // 返回用户的净佣金总额,保留两位小数
  282. return bcsub($income, $refund, 2);
  283. }
  284. /**
  285. * 计算指定用户昨日的佣金总额
  286. *
  287. * 本函数通过查询用户佣金账单,筛选出昨日的订单一和订单二的佣金记录,
  288. * 并计算这些记录的佣金总额。
  289. *
  290. * @param int $uid 用户ID
  291. * @return float 昨日佣金总额
  292. */
  293. public function yesterdayBrokerage($uid)
  294. {
  295. // 使用UserBill的数据库实例,并构造查询条件:分类为佣金,类型为订单一或订单二,用户ID为$uid
  296. // 然后获取昨日的时间范围
  297. // 最后计算符合条件的记录的number列(佣金金额)的总和
  298. return getModelTime(UserBill::getDB()->where('category', 'brokerage')
  299. ->whereIn('type', ['order_one', 'order_two'])->where('uid', $uid), 'yesterday')->sum('number');
  300. }
  301. /**
  302. * 根据条件搜索用户账单信息。
  303. *
  304. * 该方法提供了丰富的查询条件,能够根据传入的数组参数灵活地查询用户账单数据。
  305. * 主要支持的查询条件包括:现在金额(now_money)、用户ID(uid)、支付方式(pm)、类别(category)、
  306. * 状态(status)、日期(date)、具体日期(day)、月份(month)、类型(type)、商户ID(mer_id)和关联ID(link_id)。
  307. *
  308. * @param array $where 查询条件数组,包含各种可能的查询条件。
  309. * @return \think\db\BaseQuery|\think\db\Query
  310. */
  311. public function search(array $where)
  312. {
  313. // 获取数据库操作对象
  314. return UserBill::getDB()
  315. // 根据(now_money)条件筛选类别和类型
  316. ->when(isset($where['now_money']) && in_array($where['now_money'], [0, 1, 2]), function ($query) use ($where) {
  317. // 现在金额为0时的查询条件
  318. if ($where['now_money'] == 0) {
  319. $query->where('category', 'now_money')
  320. ->whereIn('type', ['pay_product', 'recharge', 'sys_inc_money', 'sys_dec_money', 'brokerage', 'presell', 'refund','extract']);
  321. // 现在金额为1时的查询条件
  322. } else if ($where['now_money'] == 1) {
  323. $query->where('category', 'now_money')
  324. ->whereIn('type', ['pay_product', 'sys_dec_money', 'presell']);
  325. // 现在金额为2时的查询条件
  326. } else if ($where['now_money'] == 2) {
  327. $query->where('category', 'now_money')
  328. ->whereIn('type', ['recharge', 'sys_inc_money', 'brokerage', 'refund','extract']);
  329. }
  330. })
  331. // 根据用户ID(uid)和商户ID(mer_id)查询
  332. ->when(isset($where['uid']) && $where['uid'] !== '', function ($query) use ($where) {
  333. $query->where('uid', $where['uid'])->where('mer_id', 0);
  334. })
  335. // 根据支付方式(pm)查询
  336. ->when(isset($where['pm']) && $where['pm'] !== '', function ($query) use ($where) {
  337. $query->where('pm', $where['pm']);
  338. })
  339. // 根据类别(category)查询
  340. ->when(isset($where['category']) && $where['category'] !== '', function ($query) use ($where) {
  341. $query->where('category', $where['category']);
  342. })
  343. // 根据状态(status)查询
  344. ->when(isset($where['status']) && $where['status'] !== '', function ($query) use ($where) {
  345. $query->where('status', $where['status']);
  346. })
  347. // 根据日期(date)查询
  348. ->when(isset($where['date']) && $where['date'] !== '', function ($query) use ($where) {
  349. getModelTime($query, $where['date'], 'create_time');
  350. })
  351. // 根据具体日期(day)查询
  352. ->when(isset($where['day']) && $where['day'] !== '', function ($query) use ($where) {
  353. $query->whereDay('create_time', $where['day']);
  354. })
  355. // 根据月份(month)查询
  356. ->when(isset($where['month']) && $where['month'] !== '', function ($query) use ($where) {
  357. $query->whereMonth('create_time', $where['month']);
  358. })
  359. // 根据类型(type)查询,支持多级类别查询
  360. ->when(isset($where['type']) && $where['type'] !== '', function ($query) use ($where) {
  361. $data = explode('/', $where['type'], 2);
  362. if (count($data) > 1) {
  363. $query->where('category', $data[0])->where('type', $data[1]);
  364. } else {
  365. $query->where('type', $where['type']);
  366. }
  367. })
  368. // 根据商户ID(mer_id)查询
  369. ->when(isset($where['mer_id']) && $where['mer_id'] !== '', function ($query) use ($where) {
  370. $query->where('mer_id', $where['mer_id']);
  371. })
  372. // 根据关联ID(link_id)查询
  373. ->when(isset($where['link_id']) && $where['link_id'] !== '', function ($query) use ($where) {
  374. $query->where('link_id', $where['link_id']);
  375. });
  376. }
  377. /**
  378. * 计算指定用户当前资金的总增加额
  379. *
  380. * 本函数用于查询数据库中指定用户的当前资金项(now_money)的增加总额。
  381. * 通过搜索满足条件的记录,其中条件包括用户ID(uid)和资金类型为2的记录,
  382. * 然后对这些记录的“number”字段进行求和操作,得到该用户的当前资金增加总额。
  383. *
  384. * @param int $uid 用户ID,用于指定要查询的用户。
  385. * @return float 返回查询结果,即指定用户当前资金的增加总额。
  386. */
  387. public function userNowMoneyIncTotal($uid)
  388. {
  389. // 根据用户ID和资金类型为2的条件查询,并对符合条件的记录的“number”字段进行求和
  390. return $this->search(['uid' => $uid, 'now_money' => 2])->sum('number');
  391. }
  392. /**
  393. * 根据条件搜索用户账单并联表查询
  394. *
  395. * 本函数用于根据提供的条件搜索用户的账单记录,并进行左连接操作以包含用户信息。
  396. * 支持的搜索条件包括:mer_id(商户ID)、type(账单类型)、date(日期范围)、keyword(关键词搜索)、category(账单分类)、uid(用户ID)。
  397. *
  398. * @param array $where 搜索条件数组,包含各种可能的搜索参数。
  399. * @return \think\Collection 返回搜索结果的集合。
  400. */
  401. public function searchJoin(array $where)
  402. {
  403. // 使用UserBill类的getDB方法获取数据库对象,并设置表别名为a
  404. return UserBill::getDB()->alias('a')
  405. // 左连接用户表b,根据a表的uid和b表的uid关联
  406. ->leftJoin('User b', 'a.uid = b.uid')
  407. // 指定查询的字段
  408. ->field('a.bill_id,a.pm,a.title,a.number,a.balance,a.mark,a.create_time,a.status,b.nickname,a.uid,a.category')
  409. // 当搜索条件中包含mer_id时,添加对应条件到查询
  410. ->when(isset($where['mer_id']) && $where['mer_id'] !== '', function ($query) use ($where) {
  411. $query->where('a.mer_id', $where['mer_id']);
  412. })
  413. // 当搜索条件中包含type时,根据type的值进行分类查询
  414. ->when(isset($where['type']) && $where['type'] !== '', function ($query) use ($where) {
  415. $data = explode('/', $where['type'], 2);
  416. if (count($data) > 1) {
  417. // 如果type是分类/类型的格式,按分类和类型查询
  418. $query->where('a.category', $data[0])->where('type', $data[1]);
  419. } else {
  420. // 否则,按type查询
  421. $query->where('a.type', $where['type']);
  422. }
  423. })
  424. // 当搜索条件中包含date时,添加日期范围条件到查询
  425. ->when(isset($where['date']) && $where['date'] !== '', function ($query) use ($where) {
  426. getModelTime($query, $where['date'], 'a.create_time');
  427. })
  428. // 当搜索条件中包含keyword时,添加关键词搜索条件到查询
  429. ->when(isset($where['keyword']) && $where['keyword'] !== '', function ($query) use ($where) {
  430. $query->whereLike('a.uid|b.nickname|a.title', "%{$where['keyword']}%");
  431. })
  432. ->when(isset($where['nickname']) && $where['nickname'] !== '', function ($query) use ($where) {
  433. $query->whereLike('b.nickname', "%{$where['nickname']}%");
  434. })
  435. ->when(isset($where['phone']) && $where['phone'] !== '', function ($query) use ($where) {
  436. $query->whereLike('b.phone', "%{$where['phone']}%");
  437. })
  438. ->when(isset($where['real_name']) && $where['real_name'] !== '', function ($query) use ($where) {
  439. $query->whereLike('b.real_name', "%{$where['real_name']}%");
  440. })
  441. ->when(isset($where['uid']) && $where['uid'] !== '', function ($query) use ($where) {
  442. $query->where('b.uid', $where['uid']);
  443. })
  444. // 当搜索条件中包含category时,添加分类条件到查询
  445. ->when(isset($where['category']) && $where['category'] !== '', function ($query) use ($where) {
  446. if (is_array($where['category'])){
  447. // 如果category是数组,使用whereIn查询
  448. $query->whereIn('a.category', $where['category']);
  449. } else {
  450. // 否则,直接按category查询
  451. $query->where('a.category', $where['category']);
  452. }
  453. })
  454. // 当搜索条件中包含uid时,添加用户ID条件到查询
  455. ->when(isset($where['uid']) && $where['uid'] !== '', function ($query) use ($where) {
  456. $query->where('a.uid', $where['uid']);
  457. })
  458. // 排除分类为sys_brokerage的账单
  459. ->where('category', '<>', 'sys_brokerage');
  460. }
  461. /**
  462. * 计算并返回指定订单和用户ID的退款佣金总额。
  463. *
  464. * 本函数通过查询用户账单表,找出与指定订单ID和用户ID相关联的退款佣金记录,
  465. * 并计算这些记录的佣金总额。这有助于在处理退款时准确地调整用户的佣金余额。
  466. *
  467. * @param string $order_id 订单ID,用于查询与订单相关的佣金退款记录。
  468. * @param string $uid 用户ID,用于查询特定用户的佣金退款记录。
  469. * @return float 返回符合条件的佣金退款总额。
  470. */
  471. public function refundBrokerage($order_id, $uid)
  472. {
  473. // 使用UserBill的数据库实例,查询满足条件的佣金退款记录,并计算总数。
  474. return UserBill::getDB()->where('link_id', $order_id)->where('uid', $uid)
  475. ->where('category', 'brokerage')->whereIn('type', ['refund_two', 'refund_one'])->sum('number');
  476. }
  477. /**
  478. * 计算指定订单和用户退款的积分总数。
  479. *
  480. * 本函数通过查询用户账单表,找出与指定订单关联的、属于指定用户的、
  481. * 类别为积分、类型为退款锁定的记录,然后计算这些记录的积分总数。
  482. * 这样做的目的是为了在退款操作中准确地回滚用户的积分,确保用户积分账户的准确性。
  483. *
  484. * @param string $order_id 订单ID,用于关联订单和用户账单。
  485. * @param int $uid 用户ID,用于查询指定用户的账单记录。
  486. * @return int 返回符合条件的记录的积分总数。
  487. */
  488. public function refundIntegral($order_id, $uid)
  489. {
  490. // 使用UserBill的数据库工具方法进行查询,通过where子句指定订单ID、用户ID、类别和类型,
  491. // 最后使用sum方法计算符合条件的记录的number列的总和,即积分总数。
  492. return UserBill::getDB()->where('link_id', $order_id)->where('uid', $uid)
  493. ->where('category', 'integral')->where('type', 'refund_lock')->sum('number');
  494. }
  495. /**
  496. * 校验用户在指定时间范围内积分的锁定状态是否有效。
  497. * 该方法通过计算用户在指定时间内锁定的积分,以及相同时间内发生的积分返还和系统扣减情况,来确定用户的实际可用积分。
  498. *
  499. * @param integer $uid 用户ID。
  500. * @param string $start 查询的开始时间。
  501. * @param string $end 查询的结束时间。
  502. * @return integer 返回用户在指定时间内实际可用的积分值。
  503. */
  504. public function validIntegral($uid, $start, $end)
  505. {
  506. // 查询指定时间内被锁定的积分记录。
  507. $lst = UserBill::getDB()->where('category', 'integral')
  508. ->where('type', 'lock')->whereBetween('create_time', [$start, $end])->where('uid', $uid)->where('status', 1)->field('link_id,number')->select()->toArray();
  509. // 初始化积分计算变量。
  510. $integral = 0;
  511. // 如果有锁定的积分记录,则计算已返还的锁定积分。
  512. if (count($lst)) {
  513. $integral = -1 * UserBill::getDB()->whereIn('link_id', array_column($lst, 'link_id'))->where('uid', $uid)
  514. ->where('category', 'integral')->where('type', 'refund_lock')->sum('number');
  515. }
  516. // 累加计算所有锁定的积分。
  517. foreach ($lst as $bill) {
  518. $integral = bcadd($integral, $bill['number'], 0);
  519. }
  520. // 计算指定时间内用户获得的积分(不包括锁定和系统扣减)。
  521. $integral2 = UserBill::getDB()->where('uid', $uid)->whereBetween('create_time', [$start, $end])
  522. ->where('category', 'integral')->where('pm', 1)->whereNotIn('type', ['lock', 'refund'])->sum('number');
  523. // 计算指定时间内用户因系统原因被扣减的积分。
  524. $integral3 = UserBill::getDB()->where('uid', $uid)->whereBetween('create_time', [$start, $end])
  525. ->where('category', 'integral')->where('type', 'sys_dec')->sum('number');
  526. // 返回用户在指定时间内实际可用的积分,确保积分值不为负。
  527. return (int)max(bcsub(bcadd($integral, $integral2, 0), $integral3, 0), 0);
  528. }
  529. }