Files
wordpress-theme-aksrt/src/AKSRT/Admin/ShopControllerFulfillmentOperations.php
T

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;
}
}