改进 工单系统

This commit is contained in:
iVampireSP.com 2022-08-15 22:29:57 +08:00
parent 90b357591e
commit 17c816ac50
No known key found for this signature in database
GPG Key ID: 2F7B001CA27A8132
16 changed files with 351 additions and 51 deletions

View File

@ -1,6 +1,6 @@
<?php <?php
namespace App\Http\Controllers\Remote\User; namespace App\Http\Controllers\Remote\Host;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use Illuminate\Http\Request; use Illuminate\Http\Request;
@ -16,10 +16,10 @@ public function __construct(Request $request)
{ {
$request->validate([ $request->validate([
'host_id' => 'sometimes|integer|exists:hosts,id', 'host_id' => 'sometimes|integer|exists:hosts,id',
'user_id' => 'integer|exists:users,id', // 'user_id' => 'integer|exists:users,id',
]); ]);
$this->user_id = $request->user_id; // $this->user_id = $request->user_id;
$this->host_id = $request->host_id; $this->host_id = $request->host_id;
} }
@ -100,7 +100,7 @@ public function pushTask($task, $id = null)
{ {
$cache_key = 'user_tasks_' . $this->user_id; $cache_key = 'user_tasks_' . $this->user_id;
$data = [ $data = [
'user_id' => $this->user_id, // 'user_id' => $this->user_id,
'done_at' => null, 'done_at' => null,
'host_id' => $this->host_id 'host_id' => $this->host_id
]; ];

View File

@ -0,0 +1,43 @@
<?php
namespace App\Http\Controllers\Remote\WorkOrder;
use Illuminate\Http\Request;
use App\Models\WorkOrder\Reply;
use App\Http\Controllers\Controller;
class ReplyController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
{
//
$replies = Reply::workOrderId($request->route('work_order'))->simplePaginate(10);
return $this->success($replies);
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
$request->validate([
'content' => 'string|required|min:1|max:1000',
]);
$reply = Reply::create([
'content' => $request->content,
'work_order_id' => $request->route('work_order'),
]);
return $this->success($reply);
}
}

View File

@ -0,0 +1,47 @@
<?php
namespace App\Http\Controllers\Remote\WorkOrder;
use Illuminate\Http\Request;
use App\Models\WorkOrder\WorkOrder;
use App\Http\Controllers\Controller;
use App\Http\Requests\Remote\WorkOrderRequest;
class WorkOrderController extends Controller
{
//
public function index(Request $request, WorkOrder $workOrder) {
// $work_orders = new WorkOrder();
// // if route has user
// if ($request->route('user')) {
// $work_orders = $work_orders->where('user_id', $request->route('user'));
// }
// $work_orders = $work_orders->simplePaginate(10);
$workOrder = $workOrder->thisModule()->simplePaginate(10);
return $this->success($workOrder);
}
// public function store(Request $request) {
// }
public function show(WorkOrderRequest $request, WorkOrder $workOrder) {
return $this->success($workOrder);
}
public function update(WorkOrderRequest $request, WorkOrder $workOrder)
{
$request->validate([
'status' => 'nullable|sometimes|string|in:open,closed,on_hold,in_progress',
]);
$workOrder->update($request->only('status'));
return $this->success($workOrder);
}
// public function destroy() {}
}

View File

@ -1,11 +0,0 @@
<?php
namespace App\Http\Controllers\Remote;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class WorkOrderController extends Controller
{
//
}

View File

@ -0,0 +1,47 @@
<?php
namespace App\Http\Controllers\User\WorkOrder;
use App\Http\Controllers\Controller;
use App\Http\Requests\User\WorkOrder\WorkOrderRequest;
use App\Models\WorkOrder\Reply;
use Illuminate\Http\Request;
class ReplyController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index(WorkOrderRequest $request)
{
//
$replies = Reply::workOrderId($request->route('work_order'))->simplePaginate(10);
return $this->success($replies);
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(WorkOrderRequest $request)
{
// add reply
$request->validate([
'content' => 'string|required|min:1|max:1000',
]);
$reply = Reply::create([
'content' => $request->content,
'work_order_id' => $request->route('work_order'),
]);
return $this->success($reply);
}
}

View File

@ -0,0 +1,57 @@
<?php
namespace App\Http\Controllers\User\WorkOrder;
use Illuminate\Http\Request;
use App\Models\WorkOrder\WorkOrder;
use App\Http\Controllers\Controller;
use App\Http\Requests\User\WorkOrder\WorkOrderRequest;
class WorkOrderController extends Controller
{
//
public function index(Request $request, WorkOrder $workOrder) {
$workOrder = $workOrder->user()->simplePaginate(10);
return $this->success($workOrder);
}
public function store(Request $request) {
$request->validate([
'title' => 'required|max:255',
'content' => 'required',
'module_id' => 'nullable|sometimes|string|exists:modules,id',
'host_id' => 'nullable|sometimes|string|exists:hosts,id',
]);
// module_id 和 host_id 必须有个要填写
if (!$request->module_id && !$request->host_id) {
return $this->error('module_id 和 host_id 至少要填写一个');
}
$workOrder = WorkOrder::create([
'title' => $request->title,
'content' => $request->content,
'module_id' => $request->module_id,
'host_id' => $request->host_id,
'status' => 'pending',
]);
return $this->success($workOrder);
}
public function show(WorkOrderRequest $request, WorkOrder $workOrder) {
return $this->success($workOrder);
}
public function update(WorkOrderRequest $request, WorkOrder $workOrder) {
$request->validate([
'status' => 'nullable|sometimes|string|in:closed',
]);
$workOrder->update($request->only('status'));
return $this->success($workOrder);
}
}

View File

@ -1,11 +0,0 @@
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class WorkOrderController extends Controller
{
//
}

View File

@ -2,6 +2,7 @@
namespace App\Http\Requests\Remote; namespace App\Http\Requests\Remote;
use App\Models\WorkOrder\WorkOrder;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
class WorkOrderRequest extends FormRequest class WorkOrderRequest extends FormRequest
@ -13,7 +14,7 @@ class WorkOrderRequest extends FormRequest
*/ */
public function authorize() public function authorize()
{ {
return false; return WorkOrder::where('id', $this->route('work_order')->id)->where('module_id', auth('remote')->id())->exists();
} }
/** /**

View File

@ -1,7 +1,8 @@
<?php <?php
namespace App\Http\Requests\User; namespace App\Http\Requests\User\WorkOrder;
use App\Models\WorkOrder\WorkOrder;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
class WorkOrderRequest extends FormRequest class WorkOrderRequest extends FormRequest
@ -13,6 +14,19 @@ class WorkOrderRequest extends FormRequest
*/ */
public function authorize() public function authorize()
{ {
$work_order = $this->route('work_order');
// if work_order is model
if ($work_order instanceof WorkOrder) {
$work_order_id = $work_order->id;
} else {
$work_order_id = $work_order;
}
return WorkOrder::where('user_id', auth('sanctum')->id())->where('id', $work_order_id)->exists();
return false; return false;
} }

View File

@ -9,13 +9,49 @@ class Reply extends Model
{ {
use HasFactory; use HasFactory;
protected $table = 'workorder_replies'; protected $table = 'work_order_replies';
protected $fillable = [ protected $fillable = [
'content', 'content',
'work_order_id', 'work_order_id',
'user_id', // 'user_id',
'is_pending', 'is_pending',
]; ];
public function workOrder()
{
return $this->belongsTo(WorkOrder::class);
}
public function scopeWorkOrderId($query, $work_order_id)
{
return $query->where('work_order_id', $work_order_id);
}
// before create
protected static function boot()
{
parent::boot();
static::creating(function ($model) {
// load work order
$model->load(['workOrder']);
// change work order status
if (auth('sanctum')->check()) {
$model->user_id = auth()->id();
$model->workOrder->status = 'user_replied';
}
if (auth('remote')->check()) {
$model->user_id = null;
$model->workOrder->status = 'replied';
}
$model->workOrder->save();
});
}
} }

View File

@ -3,23 +3,24 @@
namespace App\Models\WorkOrder; namespace App\Models\WorkOrder;
use App\Models\User\Host; use App\Models\User\Host;
use Illuminate\Support\Arr;
use App\Models\Module\Module;
use App\Exceptions\CommonException; use App\Exceptions\CommonException;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Support\Arr;
class WorkOrder extends Model class WorkOrder extends Model
{ {
use HasFactory; use HasFactory;
protected $table = 'workorders'; protected $table = 'work_orders';
protected $fillable = [ protected $fillable = [
'title', 'title',
'content', 'content',
'host_id', 'host_id',
'user_id', 'user_id',
'provider_module_id', 'module_id',
'status', 'status',
]; ];
@ -30,12 +31,28 @@ public function replies()
return $this->hasMany(Reply::class); return $this->hasMany(Reply::class);
} }
// provider module // host
public function host() public function host()
{ {
return $this->belongsTo(Host::class); return $this->belongsTo(Host::class);
} }
public function module()
{
return $this->belongsTo(Module::class);
}
// scope
public function scopeThisModule($query)
{
return $query->where('module_id', auth('remote')->id());
}
public function scopeUser($query)
{
return $query->where('user_id', auth()->id());
}
// on create // on create
protected static function boot() protected static function boot()
@ -43,22 +60,37 @@ protected static function boot()
parent::boot(); parent::boot();
static::creating(function ($model) { static::creating(function ($model) {
$model->load('host');
if (!$model->user_id === $model->host->user_id) { if ($model->host_id) {
throw new CommonException('user_id not match host user_id'); $model->load(['host']);
$model->module_id = $model->host->module_id;
} }
$model->host->load('provider_module'); // if logged
$provider_module = $model->host->provider_module; if (auth('sanctum')->check()) {
$model->user_id = auth('sanctum')->id();
if ($model->host_id) {
if ($provider_module === null) { if (!$model->user_id === $model->host->user_id) {
$model->status = 'open'; throw new CommonException('user_id not match host user_id');
}
}
} else { } else {
$model->status = 'pending'; throw new CommonException('user_id is required');
} }
if ($model->host_id) {
$model->host->load('module');
$module = $model->host->module;
if ($module === null) {
$model->status = 'open';
} else {
$model->status = 'pending';
}
}
}); });
// 更新时获取差异部分 // 更新时获取差异部分

View File

@ -17,7 +17,7 @@
*/ */
public function up() public function up()
{ {
Schema::create('workorders', function (Blueprint $table) { Schema::create('work_orders', function (Blueprint $table) {
$table->id(); $table->id();
// title // title
@ -30,8 +30,12 @@ public function up()
$table->unsignedBigInteger('user_id')->index(); $table->unsignedBigInteger('user_id')->index();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
// module id
$table->string('module_id')->index();
$table->foreign('module_id')->references('id')->on('modules')->onDelete('cascade');
// host id // host id
$table->unsignedBigInteger('host_id')->index(); $table->unsignedBigInteger('host_id')->index()->nullable();
$table->foreign('host_id')->references('id')->on('hosts')->onDelete('cascade'); $table->foreign('host_id')->references('id')->on('hosts')->onDelete('cascade');
// status // status

View File

@ -15,15 +15,15 @@
*/ */
public function up() public function up()
{ {
Schema::create('workorder_replies', function (Blueprint $table) { Schema::create('work_order_replies', function (Blueprint $table) {
$table->id(); $table->id();
// content // content
$table->text('content'); $table->text('content');
// workorder id (on delete cascade) // workorder id (on delete cascade)
$table->unsignedBigInteger('workorder_id')->index(); $table->unsignedBigInteger('work_order_id')->index();
$table->foreign('workorder_id')->references('id')->on('workorders')->onDelete('cascade'); $table->foreign('work_order_id')->references('id')->on('work_orders')->onDelete('cascade');
// user id // user id
$table->unsignedBigInteger('user_id')->index(); $table->unsignedBigInteger('user_id')->index();

View File

@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('work_order_replies', function (Blueprint $table) {
//
$table->unsignedBigInteger('user_id')->nullable()->change();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('work_order_replies', function (Blueprint $table) {
//
});
}
};

View File

@ -2,12 +2,15 @@
use App\Http\Controllers; use App\Http\Controllers;
use App\Http\Controllers\Admin\User\DropController; use App\Http\Controllers\Admin\User\DropController;
use App\Models\Admin\Admin; use App\Http\Controllers\User;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
Route::name('client.')->middleware(['api'])->group(function () { Route::name('client.')->middleware(['api', 'auth:sanctum'])->group(function () {
// Route::apiResource('users', Controllers\User\UserController::class); // Route::apiResource('users', Controllers\User\UserController::class);
Route::apiResource('drops', DropController::class); Route::apiResource('drops', DropController::class);
Route::apiResource('work-orders', User\WorkOrder\WorkOrderController::class);
Route::apiResource('work-orders.replies', User\WorkOrder\ReplyController::class);
}); });

View File

@ -7,6 +7,10 @@
Route::apiResource('modules', Remote\ModuleController::class)->only(['index']); Route::apiResource('modules', Remote\ModuleController::class)->only(['index']);
Route::apiResource('servers', Remote\ServerController::class); Route::apiResource('servers', Remote\ServerController::class);
Route::patch('hosts/{host}/drops', [Remote\Host\DropController::class, 'update']); Route::patch('hosts/{host}/drops', [Remote\Host\DropController::class, 'update']);
Route::apiResource('users.tasks', Remote\User\TaskController::class); Route::apiResource('hosts.tasks', Remote\Host\TaskController::class);
Route::apiResource('work-orders', Remote\WorkOrder\WorkOrderController::class);
Route::apiResource('work-orders.replies', Remote\WorkOrder\ReplyController::class);
// Route::apiResource('users', Controllers\User\UserController::class); // Route::apiResource('users', Controllers\User\UserController::class);
}); });