后台退换货和退换货原因管理

This commit is contained in:
TL 2022-08-03 14:36:59 +08:00
parent e118705324
commit 8e0330b01c
13 changed files with 695 additions and 0 deletions

View File

@ -0,0 +1,52 @@
<?php
/**
* RmaController.php
*
* @copyright 2022 opencart.cn - All Rights Reserved
* @link http://www.guangdawangluo.com
* @author TL <mengwb@opencart.cn>
* @created 2022-08-03 21:17:04
* @modified 2022-08-03 21:17:04
*/
namespace Beike\Admin\Http\Controllers;
use Beike\Models\Rma;
use Beike\Repositories\RmaReasonRepo;
use Beike\Repositories\RmaRepo;
use Exception;
use Illuminate\Http\Request;
class RmaController extends Controller
{
public function index(Request $request)
{
$rmas = RmaRepo::list($request->only('name', 'email', 'telephone', 'product_name', 'model', 'type', 'status'));
$data = [
'rmas' => $rmas,
];
return view('admin::pages.rmas.index', $data);
}
/**
* @param int $id
* @return mixed
*/
public function show(int $id)
{
$data = [
'rma' => RmaRepo::find($id),
'statuses' => RmaRepo::getStatuses(),
'types' => RmaRepo::getTypes(),
];
return view('admin::pages.rmas.info', $data);
}
public function destroy(int $id): array
{
RmaRepo::delete($id);
return json_success("已成功删除");
}
}

View File

@ -0,0 +1,52 @@
<?php
/**
* RmaController.php
*
* @copyright 2022 opencart.cn - All Rights Reserved
* @link http://www.guangdawangluo.com
* @author TL <mengwb@opencart.cn>
* @created 2022-08-03 21:17:04
* @modified 2022-08-03 21:17:04
*/
namespace Beike\Admin\Http\Controllers;
use Beike\Repositories\RmaReasonRepo;
use Exception;
use Illuminate\Http\Request;
class RmaReasonController extends Controller
{
public function index(Request $request)
{
$rmaReasons = RmaReasonRepo::list($request->only('name'));
$data = [
'rmaReasons' => $rmaReasons,
];
return view('admin::pages.rma_reasons.index', $data);
}
public function store(Request $request): array
{
$rmaReason = RmaReasonRepo::create($request->only('name'));
return json_success("创建成功", $rmaReason);
}
/**
* @throws Exception
*/
public function update(Request $request, int $id): array
{
$rmaReason = RmaReasonRepo::update($id, $request->only('name'));
return json_success("成功修改", $rmaReason);
}
public function destroy(int $id): array
{
RmaReasonRepo::delete($id);
return json_success("已成功删除");
}
}

View File

@ -0,0 +1,59 @@
<?php
/**
* RmaRequest.php
*
* @copyright 2022 opencart.cn - All Rights Reserved
* @link http://www.guangdawangluo.com
* @author TL <mengwb@opencart.cn>
* @created 2022-08-03 11:17:04
* @modified 2022-08-03 11:17:04
*/
namespace Beike\Admin\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class RmaRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
$rules = [
'order_id' => 'required|exists:orders,id',
'order_product_id' => 'required|exists:order_products,id',
'customer_id' => 'required|exists:customers,id',
'quantity' => 'required',
'opened' => 'required',
'rma_reason_id' => 'required|exists:rma_reasons,id',
'type' => 'required',
];
return $rules;
}
public function attributes()
{
return [
'order_id' => '订单',
'order_product_id' => '订单商品',
'customer_id' => '顾客',
'quantity' => '数量',
'opened' => '已拆包装',
'rma_reason_id' => '退换货原因',
'type' => '售后服务类型',
];
}
}

View File

