# Project Guidelines for Junie

## Project Overview

Chill is a comprehensive web application built as a set of Symfony bundles. It is a case management system, for social work. The project consists of multiple specialized bundles that provide different functionalities:

- **ChillMainBundle**: Core bundles that provide the foundation of the application
- **ChillPersonBundle**: Core bundles that provide the foundation of the bundles associated to person (which is the case for all other bundles)
- **ChillCalendarBundle**: Calendar and scheduling functionality
- **ChillDocStoreBundle** and **ChillDocGeneratorBundle**: Document management and generation
- **ChillActivityBundle**, **ChillEventBundle**, **ChillTaskBundle**: Activity and task tracking
- **ChillBudgetBundle**: Financial management
- **ChillThirdPartyBundle**: Integration with external systems
- **ChillCustomFieldsBundle**: Extensibility through custom fields
- **ChillReportBundle**: Save arbitrary reports about persons
- **ChillTicketBundle**: Record and track issues about persons

- And several other specialized bundles

## Technology Stack

- **Backend**: PHP 8.3+, Symfony 5.4
- **Frontend**: JavaScript/TypeScript, Vue.js 3, Bootstrap 5
- **Build Tools**: Webpack Encore, Yarn
- **Database**: PostgreSQL with materialized views. We do not support other databases.
- **Other Services**: Redis, AMQP (RabbitMQ), SMTP

## Project Structure

Note: This is a project that's existed for a long time, and throughout the years we've used multiple structures inside each bundle. When having the choice, the developers should choose the new structure.

The project follows a standard Symfony bundle structure:
- `/src/Bundle/`: Contains all the Chill bundles. The code is either at the root of the bundle directory, or within a `src/` directory (preferred). See psr4 mapping at the root's `composer.json`.
- each bundle comes with its own tests, either in the `Tests` directory (when the code is directly within the bundle directory (for instance `src/Bundle/ChillMainBundle/Tests`, `src/Bundle/ChillPersonBundle/Tests`)), or inside the `tests` directory, alongside the `src/` sub-directory (example: `src/Bundle/ChillWopiBundle/tests`) (this is the preferred way).
- `/docs/`: Contains project documentation

Each bundle typically has the following structure:

- `Controller/`: Contains controllers
- `Entity/`: Contains Doctrine entities
- `Repository/`: Contains Doctrine repositories
- `Resources/`: Contains views, translations, and public assets
- `DependencyInjection/`: Contains service configuration
- `Export/`: Contains services related to exports
- `Security/`: Contains services related to security. Most of the time, those are new voters, and so on.

### A special word about TicketBundle

The ticket bundle is developed using a kind of "Command" pattern. The controller fills a "Command," and a "CommandHandler" handles this command. They are saved in the `src/Bundle/ChillTicketBundle/src/Action` directory.

## Development Guidelines

### Building and Configuration Instructions

All the commands should be run through the `symfony` command, which will configure the required variables.

For assets, we must ensure that we use node at version `^20.0.0`. This is done using `nvm use 20`.

#### Initial Setup

1. **Clone the Repository**:
   ```bash
   git clone <repository-url>
   cd chill-bundles
   ```

2. **Install PHP Dependencies**:
   ```bash
   composer install
   ```

3. **Install JavaScript Dependencies**:
   ```bash
   nvm use 20
   yarn install
   ```

4. **Configure Environment Variables**:

   - Create a `.env.local` file with minimal configuration
   ```bash
   echo "APP_ENV=dev" >> .env.local
   ```

5. Start the associated services (database, and so on):
   ```bash
   docker compose up -d
   ```

6. **Set Up the Database**:
   ```bash
   # Create the database
   symfony console doctrine:database:create

   # Run migrations
   symfony console doctrine:migrations:migrate

   # Load fixtures (optional)
   symfony console doctrine:fixtures:load
   ```

7. **Build Assets**:
   ```bash
   nvm use 20
   yarn run encore dev
   ```

8. **Start the Development Server**:
   ```bash
   symfony server:start -d
   ```

#### Docker Setup

The project includes a Docker configuration for easier development:

1. **Start Docker Services**:
   ```bash
   docker-compose up -d
   ```

2. **Access the Application**:
   - The application will be available at `http://localhost:8000`
   - PostgreSQL will be available at `localhost:5432`
   - Redis will be available at `localhost:6379`

#### Building Assets

Before submitting any changes, you should build the project to ensure that all assets are properly compiled:

```bash
# For production
yarn run encore production

# For development with hot-reloading
yarn run encore dev --watch

# for development
yarn run encore dev
```

#### Configuration Files

