Add comprehensive project documentation for ClinicPro in CLAUDE.md and README.md
- Introduced CLAUDE.md for internal guidance on project structure, commands, and architecture. - Created README.md with detailed project overview, technology stack, directory structure, setup instructions, API endpoints, authentication flow, and external services.
This commit is contained in:
@@ -9,12 +9,14 @@ use App\Settlement\Repository\SettlementRepository;
|
||||
use App\Settlement\Repository\WalletTransactionRepository;
|
||||
use App\Shared\Constant\ErrorCodes;
|
||||
use App\Shared\Controller\BaseController;
|
||||
use OpenApi\Attributes as OA;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\CurrentUser;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
#[OA\Tag(name: 'Settlements')]
|
||||
#[IsGranted('IS_AUTHENTICATED_FULLY')]
|
||||
class SettlementController extends BaseController
|
||||
{
|
||||
@@ -25,6 +27,27 @@ class SettlementController extends BaseController
|
||||
|
||||
// ── Wallet ────────────────────────────────────────────────────────────────
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/wallet/balance',
|
||||
summary: 'Get current wallet balance and recent transactions',
|
||||
security: [['bearerAuth' => []]],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 200,
|
||||
description: 'Wallet balance and recent transactions',
|
||||
content: new OA\JsonContent(
|
||||
properties: [
|
||||
new OA\Property(property: 'success', type: 'boolean', example: true),
|
||||
new OA\Property(property: 'data', properties: [
|
||||
new OA\Property(property: 'balance_rials', type: 'integer'),
|
||||
new OA\Property(property: 'recent_transactions', type: 'array', items: new OA\Items(type: 'object')),
|
||||
], type: 'object'),
|
||||
]
|
||||
)
|
||||
),
|
||||
new OA\Response(response: 401, description: 'Unauthorized'),
|
||||
]
|
||||
)]
|
||||
#[Route('/api/v1/wallet/balance', methods: ['GET'])]
|
||||
public function balance(#[CurrentUser] User $user): JsonResponse
|
||||
{
|
||||
@@ -40,6 +63,24 @@ class SettlementController extends BaseController
|
||||
]);
|
||||
}
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/wallet/transactions',
|
||||
summary: 'List all wallet transactions for the authenticated user',
|
||||
security: [['bearerAuth' => []]],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 200,
|
||||
description: 'List of wallet transactions',
|
||||
content: new OA\JsonContent(
|
||||
properties: [
|
||||
new OA\Property(property: 'success', type: 'boolean', example: true),
|
||||
new OA\Property(property: 'data', type: 'array', items: new OA\Items(type: 'object')),
|
||||
]
|
||||
)
|
||||
),
|
||||
new OA\Response(response: 401, description: 'Unauthorized'),
|
||||
]
|
||||
)]
|
||||
#[Route('/api/v1/wallet/transactions', methods: ['GET'])]
|
||||
public function transactions(#[CurrentUser] User $user): JsonResponse
|
||||
{
|
||||
@@ -53,6 +94,35 @@ class SettlementController extends BaseController
|
||||
|
||||
// ── Settlement Requests ───────────────────────────────────────────────────
|
||||
|
||||
#[OA\Post(
|
||||
path: '/api/v1/settlement',
|
||||
summary: 'Request a new settlement (withdrawal)',
|
||||
security: [['bearerAuth' => []]],
|
||||
requestBody: new OA\RequestBody(
|
||||
required: true,
|
||||
content: new OA\JsonContent(
|
||||
required: ['amount_rials'],
|
||||
properties: [
|
||||
new OA\Property(property: 'amount_rials', type: 'integer', minimum: 1),
|
||||
new OA\Property(property: 'bank_account', type: 'object', nullable: true),
|
||||
]
|
||||
)
|
||||
),
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 201,
|
||||
description: 'Settlement request created',
|
||||
content: new OA\JsonContent(
|
||||
properties: [
|
||||
new OA\Property(property: 'success', type: 'boolean', example: true),
|
||||
new OA\Property(property: 'data', type: 'object'),
|
||||
]
|
||||
)
|
||||
),
|
||||
new OA\Response(response: 401, description: 'Unauthorized'),
|
||||
new OA\Response(response: 422, description: 'Validation error or insufficient balance'),
|
||||
]
|
||||
)]
|
||||
#[Route('/api/v1/settlement', methods: ['POST'])]
|
||||
public function request(Request $request, #[CurrentUser] User $user): JsonResponse
|
||||
{
|
||||
@@ -80,6 +150,24 @@ class SettlementController extends BaseController
|
||||
return $this->success(['data' => $settlement->toArray()], 201);
|
||||
}
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/settlement',
|
||||
summary: 'List settlement requests for the authenticated user',
|
||||
security: [['bearerAuth' => []]],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 200,
|
||||
description: 'List of settlement requests',
|
||||
content: new OA\JsonContent(
|
||||
properties: [
|
||||
new OA\Property(property: 'success', type: 'boolean', example: true),
|
||||
new OA\Property(property: 'data', type: 'array', items: new OA\Items(type: 'object')),
|
||||
]
|
||||
)
|
||||
),
|
||||
new OA\Response(response: 401, description: 'Unauthorized'),
|
||||
]
|
||||
)]
|
||||
#[Route('/api/v1/settlement', methods: ['GET'])]
|
||||
public function listMine(#[CurrentUser] User $user): JsonResponse
|
||||
{
|
||||
@@ -91,6 +179,29 @@ class SettlementController extends BaseController
|
||||
return $this->success(['data' => $settlements]);
|
||||
}
|
||||
|
||||
#[OA\Get(
|
||||
path: '/api/v1/settlement/{uuid}',
|
||||
summary: 'Get a settlement request by UUID (own or admin)',
|
||||
security: [['bearerAuth' => []]],
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'uuid', in: 'path', required: true, schema: new OA\Schema(type: 'string')),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 200,
|
||||
description: 'Settlement request details',
|
||||
content: new OA\JsonContent(
|
||||
properties: [
|
||||
new OA\Property(property: 'success', type: 'boolean', example: true),
|
||||
new OA\Property(property: 'data', type: 'object'),
|
||||
]
|
||||
)
|
||||
),
|
||||
new OA\Response(response: 401, description: 'Unauthorized'),
|
||||
new OA\Response(response: 403, description: 'Forbidden'),
|
||||
new OA\Response(response: 404, description: 'Not found'),
|
||||
]
|
||||
)]
|
||||
#[Route('/api/v1/settlement/{uuid}', methods: ['GET'])]
|
||||
public function get(string $uuid, #[CurrentUser] User $user): JsonResponse
|
||||
{
|
||||
@@ -108,6 +219,38 @@ class SettlementController extends BaseController
|
||||
|
||||
// ── Admin Actions ─────────────────────────────────────────────────────────
|
||||
|
||||
#[OA\Post(
|
||||
path: '/api/v1/settlement/{uuid}/approve',
|
||||
summary: 'Approve a pending settlement request (ROLE_ADMIN)',
|
||||
security: [['bearerAuth' => []]],
|
||||
requestBody: new OA\RequestBody(
|
||||
required: false,
|
||||
content: new OA\JsonContent(
|
||||
properties: [
|
||||
new OA\Property(property: 'note', type: 'string', nullable: true),
|
||||
]
|
||||
)
|
||||
),
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'uuid', in: 'path', required: true, schema: new OA\Schema(type: 'string')),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 200,
|
||||
description: 'Settlement approved',
|
||||
content: new OA\JsonContent(
|
||||
properties: [
|
||||
new OA\Property(property: 'success', type: 'boolean', example: true),
|
||||
new OA\Property(property: 'data', type: 'object'),
|
||||
]
|
||||
)
|
||||
),
|
||||
new OA\Response(response: 401, description: 'Unauthorized'),
|
||||
new OA\Response(response: 403, description: 'Forbidden – ROLE_ADMIN required'),
|
||||
new OA\Response(response: 404, description: 'Not found'),
|
||||
new OA\Response(response: 422, description: 'Settlement is not in pending state'),
|
||||
]
|
||||
)]
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
#[Route('/api/v1/settlement/{uuid}/approve', methods: ['POST'])]
|
||||
public function approve(string $uuid, Request $request, #[CurrentUser] User $admin): JsonResponse
|
||||
@@ -128,6 +271,39 @@ class SettlementController extends BaseController
|
||||
return $this->success(['data' => $settlement->toArray()]);
|
||||
}
|
||||
|
||||
#[OA\Post(
|
||||
path: '/api/v1/settlement/{uuid}/reject',
|
||||
summary: 'Reject a pending settlement request (ROLE_ADMIN)',
|
||||
security: [['bearerAuth' => []]],
|
||||
requestBody: new OA\RequestBody(
|
||||
required: true,
|
||||
content: new OA\JsonContent(
|
||||
required: ['note'],
|
||||
properties: [
|
||||
new OA\Property(property: 'note', type: 'string', description: 'Rejection reason (required)'),
|
||||
]
|
||||
)
|
||||
),
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'uuid', in: 'path', required: true, schema: new OA\Schema(type: 'string')),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 200,
|
||||
description: 'Settlement rejected and amount refunded to wallet',
|
||||
content: new OA\JsonContent(
|
||||
properties: [
|
||||
new OA\Property(property: 'success', type: 'boolean', example: true),
|
||||
new OA\Property(property: 'data', type: 'object'),
|
||||
]
|
||||
)
|
||||
),
|
||||
new OA\Response(response: 401, description: 'Unauthorized'),
|
||||
new OA\Response(response: 403, description: 'Forbidden – ROLE_ADMIN required'),
|
||||
new OA\Response(response: 404, description: 'Not found'),
|
||||
new OA\Response(response: 422, description: 'Settlement is not pending or note is missing'),
|
||||
]
|
||||
)]
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
#[Route('/api/v1/settlement/{uuid}/reject', methods: ['POST'])]
|
||||
public function reject(string $uuid, Request $request, #[CurrentUser] User $admin): JsonResponse
|
||||
|
||||
Reference in New Issue
Block a user