Files
webman-buildadmin-mall/app/admin/controller/mall/Order.php

293 lines
8.3 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace app\admin\controller\mall;
use Throwable;
use app\common\controller\Backend;
use app\common\model\MallOrder;
use app\common\model\MallUserAsset;
use support\think\Db;
use support\Response;
use Webman\Http\Request;
/**
* 统一订单(后台列表)
*/
class Order extends Backend
{
/**
* @var object|null
* @phpstan-var \app\common\model\MallOrder|null
*/
protected ?object $model = null;
protected array|string $preExcludeFields = ['id', 'create_time', 'update_time'];
protected array $withJoinTable = ['mallItem'];
protected string|array $quickSearchField = ['user_id', 'external_transaction_id', 'playx_transaction_id'];
protected string|array $indexField = [
'id',
'user_id',
'type',
'status',
'mall_item_id',
'points_cost',
'amount',
'multiplier',
'external_transaction_id',
'playx_transaction_id',
'grant_status',
'fail_reason',
'reject_reason',
'shipping_company',
'shipping_no',
'receiver_name',
'receiver_phone',
'receiver_address',
'mall_address_id',
'create_time',
'update_time',
];
public function initialize(): void
{
parent::initialize();
$this->model = new \app\common\model\MallOrder();
}
/**
* 查看
* @throws Throwable
*/
public function index(Request $request): Response
{
$response = $this->initializeBackend($request);
if ($response !== null) {
return $response;
}
if ($request->get('select') || $request->post('select')) {
return $this->select($request);
}
[$where, $alias, $limit, $order] = $this->queryBuilder();
$res = $this->model
->with(['mallItem' => function ($query) {
$query->field('id,title');
}])
->visible(['mallItem' => ['title']])
->alias($alias)
->where($where)
->order($order)
->paginate($limit);
return $this->success('', [
'list' => $res->items(),
'total' => $res->total(),
'remark' => get_route_remark(),
]);
}
/**
* PHYSICAL 发货:更新 shipping_company/shipping_no并将状态置为 SHIPPED
*/
public function ship(Request $request): Response
{
$response = $this->initializeBackend($request);
if ($response !== null) {
return $response;
}
if ($request->method() !== 'POST') {
return $this->error(__('Parameter error'));
}
$data = $request->post();
$id = $data['id'] ?? 0;
$shippingCompany = $data['shipping_company'] ?? '';
$shippingNo = $data['shipping_no'] ?? '';
if (!$id || $shippingCompany === '' || $shippingNo === '') {
return $this->error(__('Missing required fields'));
}
$order = MallOrder::where('id', $id)->find();
if (!$order) {
return $this->error(__('Record not found'));
}
if ($order->type !== MallOrder::TYPE_PHYSICAL) {
return $this->error(__('Order type not PHYSICAL'));
}
if ($order->status !== MallOrder::STATUS_PENDING) {
return $this->error(__('Order status must be PENDING'));
}
Db::startTrans();
try {
$order->shipping_company = $shippingCompany;
$order->shipping_no = $shippingNo;
$order->status = MallOrder::STATUS_SHIPPED;
$order->save();
Db::commit();
} catch (Throwable $e) {
Db::rollback();
return $this->error($e->getMessage());
}
return $this->success(__('Shipped successfully'));
}
/**
* 审核通过(非 PHYSICAL更新状态为 COMPLETED
*/
public function approve(Request $request): Response
{
$response = $this->initializeBackend($request);
if ($response !== null) {
return $response;
}
if ($request->method() !== 'POST') {
return $this->error(__('Parameter error'));
}
$id = $request->post('id', 0);
if (!$id) {
return $this->error(__('Missing required fields'));
}
$order = MallOrder::where('id', $id)->find();
if (!$order) {
return $this->error(__('Record not found'));
}
if ($order->status !== MallOrder::STATUS_PENDING) {
return $this->error(__('Order status must be PENDING'));
}
if ($order->type === MallOrder::TYPE_PHYSICAL) {
return $this->error(__('Order type not supported'));
}
Db::startTrans();
try {
$order->status = MallOrder::STATUS_COMPLETED;
$order->update_time = time();
$order->save();
Db::commit();
} catch (Throwable $e) {
Db::rollback();
return $this->error($e->getMessage());
}
return $this->success(__('Approved successfully'));
}
/**
* 审核驳回:更新状态为 REJECTED并退回积分到 available_points所有类型通用
*/
public function reject(Request $request): Response
{
$response = $this->initializeBackend($request);
if ($response !== null) {
return $response;
}
if ($request->method() !== 'POST') {
return $this->error(__('Parameter error'));
}
$data = $request->post();
$id = $data['id'] ?? 0;
$rejectReason = $data['reject_reason'] ?? '';
if (!$id) {
return $this->error(__('Missing required fields'));
}
$order = MallOrder::where('id', $id)->find();
if (!$order) {
return $this->error(__('Record not found'));
}
if ($order->status !== MallOrder::STATUS_PENDING) {
return $this->error(__('Order status must be PENDING'));
}
if ($order->type === MallOrder::TYPE_PHYSICAL && $rejectReason === '') {
return $this->error(__('Missing required fields'));
}
Db::startTrans();
try {
$asset = MallUserAsset::where('playx_user_id', $order->user_id ?? '')->find();
if (!$asset) {
throw new \RuntimeException('User asset not found');
}
$refund = $order->points_cost ?? 0;
if ($refund > 0) {
$asset->available_points += $refund;
$asset->save();
}
$order->status = MallOrder::STATUS_REJECTED;
$order->reject_reason = $rejectReason;
if ($order->type === MallOrder::TYPE_BONUS) {
$order->grant_status = MallOrder::GRANT_FAILED_FINAL;
} else {
$order->grant_status = MallOrder::GRANT_NOT_APPLICABLE;
}
$order->update_time = time();
$order->save();
Db::commit();
} catch (Throwable $e) {
Db::rollback();
return $this->error($e->getMessage());
}
return $this->success(__('Rejected successfully'));
}
/**
* 手动重试(仅红利推送失败可重试)
*/
public function retry(Request $request): Response
{
$response = $this->initializeBackend($request);
if ($response !== null) {
return $response;
}
if ($request->method() !== 'POST') {
return $this->error(__('Parameter error'));
}
$id = $request->post('id', 0);
if (!$id) {
return $this->error(__('Missing required fields'));
}
$order = MallOrder::where('id', $id)->find();
if (!$order) {
return $this->error(__('Record not found'));
}
if ($order->type !== MallOrder::TYPE_BONUS) {
return $this->error(__('Only BONUS can retry'));
}
if ($order->grant_status !== MallOrder::GRANT_FAILED_RETRYABLE) {
return $this->error(__('Only FAILED_RETRYABLE can retry'));
}
if (($order->retry_count ?? 0) >= 3) {
return $this->error(__('Retry count exceeded'));
}
$order->grant_status = MallOrder::GRANT_NOT_SENT;
$order->save();
return $this->success(__('Retry queued'));
}
}