Key configuration files:

- `config/packages/*.yaml`: Symfony bundle configurations
- `webpack.config.js`: Webpack Encore configuration
- `composer.json`: PHP dependencies and scripts
- `package.json`: JavaScript dependencies and scripts
- `.env`: Default environment variables. Must usually not be updated: use `.env.local` instead.

### Database migrations

Each time a doctrine entity is created, we generate migration to adapt the database.

The migration is created using the command `symfony console doctrine:migrations:diff --no-interaction --namespace <namespace>`, where the namespace is the relevant namespace for migration. As this is a bash script, remember to quote the `\` (`\` must become `\\` in your command).

Each bundle has his own namespace for migration (always ask me to confirm that command with a list of updated / created entities so that I can confirm to you that it is ok):

- `Chill\Bundle\ActivityBundle` writes migrations to `Chill\Migrations\Activity`;
- `Chill\Bundle\BudgetBundle` writes migrations to `Chill\Migrations\Budget`;
- `Chill\Bundle\CustomFieldsBundle` writes migrations to `Chill\Migrations\CustomFields`;
- `Chill\Bundle\DocGeneratorBundle` writes migrations to `Chill\Migrations\DocGenerator`;
- `Chill\Bundle\DocStoreBundle` writes migrations to `Chill\Migrations\DocStore`;
- `Chill\Bundle\EventBundle` writes migrations to `Chill\Migrations\Event`;
- `Chill\Bundle\CalendarBundle` writes migrations to `Chill\Migrations\Calendar`;
- `Chill\Bundle\FamilyMembersBundle` writes migrations to `Chill\Migrations\FamilyMembers`;
- `Chill\Bundle\FranceTravailApiBundle` writes migrations to `Chill\Migrations\FranceTravailApi`;
- `Chill\Bundle\JobBundle` writes migrations to `Chill\Migrations\Job`;
- `Chill\Bundle\MainBundle` writes migrations to `Chill\Migrations\Main`;
- `Chill\Bundle\PersonBundle` writes migrations to `Chill\Migrations\Person`;
- `Chill\Bundle\ReportBundle` writes migrations to `Chill\Migrations\Report`;
- `Chill\Bundle\TaskBundle` writes migrations to `Chill\Migrations\Task`;
- `Chill\Bundle\ThirdPartyBundle` writes migrations to `Chill\Migrations\ThirdParty`;
- `Chill\Bundle\TicketBundle` writes migrations to `Chill\Migrations\Ticket`;
- `Chill\Bundle\WopiBundle` writes migrations to `Chill\Migrations\Wopi`;

Once created the, comment's classes should be removed and a description of the changes made to the entities should be added to the migrations, using the `getDescription` method. The migration should not be cleaned by any artificial intelligence, as modifying this migration is error prone.

### Guidelines related to code structure and requirements

#### Usage of clock

When we need to use a DateTime or DateTimeImmutable that need to express "now", we prefer the usage of
`Symfony\Component\Clock\ClockInterface`, where possible. This is usually not possible in doctrine entities,
where injection does not work when restoring an entity from a database, but usually possible in services.

In test, we use `\Symfony\Component\Clock\MockClock` which is an implementation of `Symfony\Component\Clock\ClockInterface`
where we have full and easy control of the date.

### Testing Information

The project uses PHPUnit for testing. Each bundle has its own test suite, and there's also a global test suite at the root level.

#### Use of mock in tests

##### General mocking

For creating mock, we prefer using prophecy (library phpspec/prophecy).

##### Useful helpers and tips that avoid creating a mock

Some notable implementations that are test helpers and avoid creating a mock:

- `\Psr\Log\NullLogger`, an implementation of `\Psr\Log\LoggerInterface`;
- `\Symfony\Component\Clock\MockClock`, an implementation of `Symfony\Component\Clock\ClockInterface` (already mentioned above);
- `\Symfony\Component\HttpClient\MockHttpClient`, an implementation of `\Symfony\Contracts\HttpClient\HttpClientInterface`;
- When using `\Symfony\Component\Mailer\MailerInterface`, we can create the mock with "InMemoryTransport":

    ```php
    use Symfony\Component\Mailer\Transport\InMemoryTransport;
    use \Symfony\Component\Mailer\Mailer;

    $transport = new InMemoryTransport();
    $mailer = new Mailer($transport);

    // After sending:
    $messages = $transport->getSent(); // array of SentMessage
    ```
- When using `\Symfony\Contracts\EventDispatcher\EventDispatcherInterface`, we can use directly an instance of `\Symfony\Component\EventDispatcher\EventDispatcher`;

##### When we prefer not creating a mock

- When we use Doctrine Entities related to the project, we prefer not to use a mock: we instantiate them directly (unless it requires too much code to write);

##### Mocking final and readonly classes

Classes marked as final can't be mocked. To avoid that, either:

- we remove the `final` keyword from the class;
- we extract an interface from the final class.

This must be a decision made by a human, not by an AI. Every AI task must abort with an explicit message in that case.

#### Running Tests

The tests are run from the project's root (not from the bundle's root).

```bash
# Run all tests
vendor/bin/phpunit

