---
globs: back/**
alwaysApply: false
---

# Backend Development Workflow

## Architecture

This project uses the event driven broker architecture pattern with Firebase Functions. All business logic is organized into brokers that handle different types of requests and events. The data is saved in firestore and updated on the front end automatically through firestore hooks.

## Testing

You must always start from tests. We primarily use integration tests that test the user flow from start to finish. For example, for testing item management flow, you would test: creating item -> updating item -> archiving item -> deleting item -> etc. Inside each test case you must check the results in firestore. Test is considered passed, when all document properties are as expected.

**Important**: We check real documents in firestore after running each firebase function. The same with external services. Never create useless unit tests that just test properties of the class. Instead, test the actual functionality of the class.

Emulator is started automatically when executing `back/run_tests.py` file. Only run tests by running this file, otherwise, they will not work.

# Development Principles

All code must be clearly readable and maintainable. It must read like a story. Everything should be self-explanatory. You should not need tons of comments to understand what it does. The key idea is to make sure I can understand what the code does in 5 seconds. If I can't, you should refactor the code. Below is a list of principles that you must follow to achieve this:

- 🪟 **No broken windows**: Keep code clean from the start. Don't leave anything for later.
- 🔄 **DRY**: Don't repeat yourself. If you are about to write the same code twice, stop, reconsider your approach and refactor.
- 🌐 **Leave it better than you found it**: Improve bad code as you encounter it. Your code should clearly communicate its purpose.
- 🔁 **Write code once**: Don't repeat yourself. Make code modular and extract components when needed. Prefer types over obvious comments.
- 🧪 **Test First**: Do not start integrating any front-end features until they have been fully tested on the back end.
- 👨‍💻 **SOLID**: Follow SOLID principles. Write single purpose short self-contained functions.

## Development Rules

Below are the rules that you must follow when developing backend functionality:

- All firestore documents must be modified **strictly** within `DocumentBase` classes located in `src/documents/DocumentBase.py`. You must **never** modify documents outside of these classes.
- All third party APIs/clients must be wrapped in API wrapper classes located in `src/apis/`.
- Never make calls to firestore directly. Always use `Db` class located in `src/apis/Db.py`.
- All firestore document types should always be updated in `src/models/firestore_types.py`.
- If you are creating multiple documents from an event (like creating items from CSV file) - create a Factory class with a method `.from_csv(csv_path)` - this method should return an array of Document classes.
- Rules for new firestore and storage types must **always** be up to date in `firestore.rules` or `storage.rules`. Define them as soon as possible.
- All third party APIs must be wrapped in APIWrapperBase class located in `src/apis/APIWrapperBase.py`.
- All firestore function request and response types must be in `src/models/function_types.py`.
- Functions should be named as `{action}_{resource}_callable` or `on_{resource}_{event}`.
- All complex functionality that involves multiple documents, other APIBase classes, or complex logic should be wrapped in a Service class, located in `src/services/`.

## Workflow

When building new features, you must always start from creating new test files or modifying existing test files. Follow the workflow below:

0. Before starting, create a to-do list for yourself, following this exact process.
1. Navigate to the `tests` directory and find the most relevant test files that contain a similar user flow.
   - If you cannot find any relevant test files, ask clarification from the user.
   - If it's a new feature, create a new test file.
2. Incorporate new functionality into the test files. Make sure to check types from the `models` folder or add new types as necessary.
3. Build the new feature following our broker architecture and development principles.
4. Run the affected tests and check the results in terminal.
5. Keep iterating until all tests are passing. Do not stop until all tests are passing.
6. Export any new brokers from the `main.py` file for deployment.
7. Document any key architecture decisions (if any)in the `back/.cursor/rules/ADR.mdc` file.
8. Ensure firestore rules and storage rules are updated to reflect the new functionality in the `firestore.rules` and `storage.rules` files.

## Common Patterns

### Creating a Callable Function

```python
@https_fn.on_call(
    cors=options.CorsOptions(cors_origins=["*"]),
    ingress=options.IngressSetting.ALLOW_ALL,
)
def function_name(req: https_fn.CallableRequest):
    uid = db_auth_wrapper(req)
    # Implementation
```

### Creating a Document Class

```python
class MyDocument(ProjectDocumentBase[MyDocType]):
    pydantic_model = MyDocType

    def __init__(self, id: str, doc: Optional[dict] = None):
        self.collection_ref = self.db.collections["my_collection"]
        super().__init__(id, doc)
```

### Creating a Service

```python
class MyService:
    def __init__(self, doc: MyDocument):
        self.document = doc

    def complex_operation(self):
        # Orchestrate multiple documents
```

## Guardrails

- NEVER run any deploy commands.
