# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Commands

```bash
# Inside the Docker container (working dir /var/www/html)
composer install
./vendor/bin/phpunit                 # all tests
./vendor/bin/phpunit tests/Functional
php bin/console [command]

# From the host (Makefile)
make start                           # start the service via ../docker-env
make bash                            # shell into the container
make test                            # ./vendor/bin/phpunit
make db-migrate                      # doctrine:migrations:migrate
```

The service runs under the `../docker-env` compose project as `bpc-acquiring-integration-service`. Database: PostgreSQL host `db`, schema `bpc`, dev database `bpc_acquiring` / test database `bpc_acquiring_test`.

## Architecture

A **PHP 8.1 / Symfony 5.4** integration service that exposes a card credit (OCT / Original Credit Transfer) endpoint and forwards it to BPC's REST P2P API, and a communication-log listing endpoint. It is built on the internal `payneticsteam/paynetics-bundle` (`AbstractApiController`, `ValidationTrait`, `SerializationTrait`, `ErrorNormalizer`, `ExceptionCodes`).

### Request flow

```
HTTP Request
  → Controller (src/Controller/)        — deserialize + validate the DTO, orchestrate, return JsonResponse
  → BPCRequestManager (src/RequestManager/) — sets up credentials, issues the BPC P2P calls
  → BpcRestClient (src/BPC/)            — Symfony HttpClient calls to BPC, logs each exchange
  → Builder (src/Builder/)              — build outbound BPC payloads and the API response
```

### Endpoints

- `POST /v1/oct` — `OctController::credit`. Deserializes `EcommercePaymentDto`, validates, then calls BPC `registerP2P.do` → `performP2P.do` → `getP2PStatus.do`, and builds the payment response. No authentication.
- `GET /v1/logs/list` — `LogsController::listLogs`. Filters/paginates `CommunicationLog` rows (`orderId`, `stan`, `fromDate`, `toDate`, `order`, `fromId`, `limit`, `direction`). No authentication.

### Key layers

- **Controllers** (`src/Controller/`) — `OctController`, `LogsController`. Thin: deserialize, validate, delegate, respond.
- **RequestManager** (`src/RequestManager/`) — `BPCRequestManager` orchestrates the BPC P2P calls and maps raw responses into `src/Dto/Response/` objects.
- **BPC** (`src/BPC/`) — `BpcRestClient` (the Symfony HttpClient wrapper, persists a `CommunicationLog` per call) and `BpcRestClientFactory` (builds the client with the configured base URL + credentials).
- **Builders** (`src/Builder/`) — `OrderBuilder`, `CreditBuilder`, `ResponseBuilder`, `LogBuilder` transform DTOs to BPC payloads and to the API response.
- **DTOs** (`src/Dto/`) — request DTOs (`EcommercePaymentDto`, `ConfigurationDto`, `Logs/*`) and response DTOs (`P2P*Response`, `ResponseDto`). Symfony Serializer (snake_case) deserializes requests.
- **Entity / Repository** — `CommunicationLog` + `CommunicationLogRepository::filtered()` back the logs endpoint.

### BPC transformations

amount → minor units (`100.0` → `10000`); currency → ISO numeric int (`EUR` → `978`); card acceptor country → alpha-3 (`BG` → `BGR`); single-digit `resultCode` left-padded to 2 chars; card acceptor `winbet` → payer name `winbet EOOD`. A non-zero BPC error code or HTTP error throws inside `BpcRestClient` and maps to the general error code.

## Testing

Tests require no `src` changes. Functional tests live in `tests/Functional/` and extend `BaseWebTestCase`; the OCT tests replace the `BPCRequestManager` service with a stub (made public in the `test` env via `when@test` in `config/services.yaml`) since `BpcRestClient` has no HTTP-client seam. Unit tests live in `tests/Unit/` (`Builder/`, `BPC/`, `RequestManager/`) and extend `PHPUnit\Framework\TestCase`, injecting a `MockHttpClient` via reflection where needed. Shared fixtures: `tests/Helper/Constants/`, `tests/Helper/Factory/`, `tests/Helper/Responses/`. `dama/doctrine-test-bundle` rolls back the DB after each test. See `tests/CLAUDE.md` for the full testing guide.