# Run a specific test file
vendor/bin/phpunit path/to/TestFile.php

# Run a specific test method
vendor/bin/phpunit --filter methodName path/to/TestFile.php
```

When writing tests, only test specific files. Do not run all tests or the full
test suite.

#### Test Structure

Tests are organized by bundle and follow the same structure as the bundle itself:

- Unit tests: Test individual components in isolation
- Integration tests: Test components working together
- Functional tests: Test the application from the user's perspective

#### Writing Tests

Tests should be placed in the appropriate bundle's test directory. For example, tests for the TicketBundle should be placed in `src/Bundle/ChillTicketBundle/tests/`.

Here's an example of a simple entity test:

```php
<?php

namespace Chill\TicketBundle\Tests\Entity;

use Chill\TicketBundle\Entity\Ticket;
use PHPUnit\Framework\TestCase;

class TicketTest extends TestCase
{
    public function testGetAndSetExternalRef(): void
    {
        $ticket = new Ticket();
        $externalRef = 'REF-123';

        // Set the external reference
        $ticket->setExternalRef($externalRef);

        // Verify that getExternalRef returns the correct value
        self::assertSame($externalRef, $ticket->getExternalRef());

        // Change the external reference
        $newExternalRef = 'REF-456';
        $ticket->setExternalRef($newExternalRef);

        // Verify that getExternalRef returns the updated value
        self::assertSame($newExternalRef, $ticket->getExternalRef());
    }
}
```

#### Test Database

For tests that require a database, the project uses a postgresql database filled with fixtures (usage of doctrine-fixtures). You can configure a different database for testing in the `.env.test` file.

### Code Quality Tools

The project uses several tools to maintain code quality:

#### PHP Code Style

The project uses PHP-CS-Fixer for code style. You can run it with:

```bash
# Using the composer script
composer php-cs-fixer

# Or directly
php-cs-fixer fix --config=./.php-cs-fixer.dist.php
```

#### Static Analysis

The project uses PHPStan for static analysis. You can run it with:

```bash
# Using the composer script
composer phpstan

# Or directly
vendor/bin/phpstan analyse
```

#### Automated Refactoring

The project uses Rector for automated refactoring. You can run it with:

```bash
# Using the composer script
composer rector

# Or directly
vendor/bin/rector
```

#### JavaScript/TypeScript Linting

The project uses ESLint for JavaScript/TypeScript code quality. You can run it with:

```bash
yarn run eslint
```

## Deployment

The project can be deployed in a production environment following Symfony's deployment guidelines. The documentation provides detailed instructions for setting up a production environment.

### Production Deployment Checklist

1. Set environment variables for production
2. Optimize Composer autoloader: `composer install --no-dev --optimize-autoloader`
3. Compile assets for production: `yarn run encore production`
4. Clear and warm up the cache: `php bin/console cache:clear --env=prod`
5. Run database migrations: `php bin/console doctrine:migrations:migrate --env=prod`

## Documentation

Comprehensive documentation is available in the `/docs/` directory, including installation instructions, configuration guides, and operational procedures.

## Development Workflow

1. **Create a Feature Branch**: Always create a new branch for your feature or bugfix
2. **Write Tests**: Write tests for your changes before implementing them
3. **Implement Changes**: Implement your changes following the project's coding standards
4. **Run Tests**: Make sure all tests pass
5. **Run Code Quality Tools**: Make sure your code passes all code quality checks
6. **Submit a Pull Request**: Submit a pull request for review

## Debugging

The project includes several tools for debugging:

- **Symfony Profiler**: Available in development mode at `/_profiler`
- **Xdebug**: Configure your IDE to use Xdebug for step-by-step debugging
- **Symfony Debug Toolbar**: Available at the bottom of the page in development mode

## Conclusion

When working with this project, Junie should:

1. Understand the modular bundle structure and how the different components interact
2. Build the project before submitting changes to ensure assets are properly compiled
3. Run relevant tests to ensure changes don't break existing functionality
4. Follow the established code style and patterns
5. Use the provided tools for debugging and code quality