@ -72,6 +72,8 @@ Route::prefix($adminName)
Route::resource('products', Controllers\ProductController::class);
Route::resource('regions', Controllers\RegionController::class);
Route::resource('rmas', Controllers\RmaController::class);
Route::resource('rma_reasons', Controllers\RmaReasonController::class);
Route::get('settings', [Controllers\SettingController::class, 'index'])->name('settings.index');
Route::post('settings', [Controllers\SettingController::class, 'store'])->name('settings.store');

42
beike/Models/Rma.php Normal file
View File

@ -0,0 +1,42 @@
<?php
/**
* Rma.php
*
* @copyright 2022 opencart.cn - All Rights Reserved
* @link http://www.guangdawangluo.com
* @author TL <mengwb@opencart.cn>
* @created 2022-08-01 20:22:18
* @modified 2022-08-01 20:22:18
*/
namespace Beike\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Rma extends Base
{
use HasFactory;
protected $fillable = ['order_id','order_product_id','customer_id','name','email','telephone','product_name','model','quantity','opened','rma_reason_id','type','status','comment'];
public function order() :BelongsTo
{
return $this->belongsTo(Order::Class);
}
public function orderProduct() :BelongsTo
{
return $this->belongsTo(OrderProduct::class);
}
public function customer() :BelongsTo
{
return $this->belongsTo(Customer::class);
}
public function reason() :BelongsTo
{
return $this->belongsTo(RmaReason::class);
}
}

View File

@ -0,0 +1,22 @@
<?php
/**
* RmaReason.php
*
* @copyright 2022 opencart.cn - All Rights Reserved
* @link http://www.guangdawangluo.com
* @author TL <mengwb@opencart.cn>
* @created 2022-08-01 20:22:18
* @modified 2022-08-01 20:22:18
*/
namespace Beike\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class RmaReason extends Base
{
use HasFactory;
protected $fillable = ['locale','name'];
}

View File

@ -0,0 +1,88 @@
<?php
/**
* RmaReasonRepo.php
*
* @copyright 2022 opencart.cn - All Rights Reserved
* @link http://www.guangdawangluo.com
* @author TL <mengwb@opencart.cn>
* @created 2022-08-01 20:42:05
* @modified 2022-08-01 20:42:05
*/
namespace Beike\Repositories;
use Beike\Models\Rma;
use Beike\Models\RmaReason;
use Exception;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
class RmaReasonRepo
{
/**
* 创建一个记录
* @param $data
* @return Builder|Model
*/
public static function create($data)
{
$item = RmaReason::query()->create($data);
return $item;
}
/**
* @param $reason
* @param $data
* @return Builder|Builder[]|Collection|Model|mixed
* @throws Exception
*/
public static function update($reason, $data)
{
if (!$reason instanceof RmaReason) {
$reason = RmaReason::query()->find($reason);
}
if (!$reason) {
throw new Exception("退换货原因id $reason 不存在");
}
$reason->update($data);
return $reason;
}
/**
* @param $id
* @return Builder|Builder[]|Collection|Model|null
*/
public static function find($id)
{
return RmaReason::query()->find($id);
}
/**
* @param $id
* @return void
*/
public static function delete($id)
{
$reason = RmaReason::query()->find($id);
if ($reason) {
$reason->delete();
}
}
/**
* @param $data
* @return LengthAwarePaginator
*/
public static function list($data = []): LengthAwarePaginator
{
$builder = Rma::query();
if (isset($data['name'])) {
$builder->where('name', 'like', "%{$data['name']}%");
}
return $builder->paginate(10);
}
}

View File

