| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- <?php
- namespace plugin\saiadmin\app\logic\order;
- use plugin\saiadmin\app\model\order\RentalOrder;
- use plugin\saiadmin\app\model\system\SystemUser;
- use plugin\saiadmin\basic\think\BaseLogic;
- use plugin\saiadmin\exception\ApiException;
- use support\think\Db;
- /**
- * “我的订单”查询逻辑。
- *
- * 参照旧项目 OrderSearch::query_orders_new() 的筛选和可见范围语义,
- * 新系统只查询 sa_rental_order,不调用旧 ThinkPHP 项目。
- */
- class MyOrderLogic extends BaseLogic
- {
- private const DEVICE_TYPES = [
- 'vehicle' => [107],
- 'k-battery' => [100, 102],
- 'bluetooth' => [104],
- 'power-bank' => [1, 101],
- 'password' => [103],
- 'password-bluetooth' => [105],
- ];
- private const DEVICE_NAMES = [
- 1 => '充电底座', 100 => 'K霸宝', 101 => '充电宝', 102 => 'K霸宝 Blue',
- 103 => '密码线充', 104 => '蓝牙线充', 105 => '密码蓝牙线充', 107 => '车载充电器',
- ];
- private const STATUSES = [
- 0 => ['code' => 'pending', 'name' => '待支付'],
- 1 => ['code' => 'using', 'name' => '使用中'],
- 2 => ['code' => 'done', 'name' => '已完成'],
- 3 => ['code' => 'timeout', 'name' => '超时完成'],
- 4 => ['code' => 'rent_failed', 'name' => '租借失败'],
- 5 => ['code' => 'deduct_failed', 'name' => '扣款失败'],
- 6 => ['code' => 'refund', 'name' => '申请退款'],
- ];
- public function __construct()
- {
- $this->model = new RentalOrder();
- }
- public function indexList(array $filters): array
- {
- return $this->listOrders($filters);
- }
- /**
- * 当前账号下级代理管理的订单分页列表。
- */
- public function subordinateIndexList(array $filters): array
- {
- return $this->listOrders($filters, true);
- }
- private function listOrders(array $filters, bool $subordinate = false): array
- {
- $page = max(1, (int) request()->input('page', 1));
- $limit = min(100, max(1, (int) request()->input('limit', 20)));
- $result = $this->buildQuery($filters, $subordinate)
- ->order('o.rent_at', 'desc')
- ->order('o.id', 'desc')
- ->paginate(['page' => $page, 'list_rows' => $limit])
- ->toArray();
- $result['data'] = array_map(fn (array $item) => $this->formatOrder($item), $result['data'] ?? []);
- $result['summary'] = $this->summary($filters, $subordinate);
- return $result;
- }
- public function readOrder(int $id): array
- {
- return $this->readScopedOrder($id);
- }
- /**
- * 获取下级代理管理的订单详情。
- */
- public function readSubordinateOrder(int $id): array
- {
- return $this->readScopedOrder($id, true);
- }
- private function readScopedOrder(int $id, bool $subordinate = false): array
- {
- if ($id <= 0) {
- throw new ApiException('订单参数错误');
- }
- $order = $this->buildQuery([], $subordinate)->where('o.id', $id)->find();
- if (empty($order)) {
- throw new ApiException('订单不存在或无权查看');
- }
- return $this->formatOrder($order, true);
- }
- private function buildQuery(array $filters, bool $subordinate = false)
- {
- $query = Db::table('sa_rental_order')->alias('o')
- ->leftJoin('sa_device d', 'd.id = o.device_id AND d.delete_time IS NULL')
- ->leftJoin('sa_merchant rent', 'rent.id = o.rent_merchant_id AND rent.delete_time IS NULL')
- ->leftJoin('sa_merchant back', 'back.id = o.return_merchant_id AND back.delete_time IS NULL')
- ->leftJoin('sa_system_user manager', 'manager.id = o.manage_agent_id AND manager.delete_time IS NULL')
- ->whereNull('o.delete_time')
- ->field(implode(',', [
- 'o.id,o.order_sn,o.sub_order_sn,o.transaction_id,o.merchant_order_no,o.device_id,o.device_type,o.source,o.pay_type',
- 'o.user_id,o.user_name,o.user_phone,o.rent_merchant_id,o.return_merchant_id,o.rent_at,o.return_at,o.status',
- 'o.paid_amount,o.income_amount,o.refund_amount,o.package_description,o.remark,o.manage_agent_id,o.create_time',
- 'd.goods_sn AS device_sn,d.device_code AS device_code,d.goods_name AS device_name',
- 'rent.name AS rent_merchant_name,back.name AS return_merchant_name',
- 'manager.realname AS manager_realname,manager.username AS manager_username,manager.phone AS manager_phone',
- ]));
- if ($subordinate) {
- $managerIds = $this->subordinateManagerIds();
- if ($managerIds === []) {
- $query->where('o.id', 0);
- } else {
- $query->whereIn('o.manage_agent_id', $managerIds);
- }
- } elseif ($this->currentAdminId() !== 1) {
- $query->where('o.manage_agent_id', $this->currentAdminId());
- }
- $category = trim((string) ($filters['category'] ?? 'all'));
- if ($category !== 'all' && isset(self::DEVICE_TYPES[$category])) {
- $query->whereIn('o.device_type', self::DEVICE_TYPES[$category]);
- }
- $status = trim((string) ($filters['status'] ?? 'all'));
- if ($status === 'today') {
- $query->whereTime('o.rent_at', 'today');
- } elseif ($status !== 'all') {
- $statusValue = array_search($status, array_column(self::STATUSES, 'code'), true);
- if ($statusValue !== false) {
- $query->where('o.status', (int) $statusValue);
- }
- }
- $this->like($query, 'o.order_sn', $filters['order_no'] ?? '');
- $this->like($query, 'o.user_phone', $filters['phone'] ?? '');
- $this->like($query, 'o.user_id', $filters['user_id'] ?? '');
- $this->like($query, 'rent.name', $filters['merchant'] ?? '');
- $this->like($query, 'd.goods_sn', $filters['device_sn'] ?? '');
- $this->like($query, 'o.transaction_id', $filters['transaction_id'] ?? '');
- $agentId = (int) ($filters['agent_id'] ?? 0);
- if ($agentId > 0) {
- $query->where('o.manage_agent_id', $agentId);
- }
- $source = trim((string) ($filters['source'] ?? ''));
- if (in_array($source, ['1', '2'], true)) {
- $query->where('o.source', (int) $source);
- }
- $payType = trim((string) ($filters['pay_type'] ?? ''));
- if (in_array($payType, ['deposit', 'free'], true)) {
- $query->where('o.pay_type', $payType);
- }
- $startAt = trim((string) ($filters['start_at'] ?? ''));
- $endAt = trim((string) ($filters['end_at'] ?? ''));
- if ($startAt !== '') {
- $query->where('o.rent_at', '>=', $startAt . ' 00:00:00');
- }
- if ($endAt !== '') {
- $query->where('o.rent_at', '<=', $endAt . ' 23:59:59');
- }
- return $query;
- }
- private function summary(array $filters, bool $subordinate = false): array
- {
- $result = ['all' => 0, 'today' => 0];
- foreach (self::STATUSES as $status) {
- $result[$status['code']] = 0;
- }
- $rows = $this->buildQuery(array_merge($filters, ['status' => 'all']), $subordinate)
- ->field('o.status,COUNT(*) AS total')->group('o.status')->select()->toArray();
- foreach ($rows as $row) {
- $status = self::STATUSES[(int) $row['status']] ?? null;
- if ($status) {
- $result[$status['code']] = (int) $row['total'];
- $result['all'] += (int) $row['total'];
- }
- }
- $result['today'] = $this->buildQuery(array_merge($filters, ['status' => 'today']), $subordinate)->count();
- return $result;
- }
- private function formatOrder(array $order, bool $detail = false): array
- {
- $status = self::STATUSES[(int) ($order['status'] ?? 0)] ?? self::STATUSES[0];
- $source = (int) ($order['source'] ?? 0);
- $payType = (string) ($order['pay_type'] ?? 'deposit');
- return [
- 'id' => (int) $order['id'], 'order_sn' => (string) $order['order_sn'], 'sub_order_sn' => (string) ($order['sub_order_sn'] ?? ''),
- 'transaction_id' => (string) ($order['transaction_id'] ?? ''), 'merchant_order_no' => (string) ($order['merchant_order_no'] ?? ''),
- 'device_type' => (int) ($order['device_type'] ?? 0), 'device_type_name' => self::DEVICE_NAMES[(int) ($order['device_type'] ?? 0)] ?? '未知设备',
- 'device_name' => (string) ($order['device_name'] ?? ''), 'device_sn' => (string) ($order['device_sn'] ?? ''), 'device_code' => (string) ($order['device_code'] ?? ''),
- 'source' => $source, 'source_name' => $source === 1 ? '微信' : ($source === 2 ? '支付宝' : '未知'),
- 'pay_type' => $payType, 'pay_type_name' => $payType === 'free' ? '免押金' : '押金',
- 'user_id' => (int) ($order['user_id'] ?? 0), 'user_name' => (string) ($order['user_name'] ?? ''), 'user_phone' => (string) ($order['user_phone'] ?? ''),
- 'rent_merchant' => (string) ($order['rent_merchant_name'] ?? ''), 'return_merchant' => (string) ($order['return_merchant_name'] ?? ''),
- 'rent_at' => (string) ($order['rent_at'] ?? ''), 'return_at' => (string) ($order['return_at'] ?? ''),
- 'status' => $status['code'], 'status_name' => $status['name'], 'paid_amount' => (float) ($order['paid_amount'] ?? 0),
- 'income_amount' => (float) ($order['income_amount'] ?? 0), 'refund_amount' => (float) ($order['refund_amount'] ?? 0),
- 'package_description' => (string) ($order['package_description'] ?? ''), 'remark' => (string) ($order['remark'] ?? ''),
- 'manage_agent_id' => (int) ($order['manage_agent_id'] ?? 0), 'create_time' => (string) ($order['create_time'] ?? ''),
- 'manager_name' => (string) (($order['manager_realname'] ?? '') ?: ($order['manager_username'] ?? '未分配')),
- 'manager_phone' => (string) ($order['manager_phone'] ?? ''),
- 'detail' => $detail,
- ];
- }
- private function currentAdminId(): int
- {
- return (int) ($this->adminInfo['id'] ?? 0);
- }
- /** @return int[] */
- private function subordinateManagerIds(): array
- {
- $currentId = $this->currentAdminId();
- if ($currentId <= 0) {
- return [];
- }
- if ($currentId === 1) {
- return array_map('intval', SystemUser::where('id', '<>', 1)
- ->whereNull('delete_time')->column('id'));
- }
- $dept = $this->adminInfo['deptList'] ?? [];
- if (empty($dept['id']) || !isset($dept['level'])) {
- return [];
- }
- $prefix = (string) $dept['level'] . (int) $dept['id'] . ',';
- $deptIds = Db::table('sa_system_dept')->whereNull('delete_time')
- ->whereLike('level', $prefix . '%')->column('id');
- if ($deptIds === []) {
- return [];
- }
- return array_map('intval', SystemUser::whereIn('dept_id', $deptIds)
- ->whereNull('delete_time')->column('id'));
- }
- private function like($query, string $field, mixed $value): void
- {
- $value = trim((string) $value);
- if ($value !== '') {
- $query->whereLike($field, '%' . $value . '%');
- }
- }
- }
|