354 lines
13 KiB
PHP
354 lines
13 KiB
PHP
<?php
|
|
/**
|
|
* @package AKSRT
|
|
*/
|
|
|
|
namespace AKSRT\Admin;
|
|
|
|
defined('ABSPATH') || exit;
|
|
|
|
trait ShopControllerFulfillmentOperations {
|
|
|
|
/**
|
|
* GET /shop/after-sale — 售后工单列表
|
|
*/
|
|
public function get_after_sale_list(\WP_REST_Request $request): \WP_REST_Response {
|
|
if (!class_exists('\AKSRT\Payment\AfterSale')) {
|
|
return $this->success(['data' => ['items' => [], 'total' => 0, 'page' => 1, 'max_pages' => 1]]);
|
|
}
|
|
|
|
$page = max(1, (int) $request->get_param('page'));
|
|
$per_page = max(1, min(100, (int) $request->get_param('per_page'))) ?: 20;
|
|
$status = sanitize_key((string) $request->get_param('status'));
|
|
$stage = sanitize_key((string) $request->get_param('stage'));
|
|
$order = sanitize_text_field((string) $request->get_param('order_number'));
|
|
$type = sanitize_key((string) $request->get_param('type'));
|
|
$date_from = sanitize_text_field((string) $request->get_param('date_from'));
|
|
$date_to = sanitize_text_field((string) $request->get_param('date_to'));
|
|
|
|
$result = \AKSRT\Payment\AfterSale::get_instance()->get_list([
|
|
'limit' => $per_page,
|
|
'offset' => ($page - 1) * $per_page,
|
|
'status' => $status,
|
|
'stage' => $stage,
|
|
'order_number' => $order,
|
|
'type' => $type,
|
|
'date_from' => $date_from,
|
|
'date_to' => $date_to,
|
|
'include_order_context' => true,
|
|
]);
|
|
|
|
$stats = \AKSRT\Payment\AfterSale::get_instance()->get_stats();
|
|
|
|
return $this->success(['data' => array_merge($result, [
|
|
'stats' => $stats,
|
|
'filters' => [
|
|
'status' => $status,
|
|
'stage' => $stage,
|
|
'order_number' => $order,
|
|
'type' => $type,
|
|
'date_from' => $date_from,
|
|
'date_to' => $date_to,
|
|
],
|
|
'options' => [
|
|
'status' => \AKSRT\Payment\AfterSale::get_status_options(),
|
|
'stage' => \AKSRT\Payment\AfterSale::get_stage_options(),
|
|
'type' => \AKSRT\Payment\AfterSale::get_type_options(),
|
|
],
|
|
])]);
|
|
}
|
|
|
|
/**
|
|
* POST /shop/after-sale — 创建售后工单
|
|
*/
|
|
public function create_after_sale(\WP_REST_Request $request): \WP_REST_Response {
|
|
if (!class_exists('\AKSRT\Payment\AfterSale')) {
|
|
return $this->error('售后系统未启用', 500);
|
|
}
|
|
|
|
$params = $this->get_json_params($request);
|
|
$order_number = sanitize_text_field((string) ($params['order_number'] ?? ''));
|
|
$reason = sanitize_textarea_field((string) ($params['reason'] ?? ''));
|
|
|
|
if ($order_number === '' || $reason === '') {
|
|
return $this->error('订单号和原因不能为空');
|
|
}
|
|
|
|
$order = class_exists('\AKSRT\Payment\OrderRepository')
|
|
? \AKSRT\Payment\OrderRepository::get_instance()->get($order_number)
|
|
: null;
|
|
|
|
if (!$order) {
|
|
return $this->error(__('订单不存在', 'aksrt'), 404);
|
|
}
|
|
|
|
unset($params['user_id'], $params['applicant_user_id']);
|
|
$id = \AKSRT\Payment\AfterSale::get_instance()->create($params);
|
|
|
|
if (is_wp_error($id)) {
|
|
return $this->error($id->get_error_message(), 422);
|
|
}
|
|
if ($id > 0) {
|
|
return $this->success([
|
|
'message' => __('售后工单已创建', 'aksrt'),
|
|
'data' => ['id' => $id],
|
|
], 201);
|
|
}
|
|
|
|
return $this->error(__('创建失败', 'aksrt'));
|
|
}
|
|
|
|
/**
|
|
* POST /shop/after-sale/{id}/update-status — 更新售后工单状态
|
|
*/
|
|
public function update_after_sale_status(\WP_REST_Request $request): \WP_REST_Response {
|
|
if (!class_exists('\AKSRT\Payment\AfterSale')) {
|
|
return $this->error('售后系统未启用', 500);
|
|
}
|
|
|
|
$id = (int) $request->get_param('id');
|
|
$params = $this->get_json_params($request);
|
|
$new_status = sanitize_key((string) ($params['status'] ?? ''));
|
|
$note = sanitize_textarea_field((string) ($params['operator_note'] ?? ''));
|
|
|
|
if ($id <= 0 || $new_status === '') {
|
|
return $this->error('参数无效');
|
|
}
|
|
|
|
$success = \AKSRT\Payment\AfterSale::get_instance()->update_status(
|
|
$id,
|
|
$new_status,
|
|
get_current_user_id(),
|
|
$note
|
|
);
|
|
|
|
if ($success) {
|
|
return $this->success(['message' => __('状态已更新', 'aksrt')]);
|
|
}
|
|
return $this->error(__('更新失败', 'aksrt'));
|
|
}
|
|
|
|
/**
|
|
* GET /shop/shipping — 发货记录列表
|
|
*/
|
|
public function get_shipping_list(\WP_REST_Request $request): \WP_REST_Response {
|
|
if (!class_exists('\AKSRT\Payment\Shipping')) {
|
|
return $this->success(['data' => ['items' => [], 'total' => 0, 'page' => 1, 'max_pages' => 1]]);
|
|
}
|
|
|
|
$page = max(1, (int) $request->get_param('page'));
|
|
$per_page = max(1, min(100, (int) $request->get_param('per_page'))) ?: 20;
|
|
$status = sanitize_key((string) $request->get_param('status'));
|
|
$order = sanitize_text_field((string) $request->get_param('order_number'));
|
|
$date_from = sanitize_text_field((string) $request->get_param('date_from'));
|
|
$date_to = sanitize_text_field((string) $request->get_param('date_to'));
|
|
$tracking_no = sanitize_text_field((string) $request->get_param('tracking_no'));
|
|
|
|
$result = \AKSRT\Payment\Shipping::get_instance()->get_list([
|
|
'limit' => $per_page,
|
|
'offset' => ($page - 1) * $per_page,
|
|
'status' => $status,
|
|
'order_number' => $order,
|
|
'date_from' => $date_from,
|
|
'date_to' => $date_to,
|
|
'tracking_no' => $tracking_no,
|
|
'include_order_context' => true,
|
|
]);
|
|
|
|
$stats = \AKSRT\Payment\Shipping::get_instance()->get_stats();
|
|
|
|
return $this->success(['data' => array_merge($result, [
|
|
'stats' => $stats,
|
|
'filters' => [
|
|
'status' => $status,
|
|
'order_number' => $order,
|
|
'date_from' => $date_from,
|
|
'date_to' => $date_to,
|
|
'tracking_no' => $tracking_no,
|
|
],
|
|
'options' => [
|
|
'status' => \AKSRT\Payment\Shipping::get_status_options(),
|
|
'carrier' => \AKSRT\Payment\Shipping::get_carrier_options(),
|
|
],
|
|
])]);
|
|
}
|
|
|
|
/**
|
|
* POST /shop/shipping — 创建发货记录
|
|
*/
|
|
public function create_shipping(\WP_REST_Request $request): \WP_REST_Response {
|
|
if (!class_exists('\AKSRT\Payment\Shipping')) {
|
|
return $this->error('物流系统未启用', 500);
|
|
}
|
|
|
|
$params = $this->get_json_params($request);
|
|
$order_number = sanitize_text_field((string) ($params['order_number'] ?? ''));
|
|
$carrier = sanitize_text_field((string) ($params['carrier'] ?? ''));
|
|
$tracking_no = sanitize_text_field((string) ($params['tracking_no'] ?? ''));
|
|
|
|
if ($order_number === '' || $carrier === '' || $tracking_no === '') {
|
|
return $this->error('订单号、快递公司和物流单号不能为空');
|
|
}
|
|
|
|
$order = class_exists('\AKSRT\Payment\OrderRepository')
|
|
? \AKSRT\Payment\OrderRepository::get_instance()->get($order_number)
|
|
: null;
|
|
|
|
if (!$order) {
|
|
return $this->error(__('订单不存在', 'aksrt'), 404);
|
|
}
|
|
|
|
$params['operator_id'] = get_current_user_id();
|
|
|
|
$id = \AKSRT\Payment\Shipping::get_instance()->create($params);
|
|
|
|
if ($id > 0) {
|
|
return $this->success([
|
|
'message' => __('发货记录已创建', 'aksrt'),
|
|
'data' => ['id' => $id],
|
|
], 201);
|
|
}
|
|
|
|
return $this->error(__('创建失败', 'aksrt'));
|
|
}
|
|
|
|
/**
|
|
* POST /shop/shipping/{id}/update-status — 更新发货状态
|
|
*/
|
|
public function update_shipping_status(\WP_REST_Request $request): \WP_REST_Response {
|
|
if (!class_exists('\AKSRT\Payment\Shipping')) {
|
|
return $this->error('物流系统未启用', 500);
|
|
}
|
|
|
|
$id = (int) $request->get_param('id');
|
|
$params = $this->get_json_params($request);
|
|
$new_status = sanitize_key((string) ($params['status'] ?? ''));
|
|
$note = sanitize_textarea_field((string) ($params['note'] ?? ''));
|
|
|
|
if ($id <= 0 || $new_status === '') {
|
|
return $this->error('参数无效');
|
|
}
|
|
|
|
$success = \AKSRT\Payment\Shipping::get_instance()->update_status($id, $new_status, $note, get_current_user_id());
|
|
|
|
if ($success) {
|
|
return $this->success(['message' => __('状态已更新', 'aksrt')]);
|
|
}
|
|
return $this->error(__('更新失败', 'aksrt'));
|
|
}
|
|
|
|
public function get_after_sale_detail(\WP_REST_Request $request): \WP_REST_Response {
|
|
if (!class_exists('\AKSRT\Payment\AfterSale')) {
|
|
return $this->error('售后系统未启用', 500);
|
|
}
|
|
|
|
$id = (int) $request->get_param('id');
|
|
if ($id <= 0) {
|
|
return $this->error('参数无效');
|
|
}
|
|
|
|
$record = \AKSRT\Payment\AfterSale::get_instance()->get_with_order_context($id);
|
|
if (!$record) {
|
|
return $this->error(__('售后工单不存在', 'aksrt'), 404);
|
|
}
|
|
|
|
return $this->success([
|
|
'data' => [
|
|
'record' => $record,
|
|
'timeline' => $this->build_after_sale_timeline($record),
|
|
],
|
|
]);
|
|
}
|
|
|
|
public function get_shipping_detail(\WP_REST_Request $request): \WP_REST_Response {
|
|
if (!class_exists('\AKSRT\Payment\Shipping')) {
|
|
return $this->error('物流系统未启用', 500);
|
|
}
|
|
|
|
$id = (int) $request->get_param('id');
|
|
if ($id <= 0) {
|
|
return $this->error('参数无效');
|
|
}
|
|
|
|
$record = \AKSRT\Payment\Shipping::get_instance()->get_with_order_context($id);
|
|
if (!$record) {
|
|
return $this->error(__('发货记录不存在', 'aksrt'), 404);
|
|
}
|
|
|
|
return $this->success([
|
|
'data' => [
|
|
'record' => $record,
|
|
'timeline' => $this->build_shipping_timeline($record),
|
|
],
|
|
]);
|
|
}
|
|
|
|
public function batch_update_shipping_status(\WP_REST_Request $request): \WP_REST_Response {
|
|
if (!class_exists('\AKSRT\Payment\Shipping')) {
|
|
return $this->error('物流系统未启用', 500);
|
|
}
|
|
|
|
$params = $this->get_json_params($request);
|
|
$ids = is_array($params['ids'] ?? null) ? $params['ids'] : [];
|
|
$status = sanitize_key((string) ($params['status'] ?? ''));
|
|
$note = sanitize_textarea_field((string) ($params['note'] ?? ''));
|
|
|
|
if (empty($ids) || $status === '') {
|
|
return $this->error('参数无效');
|
|
}
|
|
|
|
$result = \AKSRT\Payment\Shipping::get_instance()->batch_update_status($ids, $status, $note, get_current_user_id());
|
|
|
|
return $this->success([
|
|
'message' => __('批量状态更新已执行', 'aksrt'),
|
|
'data' => $result,
|
|
]);
|
|
}
|
|
|
|
private function build_shipping_timeline(array $record): array {
|
|
$timeline = [];
|
|
|
|
foreach ([
|
|
'created_at' => __('创建发货记录', 'aksrt'),
|
|
'updated_at' => __('更新物流状态', 'aksrt'),
|
|
'delivered_at' => __('确认签收', 'aksrt'),
|
|
] as $field => $label) {
|
|
if (!empty($record[$field])) {
|
|
$timeline[] = [
|
|
'time' => (string) $record[$field],
|
|
'label' => $label,
|
|
];
|
|
}
|
|
}
|
|
|
|
usort($timeline, static function ($a, $b) {
|
|
return strcmp((string) ($a['time'] ?? ''), (string) ($b['time'] ?? ''));
|
|
});
|
|
|
|
return $timeline;
|
|
}
|
|
|
|
private function build_after_sale_timeline(array $record): array {
|
|
$timeline = [];
|
|
|
|
foreach ([
|
|
'created_at' => __('提交售后申请', 'aksrt'),
|
|
'updated_at' => __('更新售后状态', 'aksrt'),
|
|
'resolved_at' => __('售后处理结束', 'aksrt'),
|
|
] as $field => $label) {
|
|
if (!empty($record[$field])) {
|
|
$timeline[] = [
|
|
'time' => (string) $record[$field],
|
|
'label' => $label,
|
|
];
|
|
}
|
|
}
|
|
|
|
usort($timeline, static function ($a, $b) {
|
|
return strcmp((string) ($a['time'] ?? ''), (string) ($b['time'] ?? ''));
|
|
});
|
|
|
|
return $timeline;
|
|
}
|
|
}
|