@ -0,0 +1,147 @@
<?php
/**
* RmaRepo.php
*
* @copyright 2022 opencart.cn - All Rights Reserved
* @link http://www.guangdawangluo.com
* @author TL <mengwb@opencart.cn>
* @created 2022-08-01 20:42:05
* @modified 2022-08-01 20:42:05
*/
namespace Beike\Repositories;
use Beike\Models\Rma;
use Beike\Models\Customer;
use Beike\Shop\Http\Resources\RmaDetail;
use Exception;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
class RmaRepo
{
/**
* 创建一个记录
* @param $data
* @return Builder|Model
*/
public static function create($data)
{
$item = Rma::query()->create($data);
return $item;
}
/**
* @param $rma
* @param $data
* @return Builder|Builder[]|Collection|Model|mixed
* @throws Exception
*/
public static function update($rma, $data)
{
if (!$rma instanceof Rma) {
$rma = Rma::query()->find($rma);
}
if (!$rma) {
throw new Exception("退还/售后id $rma 不存在");
}
$rma->update($data);
return $rma;
}
/**
* @param $id
* @return Builder|Builder[]|Collection|Model|null
*/
public static function find($id)
{
return Rma::query()->find($id);
}
/**
* @param $id
* @return void
*/
public static function delete($id)
{
$rma = Rma::query()->find($id);
if ($rma) {
$rma->delete();
}
}
/**
* @param $data
* @return LengthAwarePaginator
*/
public static function list($data): LengthAwarePaginator
{
$builder = Rma::query();
if (isset($data['name'])) {
$builder->where('name', 'like', "%{$data['name']}%");
}
if (isset($data['email'])) {
$builder->where('email', 'like', "%{$data['email']}%");
}
if (isset($data['telephone'])) {
$builder->where('telephone', 'like', "%{$data['telephone']}%");
}
if (isset($data['product_name'])) {
$builder->where('product_name', 'like', "%{$data['product_name']}%");
}
if (isset($data['model'])) {
$builder->where('model', 'like', "%{$data['model']}%");
}
if (isset($data['type'])) {
$builder->where('type', $data['type']);
}
if (isset($data['status'])) {
$builder->where('status', $data['status']);
}
return $builder->paginate(10)->withQueryString();
}
/**
* @param $customer
* @return array
*/
public static function listByCustomer($customer): array
{
if (!$customer instanceof Customer) {
$customer = CustomerRepo::find($customer->id);
}
$results = [];
foreach ($customer->rmas as $rma) {
$results[$rma->first][] = (new RmaDetail($rma))->jsonSerialize();
}
return $results;
}
public static function getStatuses(): array
{
return [
'pending' => '待处理',
'rejected' => '已拒绝',
'approved' => '已批准(待顾客寄回商品)',
'shipped' => '已发货(寄回商品)',
'completed' => '已完成'
];
}
public static function getTypes(): array
{
return [
'return' => '退货',
'exchange' => '换货',
'repair' => '维修',
'reissue' => '补发商品',
'refund' => '仅退款'
];
}
}

View File

@ -0,0 +1,22 @@
<?php
/**
* BrandDetail.php
*
* @copyright 2022 opencart.cn - All Rights Reserved
* @link http://www.guangdawangluo.com
* @author TL <mengwb@opencart.cn>
* @created 2022-08-03 10:33:06
* @modified 2022-08-03 10:33:06
*/
namespace Beike\Shop\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class RmaDetail extends JsonResource
{
public function toArray($request): array
{
return $this->toArray($request);
}
}

View File

@ -0,0 +1,60 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class ReturnTable extends Migration
{
/**
* Run the migrations.
*
* @rma void
*/
public function up()
{
Schema::create('rmas', function (Blueprint $table) {
$table->id();
$table->unsignedInteger('order_id');
$table->unsignedInteger('order_product_id');
$table->unsignedInteger('customer_id');
$table->string('name');
$table->string('email');
$table->string('telephone');
$table->string('product_name');
$table->string('model');
$table->integer('quantity');
$table->tinyInteger('opened');
$table->unsignedInteger('rma_reason_id');
$table->string('type'); // 售后服务类型:退货、换货、维修、补发商品、仅退款
$table->string('status'); //
$table->text('comment');
$table->timestamps();
});
Schema::create('rma_histories', function (Blueprint $table) {
$table->id();
$table->unsignedInteger('rma_id');
$table->string('status');
$table->tinyInteger('notify');
$table->text('comment');
$table->timestamps();
});
Schema::create('rma_reasons', function (Blueprint $table) {
$table->id();
$table->string('locale');
$table->string('name');
});
}
/**
* Reverse the migrations.
*
* @rma void
*/
public function down()
{
Schema::dropIfExists('rmas');
Schema::dropIfExists('rma_histories');
Schema::dropIfExists('rma_reasons');
}
}

