forked from admin/services_core
Ubah dari Swagger ke Dedoc lalu buat API Ticket dan TicketType
This commit is contained in:
@@ -1,20 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Docs;
|
||||
|
||||
use OpenApi\Attributes as OA;
|
||||
|
||||
#[OA\Info(
|
||||
version: '1.0.0',
|
||||
title: 'Services Core API',
|
||||
description: 'API Backend Services Core'
|
||||
)]
|
||||
|
||||
#[OA\Server(
|
||||
url: 'http://127.0.0.1:8000',
|
||||
description: 'Local Development Server'
|
||||
)]
|
||||
|
||||
class OpenApiSpec
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Traits\ApiResponse;
|
||||
|
||||
class ApiController extends Controller
|
||||
{
|
||||
use ApiResponse;
|
||||
}
|
||||
@@ -5,38 +5,10 @@ namespace App\Http\Controllers;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use OpenApi\Attributes as OA;
|
||||
|
||||
class AuthController extends Controller
|
||||
{
|
||||
#[OA\Post(
|
||||
path: "/api/login",
|
||||
summary: "Login User",
|
||||
tags: ["Authentication"]
|
||||
)]
|
||||
#[OA\RequestBody(
|
||||
required: true,
|
||||
content: new OA\JsonContent(
|
||||
required: ["email", "password"],
|
||||
properties: [
|
||||
new OA\Property(
|
||||
property: "email",
|
||||
type: "string",
|
||||
example: "admin@test.co.id"
|
||||
),
|
||||
new OA\Property(
|
||||
property: "password",
|
||||
type: "string",
|
||||
example: "123456"
|
||||
)
|
||||
]
|
||||
)
|
||||
)]
|
||||
#[OA\Response(
|
||||
response: 200,
|
||||
description: "Login Success"
|
||||
)]
|
||||
|
||||
|
||||
public function login(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Ticket;
|
||||
|
||||
use App\Http\Controllers\ApiController;
|
||||
use App\Http\Requests\Ticket\StoreTicketRequest;
|
||||
use App\Http\Requests\Ticket\UpdateTicketRequest;
|
||||
use App\Http\Resources\Ticket\TicketResource;
|
||||
use App\Models\Ticket;
|
||||
use App\Services\Ticket\TicketService;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class TicketController extends ApiController
|
||||
{
|
||||
public function __construct(
|
||||
protected TicketService $service
|
||||
) {}
|
||||
|
||||
public function index(Request $request)
|
||||
{
|
||||
$tickets = Ticket::latest()->paginate(
|
||||
$request->get('per_page', 10)
|
||||
);
|
||||
|
||||
return $this->success($tickets);
|
||||
}
|
||||
|
||||
public function store(StoreTicketRequest $request)
|
||||
{
|
||||
$ticket = $this->service->create(
|
||||
$request->validated()
|
||||
);
|
||||
|
||||
return $this->created(
|
||||
new TicketResource($ticket),
|
||||
'Ticket berhasil dibuat'
|
||||
);
|
||||
}
|
||||
|
||||
public function show(Ticket $ticket)
|
||||
{
|
||||
return $this->success(
|
||||
new TicketResource($ticket)
|
||||
);
|
||||
}
|
||||
|
||||
public function update(
|
||||
UpdateTicketRequest $request,
|
||||
Ticket $ticket
|
||||
) {
|
||||
$ticket = $this->service->update(
|
||||
$ticket,
|
||||
$request->validated()
|
||||
);
|
||||
|
||||
return $this->updated(
|
||||
new TicketResource($ticket),
|
||||
'Ticket berhasil diperbarui'
|
||||
);
|
||||
}
|
||||
|
||||
public function destroy(Ticket $ticket)
|
||||
{
|
||||
$this->service->delete($ticket);
|
||||
|
||||
return $this->deleted(
|
||||
'Ticket berhasil dibatalkan'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Ticket;
|
||||
|
||||
use App\Http\Controllers\ApiController;
|
||||
use App\Http\Requests\TicketType\StoreTicketTypeRequest;
|
||||
use App\Http\Requests\TicketType\UpdateTicketTypeRequest;
|
||||
use App\Http\Resources\TicketType\TicketTypeResource;
|
||||
use App\Models\TicketType;
|
||||
use App\Services\Ticket\TicketTypeService;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class TicketTypeController extends ApiController
|
||||
{
|
||||
public function __construct(
|
||||
protected TicketTypeService $service
|
||||
) {}
|
||||
|
||||
public function index(Request $request)
|
||||
{
|
||||
$data = TicketType::latest()->paginate(
|
||||
$request->get('per_page', 10)
|
||||
);
|
||||
|
||||
return $this->success($data);
|
||||
}
|
||||
|
||||
public function store(StoreTicketTypeRequest $request)
|
||||
{
|
||||
$type = $this->service->create(
|
||||
$request->validated()
|
||||
);
|
||||
|
||||
return $this->created(
|
||||
new TicketTypeResource($type),
|
||||
'Ticket Type berhasil dibuat'
|
||||
);
|
||||
}
|
||||
|
||||
public function show(TicketType $ticket_type)
|
||||
{
|
||||
return $this->success(
|
||||
new TicketTypeResource($ticket_type)
|
||||
);
|
||||
}
|
||||
|
||||
public function update(
|
||||
UpdateTicketTypeRequest $request,
|
||||
TicketType $ticket_type
|
||||
) {
|
||||
$type = $this->service->update(
|
||||
$ticket_type,
|
||||
$request->validated()
|
||||
);
|
||||
|
||||
return $this->updated(
|
||||
new TicketTypeResource($type),
|
||||
'Ticket Type berhasil diupdate'
|
||||
);
|
||||
}
|
||||
|
||||
public function destroy(TicketType $ticket_type)
|
||||
{
|
||||
$this->service->delete($ticket_type);
|
||||
|
||||
return $this->deleted(
|
||||
'Ticket Type berhasil dihapus'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\Ticket;
|
||||
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreTicketRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, ValidationRule|array<mixed>|string>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'ticket_type_id' => 'required|integer',
|
||||
'customer_id' => 'nullable|integer',
|
||||
'title' => 'required|string|max:255',
|
||||
'description' => 'nullable|string',
|
||||
'priority' => 'required|in:low,medium,high,critical'
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\Ticket;
|
||||
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class UpdateTicketRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, ValidationRule|array<mixed>|string>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'ticket_type_id' => 'sometimes|integer',
|
||||
'customer_id' => 'nullable|integer',
|
||||
'title' => 'sometimes|string|max:255',
|
||||
'description' => 'nullable|string',
|
||||
'priority' => 'sometimes|in:low,medium,high,critical',
|
||||
'status' => 'sometimes|in:draft,open,approved,assigned,progress,pending,resolved,closed,cancelled,rejected'
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\TicketType;
|
||||
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreTicketTypeRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, ValidationRule|array<mixed>|string>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'code' => 'required|string|max:50|unique:ticket_types,code',
|
||||
'name' => 'required|string|max:100',
|
||||
'need_approval' => 'boolean',
|
||||
'sla_minutes' => 'nullable|integer'
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\TicketType;
|
||||
|
||||
use Illuminate\Contracts\Validation\ValidationRule;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class UpdateTicketTypeRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, ValidationRule|array<mixed>|string>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'code' => 'sometimes|string|max:50|unique:ticket_types,code,' . $this->route('ticket_type'),
|
||||
'name' => 'sometimes|string|max:100',
|
||||
'need_approval' => 'sometimes|boolean',
|
||||
'sla_minutes' => 'nullable|integer'
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources\Ticket;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class TicketResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'ticket_no' => $this->ticket_no,
|
||||
'ticket_type_id' => $this->ticket_type_id,
|
||||
'customer_id' => $this->customer_id,
|
||||
'title' => $this->title,
|
||||
'description' => $this->description,
|
||||
'priority' => $this->priority,
|
||||
'status' => $this->status,
|
||||
'created_by' => $this->created_by,
|
||||
'created_at' => $this->created_at,
|
||||
'updated_at' => $this->updated_at,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources\TicketType;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class TicketTypeResource extends JsonResource
|
||||
{
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'code' => $this->code,
|
||||
'name' => $this->name,
|
||||
'need_approval' => $this->need_approval,
|
||||
'sla_minutes' => $this->sla_minutes,
|
||||
'created_at' => $this->created_at,
|
||||
'updated_at' => $this->updated_at,
|
||||
];
|
||||
}
|
||||
}
|
||||
+10
-1
@@ -6,5 +6,14 @@ use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Ticket extends Model
|
||||
{
|
||||
//
|
||||
protected $fillable = [
|
||||
'ticket_no',
|
||||
'ticket_type_id',
|
||||
'customer_id',
|
||||
'title',
|
||||
'description',
|
||||
'priority',
|
||||
'status',
|
||||
'created_by',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -6,5 +6,15 @@ use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class TicketLog extends Model
|
||||
{
|
||||
//
|
||||
public $timestamps = false;
|
||||
|
||||
protected $fillable = [
|
||||
'ticket_id',
|
||||
'user_id',
|
||||
'activity',
|
||||
'notes',
|
||||
'latitude',
|
||||
'longitude',
|
||||
'created_at'
|
||||
];
|
||||
}
|
||||
|
||||
@@ -6,5 +6,16 @@ use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class TicketType extends Model
|
||||
{
|
||||
//
|
||||
protected $table = 'ticket_types';
|
||||
|
||||
protected $fillable = [
|
||||
'code',
|
||||
'name',
|
||||
'need_approval',
|
||||
'sla_minutes'
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'need_approval' => 'boolean',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Ticket;
|
||||
|
||||
use App\Models\Ticket;
|
||||
use App\Models\TicketLog;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class TicketService
|
||||
{
|
||||
public function create(array $data): Ticket
|
||||
{
|
||||
return DB::transaction(function () use ($data) {
|
||||
|
||||
$ticket = Ticket::create([
|
||||
'ticket_no' => $this->generateTicketNo(),
|
||||
'ticket_type_id' => $data['ticket_type_id'],
|
||||
'customer_id' => $data['customer_id'] ?? null,
|
||||
'title' => $data['title'],
|
||||
'description' => $data['description'] ?? null,
|
||||
'priority' => $data['priority'],
|
||||
'status' => 'open',
|
||||
'created_by' => 1
|
||||
]);
|
||||
|
||||
TicketLog::create([
|
||||
'ticket_id' => $ticket->id,
|
||||
'user_id' => 1,
|
||||
'activity' => 'Ticket Created',
|
||||
'notes' => 'Ticket dibuat oleh sistem',
|
||||
'created_at'=> now()
|
||||
]);
|
||||
|
||||
return $ticket;
|
||||
});
|
||||
}
|
||||
|
||||
public function update(Ticket $ticket, array $data): Ticket
|
||||
{
|
||||
$ticket->update($data);
|
||||
|
||||
return $ticket->fresh();
|
||||
}
|
||||
|
||||
public function delete(Ticket $ticket): Ticket
|
||||
{
|
||||
$ticket->update([
|
||||
'status' => 'cancelled'
|
||||
]);
|
||||
|
||||
return $ticket;
|
||||
}
|
||||
|
||||
private function generateTicketNo(): string
|
||||
{
|
||||
$prefix = 'TCK-' . now()->format('Ym');
|
||||
|
||||
$lastTicket = Ticket::where(
|
||||
'ticket_no',
|
||||
'like',
|
||||
$prefix . '%'
|
||||
)
|
||||
->latest('id')
|
||||
->first();
|
||||
|
||||
$number = 1;
|
||||
|
||||
if ($lastTicket) {
|
||||
$number = ((int) substr($lastTicket->ticket_no, -6)) + 1;
|
||||
}
|
||||
|
||||
return $prefix . '-' . str_pad(
|
||||
$number,
|
||||
6,
|
||||
'0',
|
||||
STR_PAD_LEFT
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Ticket;
|
||||
|
||||
use App\Models\TicketType;
|
||||
|
||||
class TicketTypeService
|
||||
{
|
||||
public function create(array $data): TicketType
|
||||
{
|
||||
return TicketType::create($data);
|
||||
}
|
||||
|
||||
public function update(TicketType $type, array $data): TicketType
|
||||
{
|
||||
$type->update($data);
|
||||
return $type->fresh();
|
||||
}
|
||||
|
||||
public function delete(TicketType $type): bool
|
||||
{
|
||||
return $type->delete();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace App\Traits;
|
||||
|
||||
trait ApiResponse
|
||||
{
|
||||
protected function success($data = null, string $message = 'Success', int $code = 200)
|
||||
{
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'code' => $code,
|
||||
'message' => $message,
|
||||
'data' => $data
|
||||
], $code);
|
||||
}
|
||||
|
||||
protected function created($data = null, string $message = 'Data berhasil dibuat')
|
||||
{
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'code' => 201,
|
||||
'message' => $message,
|
||||
'data' => $data
|
||||
], 201);
|
||||
}
|
||||
|
||||
protected function updated($data = null, string $message = 'Data berhasil diperbarui')
|
||||
{
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'code' => 200,
|
||||
'message' => $message,
|
||||
'data' => $data
|
||||
]);
|
||||
}
|
||||
|
||||
protected function deleted(string $message = 'Data berhasil dihapus')
|
||||
{
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'code' => 200,
|
||||
'message' => $message
|
||||
]);
|
||||
}
|
||||
|
||||
protected function error(string $message = 'Internal Server Error', int $code = 500)
|
||||
{
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'code' => $code,
|
||||
'message' => $message
|
||||
], $code);
|
||||
}
|
||||
|
||||
protected function validationError($errors)
|
||||
{
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'code' => 422,
|
||||
'message' => 'Validation Error',
|
||||
'errors' => $errors
|
||||
], 422);
|
||||
}
|
||||
|
||||
protected function notFound(string $message = 'Data tidak ditemukan')
|
||||
{
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'code' => 404,
|
||||
'message' => $message
|
||||
], 404);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user