280 lines
7.6 KiB
Markdown
280 lines
7.6 KiB
Markdown
# BankFlow
|
|
|
|
BankFlow is a Laravel API for creating and processing bank loan applications through configurable, type-specific workflows.
|
|
|
|
Each loan is assigned an immutable published workflow configuration when it is created. Administrators can create draft configurations, select and order supported stages, define stage-specific rules, and publish a new version for a loan type without changing loans already in progress.
|
|
|
|
## Project status
|
|
|
|
The repository is currently in the **blueprint and scaffolding phase**. The Laravel application skeleton and project documentation exist, but the BankFlow models, API routes, workflow engine, PostgreSQL schema, admin configuration endpoints, and Docker image have not yet been implemented.
|
|
|
|
The approved implementation plan is documented in [Project Blueprint](docs/project-blueprint.md).
|
|
|
|
## Documentation
|
|
|
|
| Document | Description |
|
|
| --- | --- |
|
|
| [Challenge requirements](docs/bank-flow.md) | Functional requirements, business rules, and deliverables |
|
|
| [API reference](docs/api-routes.md) | Public routes, request bodies, responses, and processing rules |
|
|
| [Project blueprint](docs/project-blueprint.md) | Architecture, models, database schema, workflow design, and test plan |
|
|
|
|
## Technology stack
|
|
|
|
- PHP 8.4
|
|
- Laravel 13
|
|
- PostgreSQL
|
|
- Eloquent ORM
|
|
- Pest 4
|
|
- Laravel Pint
|
|
- Docker
|
|
|
|
## Architecture
|
|
|
|
BankFlow uses a layered Laravel architecture with domain grouping and single-purpose Actions.
|
|
|
|
```text
|
|
HTTP Request
|
|
↓
|
|
Form Request
|
|
↓
|
|
Controller
|
|
↓
|
|
Action
|
|
↓
|
|
Workflow Engine / Eloquent
|
|
↓
|
|
PostgreSQL
|
|
```
|
|
|
|
Important architectural decisions:
|
|
|
|
- Controllers remain thin and contain no business rules.
|
|
- Application operations use dedicated Action classes instead of a generic service layer.
|
|
- Eloquent is used directly; no Repository layer is introduced.
|
|
- Workflow stages are stateless classes with one responsibility each.
|
|
- Loan processing is synchronous and runs inside one database transaction.
|
|
- Row locking and database uniqueness constraints prevent duplicate stage execution.
|
|
- Expected business outcomes are persisted as loan history; Laravel logs are reserved for unexpected operational errors.
|
|
- Queues, microservices, CQRS, Event Sourcing, and a generic Rule Engine are outside the project scope.
|
|
|
|
## Configurable workflows
|
|
|
|
Workflow configuration is stored in PostgreSQL and belongs to a specific `loan_type_id`.
|
|
|
|
```text
|
|
LoanType
|
|
└── WorkflowConfiguration
|
|
└── WorkflowConfigurationStep
|
|
└── StageDefinition
|
|
```
|
|
|
|
Configuration lifecycle:
|
|
|
|
1. An administrator creates a draft for a loan type.
|
|
2. Supported stages are selected and ordered.
|
|
3. Stage-specific rules are stored as validated JSON.
|
|
4. The complete workflow is validated.
|
|
5. Publishing archives the previous version and makes the new version immutable.
|
|
6. New loans use the new published version.
|
|
7. Existing loans continue using their originally assigned version.
|
|
|
|
The database stores stable stage codes, not executable PHP or SQL. A trusted application registry maps each code to its handler class.
|
|
|
|
## Domain model
|
|
|
|
Primary models:
|
|
|
|
- `LoanType`
|
|
- `StageDefinition`
|
|
- `WorkflowConfiguration`
|
|
- `WorkflowConfigurationStep`
|
|
- `Loan`
|
|
- `LoanHistory`
|
|
|
|
The domain keeps three concepts separate:
|
|
|
|
| Concept | Values |
|
|
| --- | --- |
|
|
| Loan status | `SUBMITTED`, `IN_PROGRESS`, `MANUAL_REVIEW`, `APPROVED`, `REJECTED` |
|
|
| Workflow stage | `VALIDATION`, `FRAUD_CHECK`, `GUARANTOR_CHECK`, `CREDIT_CHECK`, `MANAGER_APPROVAL` |
|
|
| Stage result | `PASS`, `FAIL`, `MANUAL_REVIEW` |
|
|
|
|
## Default workflows
|
|
|
|
### Personal loan
|
|
|
|
```text
|
|
VALIDATION
|
|
↓
|
|
FRAUD_CHECK
|
|
↓
|
|
CREDIT_CHECK
|
|
↓
|
|
MANAGER_APPROVAL (when applicable)
|
|
↓
|
|
APPROVED
|
|
```
|
|
|
|
### Business loan
|
|
|
|
```text
|
|
VALIDATION
|
|
↓
|
|
FRAUD_CHECK
|
|
↓
|
|
GUARANTOR_CHECK
|
|
↓
|
|
CREDIT_CHECK
|
|
↓
|
|
MANAGER_APPROVAL (when applicable)
|
|
↓
|
|
APPROVED
|
|
```
|
|
|
|
A `FAIL` result immediately rejects the loan. A `MANUAL_REVIEW` result stops automatic processing and moves the loan to manual review.
|
|
|
|
## Public API
|
|
|
|
| Method | Route | Description |
|
|
| --- | --- | --- |
|
|
| `POST` | `/api/v1/loans` | Create a loan application |
|
|
| `POST` | `/api/v1/loans/{loanId}/process` | Process all remaining workflow stages |
|
|
| `GET` | `/api/v1/loans/{loanId}` | Get a loan application |
|
|
| `GET` | `/api/v1/loans/{loanId}/history` | Get processing history |
|
|
| `GET` | `/health` | Check service health |
|
|
|
|
One call to the process route runs all remaining applicable stages until the loan becomes `APPROVED`, `REJECTED`, or `MANUAL_REVIEW`. Calling it again after a terminal status returns the current state without rerunning stages or adding history.
|
|
|
|
See [API Reference](docs/api-routes.md) for request and response examples.
|
|
|
|
## Prerequisites
|
|
|
|
For local development:
|
|
|
|
- PHP 8.4 with the PostgreSQL extension
|
|
- Composer
|
|
- PostgreSQL
|
|
- Node.js and npm for frontend asset compilation
|
|
|
|
Laravel Herd may be used for the local PHP runtime and site management.
|
|
|
|
## Local setup
|
|
|
|
Install dependencies and create the environment file:
|
|
|
|
```bash
|
|
composer install
|
|
cp .env.example .env
|
|
php artisan key:generate
|
|
npm install
|
|
```
|
|
|
|
Configure PostgreSQL in `.env`:
|
|
|
|
```dotenv
|
|
DB_CONNECTION=pgsql
|
|
DB_HOST=127.0.0.1
|
|
DB_PORT=5432
|
|
DB_DATABASE=bankflow
|
|
DB_USERNAME=postgres
|
|
DB_PASSWORD=
|
|
```
|
|
|
|
After the BankFlow migrations and seeders are implemented, initialize the database with:
|
|
|
|
```bash
|
|
php artisan migrate --seed
|
|
```
|
|
|
|
Build frontend assets when required:
|
|
|
|
```bash
|
|
npm run build
|
|
```
|
|
|
|
## Testing
|
|
|
|
Run the complete Pest suite:
|
|
|
|
```bash
|
|
php artisan test --compact
|
|
```
|
|
|
|
Run a focused test:
|
|
|
|
```bash
|
|
php artisan test --compact --filter=ProcessLoanTest
|
|
```
|
|
|
|
The planned suite covers:
|
|
|
|
- unit tests for every workflow stage;
|
|
- workflow order, stopping behavior, and rule validation;
|
|
- workflow configuration draft and publication behavior;
|
|
- public API feature tests;
|
|
- admin configuration authorization and validation;
|
|
- idempotent and concurrent processing;
|
|
- PostgreSQL persistence and history ordering.
|
|
|
|
## Code style
|
|
|
|
Format modified PHP files with:
|
|
|
|
```bash
|
|
vendor/bin/pint --dirty --format agent
|
|
```
|
|
|
|
## Docker
|
|
|
|
The completed project must support the challenge commands:
|
|
|
|
```bash
|
|
docker build -t bankflow .
|
|
docker run -p 8080:8080 bankflow
|
|
```
|
|
|
|
The service must become ready within 60 seconds and preserve loan data across an application process restart.
|
|
|
|
> **Current status:** the required `Dockerfile` has not been implemented yet, so these commands do not work in the current repository state.
|
|
|
|
## Planned project structure
|
|
|
|
```text
|
|
app/
|
|
├── Actions/
|
|
│ ├── Loan/
|
|
│ └── WorkflowConfiguration/
|
|
├── Domain/
|
|
│ └── Loan/
|
|
│ ├── Contracts/
|
|
│ ├── Data/
|
|
│ ├── Enums/
|
|
│ └── Workflow/
|
|
├── Http/
|
|
│ ├── Controllers/
|
|
│ ├── Requests/
|
|
│ └── Resources/
|
|
└── Models/
|
|
|
|
database/
|
|
├── factories/
|
|
├── migrations/
|
|
└── seeders/
|
|
|
|
tests/
|
|
├── Feature/
|
|
└── Unit/
|
|
```
|
|
|
|
The complete file and class layout is defined in [Project Blueprint](docs/project-blueprint.md#4-project-structure).
|
|
|
|
## Implementation principles
|
|
|
|
- Do not add behavior that is absent from the requirements or approved blueprint.
|
|
- Do not allow clients to select `workflow_configuration_id`; the server selects the published configuration for the requested loan type.
|
|
- Do not edit a published workflow configuration. Create and publish a new version.
|
|
- Do not store executable class names, PHP, SQL, or unrestricted expressions in admin-managed rules.
|
|
- Do not perform business validation in a way that bypasses workflow history.
|
|
- Do not process one stage per API call; one process request runs to a terminal automatic-processing status.
|
|
- Keep documentation synchronized with the implemented behavior.
|