File size: 5,149 Bytes
4ae946d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# πŸ“˜ Developer Onboarding & Architecture Guide

Welcome to the **Zenith Fraud Detection** backend! This guide will help you understand our architecture, where to find things, and how to add new features correctly.

## πŸ—οΈ Architecture Overview

We use a **Domain-Driven Design (DDD)** approach with a clean separation between **Domain Services** (business logic) and **Infrastructure** (technical details).

### The Layered Model

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚             API Layer               β”‚
β”‚  (Routers, GraphQL Resolvers, etc.) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚          Domain Services            β”‚
β”‚  (Business Logic, Rules, Workflows) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚          Data Access Layer          β”‚
β”‚   (Repositories, Models, Schemas)   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

---

## πŸ—ΊοΈ Service Map

| Service | Located In | Responsibility |
|---------|------------|----------------|
| **CaseService** | `app/modules/cases` | Manage fraud cases, transitions, priority |
| **TransactionService** | `app/modules/transactions` | Manage financial transactions, validation |
| **UserService** | `app/modules/users` | User accounts, preferences, roles |
| **AnalyticsService** | `app/modules/analytics` | heavy aggregations, reports, stats |
| **EvidenceService** | `app/modules/evidence` | File uploads, processing, malware scan |
| **AuthService** | `app/modules/auth` | Login, JWT, password hashing |

### Infrastructure Services (Pure Technical)

Located in `app/services/infrastructure/*`:

- **DatabaseService**: Connection pooling, session management, health checks
- **CacheService**: Redis caching, invalidation
- **StorageService**: S3/Local file I/O abstraction
- **EmailService**: Sending transactional emails

---

## πŸš€ How to Add a New Feature

**Example: Adding a "Flag Transaction" feature**

### 1. Define the Data Access (Repository)

Modify `app/modules/transactions/repository.py`:

```python
def flag_transaction(self, transaction_id: str, reason: str) -> Transaction:
    txn = self.get_by_id(transaction_id)
    txn.is_flagged = True
    txn.flag_reason = reason
    self.session.add(txn)
    self.session.flush()
    return txn
```

### 2. Implement Business Logic (Service)

Modify `app/modules/transactions/service.py`:

```python
def flag_suspicious_transaction(self, db: Session, txn_id: str, reason: str, user: User) -> Transaction:
    # 1. Validate rules
    if not user.can_flag_transactions:
        raise PermissionError(...)
    
    # 2. Call repository
    repo = TransactionRepository(db)
    txn = repo.flag_transaction(txn_id, reason)
    
    # 3. Side effects (e.g. notify)
    self.notification_service.notify_manager(txn)
    
    return txn
```

### 3. Expose via API (Router)

Modify `app/modules/transactions/router.py`:

```python
@router.post("/{txn_id}/flag")
def flag_transaction_endpoint(
    txn_id: str, 
    reason: FlagRequest,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    service = TransactionService()
    return service.flag_suspicious_transaction(db, txn_id, reason.text, current_user)
```

---

## 🚫 Common Gotchas

### 1. `db_service` vs `db` Session

- **DON'T** put business logic in `DatabaseService`.
- **DO** use `DatabaseService` only to get a session: `db = db_service.get_db()`.
- **DO** pass the `Session` object to domain services.

### 2. Circular Imports

- **DO** import types only within `TYPE_CHECKING` blocks if needed.
- **DO** use dependency injection or pass dependencies in methods to avoid import loops.

### 3. Testing

- **DO** use `conftest.py` fixtures.
- **DO** mock external services (S3, Email) in unit tests.
- **DO** use real database (sqlite-memory) for integration tests.

---

## πŸ§ͺ Testing Guidelines

Run all tests:

```bash
pytest
```

Run specific module tests:

```bash
pytest tests/unit/modules/test_cases.py
```

### Test Structure

- `tests/unit/`: Fast tests, mocked dependencies.
- `tests/integration/`: Slower, real database interactions.
- `tests/performance/`: Benchmarks and load tests.

---

## πŸ†˜ Troubleshooting

**"AttributeError: 'DatabaseService' object has no attribute 'get_user'"**
You are trying to call a migrated method on the infrastructure service.
**Fix:** Use `UserService(db).get_user()` instead.

**"ImportError: cannot import name..."**
Likely a circular import.
**Fix:** Move the import inside the function/method or use `typing.TYPE_CHECKING`.

---

**Happy Coding!** πŸš€