feature/core-service-api-structure #3

Merged
aep merged 17 commits from feature/core-service-api-structure into master 2025-08-27 15:11:10 +03:00
14 changed files with 1968 additions and 120 deletions
Showing only changes of commit 94bf3a6b86 - Show all commits

View File

@@ -235,12 +235,12 @@ type LoginRequest struct {
--- ---
## 🏗️ Этап 3: API структура (Неделя 3) ## 🏗️ Этап 3: API структура (Неделя 3) ✅ ЗАВЕРШЁН
### Шаг 3.1: Базовые handlers ### Шаг 3.1: Repository pattern ✅
- [ ] Создать `internal/api/handlers/` с базовыми структурами - [x] Создать `internal/repository/` для работы с БД
- [ ] Реализовать middleware для CORS, логирования, аутентификации - [x] Реализовать CRUD операции для всех сущностей
- [ ] Добавить обработку ошибок - [x] Добавить organization-scope фильтрацию
**Структура handlers:** **Структура handlers:**
``` ```
@@ -259,51 +259,58 @@ internal/api/
└── server.go └── server.go
``` ```
### Шаг 3.2: Repository pattern ### Шаг 3.2: Service layer ✅
- [ ] Создать `internal/repository/` для работы с БД - [x] Создать `internal/service/` с бизнес-логикой
- [ ] Реализовать CRUD операции для всех сущностей - [x] Реализовать сервисы для всех сущностей
- [ ] Добавить organization-scope фильтрацию - [x] Добавить валидацию и логирование
**Основные репозитории:** **Основные сервисы:**
```go ```go
// internal/repository/organizations.go // internal/service/location_service.go
type OrganizationRepository interface { type LocationService interface {
Create(ctx context.Context, org *models.Organization) error CreateLocation(ctx context.Context, orgID uuid.UUID, req *models.CreateLocationRequest) (*models.StorageLocation, error)
GetByID(ctx context.Context, id uuid.UUID) (*models.Organization, error) GetLocation(ctx context.Context, id uuid.UUID, orgID uuid.UUID) (*models.StorageLocation, error)
Update(ctx context.Context, org *models.Organization) error GetLocations(ctx context.Context, orgID uuid.UUID) ([]*models.StorageLocation, error)
UpdateLocation(ctx context.Context, id uuid.UUID, orgID uuid.UUID, req *models.CreateLocationRequest) (*models.StorageLocation, error)
DeleteLocation(ctx context.Context, id uuid.UUID, orgID uuid.UUID) error
} }
// internal/repository/users.go // internal/service/item_service.go
type UserRepository interface { type ItemService interface {
Create(ctx context.Context, user *models.User, password string) error CreateItem(ctx context.Context, orgID uuid.UUID, req *models.CreateItemRequest) (*models.Item, error)
GetByEmail(ctx context.Context, email string) (*models.User, error) GetItem(ctx context.Context, id uuid.UUID, orgID uuid.UUID) (*models.Item, error)
GetByID(ctx context.Context, id uuid.UUID) (*models.User, error) GetItems(ctx context.Context, orgID uuid.UUID) ([]*models.Item, error)
UpdateItem(ctx context.Context, id uuid.UUID, orgID uuid.UUID, req *models.CreateItemRequest) (*models.Item, error)
DeleteItem(ctx context.Context, id uuid.UUID, orgID uuid.UUID) error
SearchItems(ctx context.Context, orgID uuid.UUID, query string, category string) ([]*models.Item, error)
} }
// internal/repository/locations.go // internal/service/operations_service.go
type LocationRepository interface { type OperationsService interface {
Create(ctx context.Context, location *models.StorageLocation) error PlaceItem(ctx context.Context, orgID uuid.UUID, req *models.PlaceItemRequest) (*models.ItemPlacement, error)
GetByID(ctx context.Context, id uuid.UUID, orgID uuid.UUID) (*models.StorageLocation, error) MoveItem(ctx context.Context, placementID uuid.UUID, newLocationID uuid.UUID, orgID uuid.UUID) error
GetByOrganization(ctx context.Context, orgID uuid.UUID) ([]*models.StorageLocation, error) GetItemPlacements(ctx context.Context, itemID uuid.UUID, orgID uuid.UUID) ([]*models.ItemPlacement, error)
Update(ctx context.Context, location *models.StorageLocation) error GetLocationPlacements(ctx context.Context, locationID uuid.UUID, orgID uuid.UUID) ([]*models.ItemPlacement, error)
Delete(ctx context.Context, id uuid.UUID, orgID uuid.UUID) error Search(ctx context.Context, orgID uuid.UUID, req *models.SearchRequest) (*models.SearchResponse, error)
}
// internal/repository/items.go
type ItemRepository interface {
Create(ctx context.Context, item *models.Item) error
GetByID(ctx context.Context, id uuid.UUID, orgID uuid.UUID) (*models.Item, error)
GetByOrganization(ctx context.Context, orgID uuid.UUID) ([]*models.Item, error)
Search(ctx context.Context, orgID uuid.UUID, query string) ([]*models.Item, error)
Update(ctx context.Context, item *models.Item) error
Delete(ctx context.Context, id uuid.UUID, orgID uuid.UUID) error
} }
``` ```
### Шаг 3.3: Service layer ### Шаг 3.3: HTTP Handlers ✅
- [ ] Создать `internal/service/` для бизнес-логики - [x] Создать `internal/api/handlers/` с базовыми структурами
- [ ] Реализовать валидацию и обработку данных - [x] Реализовать handlers для всех API endpoints
- [ ] Добавить транзакции для сложных операций - [x] Добавить валидацию запросов
**Результаты этапа 3:**
- ✅ Созданы репозитории для locations, items, operations
- ✅ Реализованы сервисы с бизнес-логикой
- ✅ Созданы HTTP handlers для всех API endpoints
- ✅ Добавлена функция GetClaims в middleware
- ✅ Organization-scope фильтрация во всех операциях
- ✅ Поддержка JSON полей в PostgreSQL
- ✅ Валидация всех входящих запросов
```
--- ---