View File

@ -0,0 +1,39 @@
@extends('admin::layouts.master')
@section('title', '售后申请列表')
@section('content')
<div id="customer-app" class="card">
<div class="card-body">
<div class="d-flex justify-content-between mb-4">
<button type="button" class="btn btn-primary" @click="checkedCreate('add', null)">创建</button>
</div>
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>名称</th>
<th>操作</th>
</tr>
</thead>
<tbody>
@foreach ($rmaReasons as $rmaReason)
<tr>
<td>{{ $rmaReason->id }}</td>
<td>{{ $rmaReason->name }}</td>
<td><a href="{{ admin_route('rma_reasons.show', [$rmaReason->id]) }}" class="btn btn-outline-secondary btn-sm">查看</a></td>
</tr>
@endforeach
</tbody>
</table>
{{ $rmaReasons->links('admin::vendor/pagination/bootstrap-4') }}
</div>
</div>
@endsection
@push('footer')
<script>
</script>
@endpush

View File

@ -0,0 +1,48 @@
@extends('admin::layouts.master')
@section('title', '售后申请列表')
@section('content')
<div id="customer-app" class="card">
<div class="card-body">
<table class="table">
<thead>
<tr>
<th>客户姓名</th>
<th>邮箱</th>
<th>电话号码</th>
<th>商品</th>
<th>商品型号</th>
<th>数量</th>
<th>服务类型</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
@foreach ($rmas as $rma)
<tr>
<td>{{ $rma->name }}</td>
<td>{{ $rma->email }}</td>
<td>{{ $rma->telephone }}</td>
<td>{{ $rma->product_name }}</td>
<td>{{ $rma->model }}</td>
<td>{{ $rma->quantity }}</td>
<td>{{ $rma->type }}</td>
<td>{{ $rma->status }}</td>
<td><a href="{{ admin_route('rmas.show', [$rma->id]) }}" class="btn btn-outline-secondary btn-sm">查看</a></td>
</tr>
@endforeach
</tbody>
</table>
{{ $rmas->links('admin::vendor/pagination/bootstrap-4') }}
</div>
</div>
@endsection
@push('footer')
<script>
</script>
@endpush

View File

@ -0,0 +1,62 @@
@extends('admin::layouts.master')
@section('title', '售后申请')
@section('content')
<div class="card mb-4">
<div class="card-header"><h6 class="card-title">售后申请详情</h6></div>
<div class="card-body">
<div class="row">
<div class="col-4">
<table class="table table-borderless">
<tbody>
<tr>
<td>ID</td>
<td>{{ $rma->id }}</td>
</tr>
<tr>
<td>客户姓名:</td>
<td>{{ $rma->name }}</td>
</tr>
<tr>
<td>联系电话:</td>
<td>{{ $rma->telephone }}</td>
</tr>
</tbody>
</table>
</div>
<div class="col-4">
<table class="table table-borderless">
<tbody>
<tr>
<td>商品:</td>
<td>{{ $rma->product_name }}</td>
</tr>
<tr>
<td>型号:</td>
<td>{{ $rma->model }}</td>
</tr>
<tr>
<td>数量:</td>
<td>{{ $rma->quantity }}</td>
</tr>
<tr>
<td>退货原因:</td>
<td>{{ $rma->quantity }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="card mb-4">
<div class="card-header"><h6 class="card-title">操作日志</h6></div>
<div class="card-body">
</div>
</div>
@endsection