Initial commit: Slim Framework 4 API Retribusi dengan modular architecture
This commit is contained in:
349
src/Modules/Retribusi/Frontend/LocationController.php
Normal file
349
src/Modules/Retribusi/Frontend/LocationController.php
Normal file
@@ -0,0 +1,349 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Modules\Retribusi\Frontend;
|
||||
|
||||
use App\Support\ResponseHelper;
|
||||
use App\Support\Validator;
|
||||
use PDOException;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class LocationController
|
||||
{
|
||||
private RetribusiReadService $readService;
|
||||
private RetribusiWriteService $writeService;
|
||||
private AuditService $auditService;
|
||||
|
||||
public function __construct(
|
||||
RetribusiReadService $readService,
|
||||
RetribusiWriteService $writeService,
|
||||
AuditService $auditService
|
||||
) {
|
||||
$this->readService = $readService;
|
||||
$this->writeService = $writeService;
|
||||
$this->auditService = $auditService;
|
||||
}
|
||||
|
||||
public function getLocations(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response
|
||||
): ResponseInterface {
|
||||
$queryParams = $request->getQueryParams();
|
||||
[$page, $limit] = Validator::validatePagination($queryParams);
|
||||
|
||||
$data = $this->readService->getLocations($page, $limit);
|
||||
$total = $this->readService->getLocationsTotal();
|
||||
|
||||
return ResponseHelper::json(
|
||||
$response,
|
||||
[
|
||||
'success' => true,
|
||||
'data' => $data,
|
||||
'meta' => [
|
||||
'page' => $page,
|
||||
'limit' => $limit,
|
||||
'total' => $total,
|
||||
'pages' => (int) ceil($total / $limit)
|
||||
],
|
||||
'timestamp' => time()
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function createLocation(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response
|
||||
): ResponseInterface {
|
||||
$body = $request->getParsedBody();
|
||||
|
||||
if (!is_array($body)) {
|
||||
return ResponseHelper::json(
|
||||
$response,
|
||||
[
|
||||
'error' => 'validation_error',
|
||||
'fields' => ['body' => 'Invalid JSON body']
|
||||
],
|
||||
422
|
||||
);
|
||||
}
|
||||
|
||||
$errors = Validator::validateLocation($body, false);
|
||||
if (!empty($errors)) {
|
||||
return ResponseHelper::json(
|
||||
$response,
|
||||
[
|
||||
'error' => 'validation_error',
|
||||
'fields' => $errors
|
||||
],
|
||||
422
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
// Check if location already exists
|
||||
$existing = $this->writeService->getLocation($body['code']);
|
||||
if ($existing !== null) {
|
||||
return ResponseHelper::json(
|
||||
$response,
|
||||
[
|
||||
'error' => 'conflict',
|
||||
'message' => 'Location with this code already exists'
|
||||
],
|
||||
409
|
||||
);
|
||||
}
|
||||
|
||||
// Create location
|
||||
$data = $this->writeService->createLocation($body);
|
||||
|
||||
// Audit log
|
||||
$serverParams = $request->getServerParams();
|
||||
$this->auditService->log(
|
||||
(int) $request->getAttribute('user_id'),
|
||||
$request->getAttribute('username', ''),
|
||||
$request->getAttribute('role', ''),
|
||||
'create',
|
||||
'locations',
|
||||
$body['code'],
|
||||
null,
|
||||
$data,
|
||||
AuditService::getClientIp($serverParams),
|
||||
$serverParams['HTTP_USER_AGENT'] ?? null
|
||||
);
|
||||
|
||||
return ResponseHelper::json(
|
||||
$response,
|
||||
[
|
||||
'success' => true,
|
||||
'data' => $data,
|
||||
'timestamp' => time()
|
||||
],
|
||||
201
|
||||
);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
// Check for unique constraint violation
|
||||
if ($e->getCode() === '23000') {
|
||||
return ResponseHelper::json(
|
||||
$response,
|
||||
[
|
||||
'error' => 'conflict',
|
||||
'message' => 'Location with this code already exists'
|
||||
],
|
||||
409
|
||||
);
|
||||
}
|
||||
|
||||
return ResponseHelper::json(
|
||||
$response,
|
||||
[
|
||||
'error' => 'server_error',
|
||||
'message' => 'Database error occurred'
|
||||
],
|
||||
500
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function updateLocation(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response,
|
||||
array $args
|
||||
): ResponseInterface {
|
||||
$code = $args['code'] ?? null;
|
||||
if ($code === null || !is_string($code)) {
|
||||
return ResponseHelper::json(
|
||||
$response,
|
||||
[
|
||||
'error' => 'validation_error',
|
||||
'fields' => ['code' => 'Invalid location code']
|
||||
],
|
||||
422
|
||||
);
|
||||
}
|
||||
|
||||
$body = $request->getParsedBody();
|
||||
if (!is_array($body)) {
|
||||
return ResponseHelper::json(
|
||||
$response,
|
||||
[
|
||||
'error' => 'validation_error',
|
||||
'fields' => ['body' => 'Invalid JSON body']
|
||||
],
|
||||
422
|
||||
);
|
||||
}
|
||||
|
||||
// Prevent changing code
|
||||
if (isset($body['code']) && $body['code'] !== $code) {
|
||||
return ResponseHelper::json(
|
||||
$response,
|
||||
[
|
||||
'error' => 'validation_error',
|
||||
'fields' => ['code' => 'Code is immutable']
|
||||
],
|
||||
422
|
||||
);
|
||||
}
|
||||
|
||||
$errors = Validator::validateLocation($body, true);
|
||||
if (!empty($errors)) {
|
||||
return ResponseHelper::json(
|
||||
$response,
|
||||
[
|
||||
'error' => 'validation_error',
|
||||
'fields' => $errors
|
||||
],
|
||||
422
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
// Check if location exists
|
||||
$before = $this->writeService->getLocation($code);
|
||||
if ($before === null) {
|
||||
return ResponseHelper::json(
|
||||
$response,
|
||||
[
|
||||
'error' => 'not_found',
|
||||
'message' => 'Location not found'
|
||||
],
|
||||
404
|
||||
);
|
||||
}
|
||||
|
||||
// Update location
|
||||
$after = $this->writeService->updateLocation($code, $body);
|
||||
if ($after === null) {
|
||||
return ResponseHelper::json(
|
||||
$response,
|
||||
[
|
||||
'error' => 'not_found',
|
||||
'message' => 'Location not found'
|
||||
],
|
||||
404
|
||||
);
|
||||
}
|
||||
|
||||
// Audit log
|
||||
$serverParams = $request->getServerParams();
|
||||
$this->auditService->log(
|
||||
(int) $request->getAttribute('user_id'),
|
||||
$request->getAttribute('username', ''),
|
||||
$request->getAttribute('role', ''),
|
||||
'update',
|
||||
'locations',
|
||||
$code,
|
||||
$before,
|
||||
$after,
|
||||
AuditService::getClientIp($serverParams),
|
||||
$serverParams['HTTP_USER_AGENT'] ?? null
|
||||
);
|
||||
|
||||
return ResponseHelper::json(
|
||||
$response,
|
||||
[
|
||||
'success' => true,
|
||||
'data' => $after,
|
||||
'timestamp' => time()
|
||||
]
|
||||
);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
return ResponseHelper::json(
|
||||
$response,
|
||||
[
|
||||
'error' => 'server_error',
|
||||
'message' => 'Database error occurred'
|
||||
],
|
||||
500
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteLocation(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response,
|
||||
array $args
|
||||
): ResponseInterface {
|
||||
$code = $args['code'] ?? null;
|
||||
if ($code === null || !is_string($code)) {
|
||||
return ResponseHelper::json(
|
||||
$response,
|
||||
[
|
||||
'error' => 'validation_error',
|
||||
'fields' => ['code' => 'Invalid location code']
|
||||
],
|
||||
422
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
// Check if location exists
|
||||
$before = $this->writeService->getLocation($code);
|
||||
if ($before === null) {
|
||||
return ResponseHelper::json(
|
||||
$response,
|
||||
[
|
||||
'error' => 'not_found',
|
||||
'message' => 'Location not found'
|
||||
],
|
||||
404
|
||||
);
|
||||
}
|
||||
|
||||
// Soft delete
|
||||
$deleted = $this->writeService->deleteLocation($code);
|
||||
if (!$deleted) {
|
||||
return ResponseHelper::json(
|
||||
$response,
|
||||
[
|
||||
'error' => 'server_error',
|
||||
'message' => 'Failed to delete location'
|
||||
],
|
||||
500
|
||||
);
|
||||
}
|
||||
|
||||
// Get after state (is_active=0)
|
||||
$after = $this->writeService->getLocation($code);
|
||||
|
||||
// Audit log
|
||||
$serverParams = $request->getServerParams();
|
||||
$this->auditService->log(
|
||||
(int) $request->getAttribute('user_id'),
|
||||
$request->getAttribute('username', ''),
|
||||
$request->getAttribute('role', ''),
|
||||
'delete',
|
||||
'locations',
|
||||
$code,
|
||||
$before,
|
||||
$after,
|
||||
AuditService::getClientIp($serverParams),
|
||||
$serverParams['HTTP_USER_AGENT'] ?? null
|
||||
);
|
||||
|
||||
return ResponseHelper::json(
|
||||
$response,
|
||||
[
|
||||
'success' => true,
|
||||
'data' => ['deleted' => true],
|
||||
'timestamp' => time()
|
||||
]
|
||||
);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
return ResponseHelper::json(
|
||||
$response,
|
||||
[
|
||||
'error' => 'server_error',
|
||||
'message' => 'Database error occurred'
|
||||
],
|
||||
500
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user