diff --git a/beike/Admin/Http/Controllers/RmaController.php b/beike/Admin/Http/Controllers/RmaController.php new file mode 100644 index 00000000..6572d285 --- /dev/null +++ b/beike/Admin/Http/Controllers/RmaController.php @@ -0,0 +1,52 @@ + + * @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("已成功删除"); + } +} diff --git a/beike/Admin/Http/Controllers/RmaReasonController.php b/beike/Admin/Http/Controllers/RmaReasonController.php new file mode 100644 index 00000000..7aa6cd3f --- /dev/null +++ b/beike/Admin/Http/Controllers/RmaReasonController.php @@ -0,0 +1,52 @@ + + * @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("已成功删除"); + } +} diff --git a/beike/Admin/Http/Requests/RmaRequest.php b/beike/Admin/Http/Requests/RmaRequest.php new file mode 100644 index 00000000..1b7c4049 --- /dev/null +++ b/beike/Admin/Http/Requests/RmaRequest.php @@ -0,0 +1,59 @@ + + * @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' => '售后服务类型', + ]; + } +} diff --git a/beike/Admin/Routes/admin.php b/beike/Admin/Routes/admin.php index 8a7cb556..f531f943 100644 --- a/beike/Admin/Routes/admin.php +++ b/beike/Admin/Routes/admin.php @@ -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'); diff --git a/beike/Models/Rma.php b/beike/Models/Rma.php new file mode 100644 index 00000000..7cc322f8 --- /dev/null +++ b/beike/Models/Rma.php @@ -0,0 +1,42 @@ + + * @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); + } +} diff --git a/beike/Models/RmaReason.php b/beike/Models/RmaReason.php new file mode 100644 index 00000000..233db784 --- /dev/null +++ b/beike/Models/RmaReason.php @@ -0,0 +1,22 @@ + + * @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']; +} + diff --git a/beike/Repositories/RmaReasonRepo.php b/beike/Repositories/RmaReasonRepo.php new file mode 100644 index 00000000..f03717cd --- /dev/null +++ b/beike/Repositories/RmaReasonRepo.php @@ -0,0 +1,88 @@ + + * @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); + } +} diff --git a/beike/Repositories/RmaRepo.php b/beike/Repositories/RmaRepo.php new file mode 100644 index 00000000..6ce13a1d --- /dev/null +++ b/beike/Repositories/RmaRepo.php @@ -0,0 +1,147 @@ + + * @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' => '仅退款' + ]; + } +} diff --git a/beike/Shop/Http/Resources/RmaDetail.php b/beike/Shop/Http/Resources/RmaDetail.php new file mode 100644 index 00000000..cf569eaa --- /dev/null +++ b/beike/Shop/Http/Resources/RmaDetail.php @@ -0,0 +1,22 @@ + + * @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); + } +} diff --git a/database/migrations/2022_07_29_021003_return_table.php b/database/migrations/2022_07_29_021003_return_table.php new file mode 100644 index 00000000..d9a27d96 --- /dev/null +++ b/database/migrations/2022_07_29_021003_return_table.php @@ -0,0 +1,60 @@ +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'); + } +} diff --git a/resources/beike/admin/views/pages/rma_reasons/index.blade.php b/resources/beike/admin/views/pages/rma_reasons/index.blade.php new file mode 100644 index 00000000..20ab4408 --- /dev/null +++ b/resources/beike/admin/views/pages/rma_reasons/index.blade.php @@ -0,0 +1,39 @@ +@extends('admin::layouts.master') + +@section('title', '售后申请列表') + +@section('content') +
+
+
+ +
+ + + + + + + + + + @foreach ($rmaReasons as $rmaReason) + + + + + + @endforeach + +
ID名称操作
{{ $rmaReason->id }}{{ $rmaReason->name }}查看
+ + {{ $rmaReasons->links('admin::vendor/pagination/bootstrap-4') }} +
+
+@endsection + +@push('footer') + +@endpush diff --git a/resources/beike/admin/views/pages/rmas/index.blade.php b/resources/beike/admin/views/pages/rmas/index.blade.php new file mode 100644 index 00000000..24ce82db --- /dev/null +++ b/resources/beike/admin/views/pages/rmas/index.blade.php @@ -0,0 +1,48 @@ +@extends('admin::layouts.master') + +@section('title', '售后申请列表') + +@section('content') +
+
+ + + + + + + + + + + + + + + + @foreach ($rmas as $rma) + + + + + + + + + + + + @endforeach + +
客户姓名邮箱电话号码商品商品型号数量服务类型状态操作
{{ $rma->name }}{{ $rma->email }}{{ $rma->telephone }}{{ $rma->product_name }}{{ $rma->model }}{{ $rma->quantity }}{{ $rma->type }}{{ $rma->status }}查看
+ + {{ $rmas->links('admin::vendor/pagination/bootstrap-4') }} +
+
+@endsection + +@push('footer') + +@endpush diff --git a/resources/beike/admin/views/pages/rmas/info.blade.php b/resources/beike/admin/views/pages/rmas/info.blade.php new file mode 100644 index 00000000..0439e833 --- /dev/null +++ b/resources/beike/admin/views/pages/rmas/info.blade.php @@ -0,0 +1,62 @@ +@extends('admin::layouts.master') + +@section('title', '售后申请') + +@section('content') +
+
售后申请详情
+
+
+
+ + + + + + + + + + + + + + + +
ID:{{ $rma->id }}
客户姓名:{{ $rma->name }}
联系电话:{{ $rma->telephone }}
+
+
+ + + + + + + + + + + + + + + + + + + +
商品:{{ $rma->product_name }}
型号:{{ $rma->model }}
数量:{{ $rma->quantity }}
退货原因:{{ $rma->quantity }}
+
+
+
+
+ +
+
操作日志
+
+ +
+
+@endsection + +