# Реализация архитектуры ## Навигация - [🏠 Главная страница курса](../../../README.md) - [📚 Модуль 11](../README.md) --- ## Структура проекта ### 1. Monorepo Structure ``` ecommerce-platform/ ├── services/ │ ├── user-service/ │ │ ├── src/ │ │ ├── Dockerfile │ │ ├── pom.xml │ │ └── README.md │ ├── product-service/ │ ├── order-service/ │ ├── payment-service/ │ └── inventory-service/ ├── frontend/ │ ├── customer-app/ │ ├── admin-app/ │ └── shared/ ├── infrastructure/ │ ├── kubernetes/ │ ├── terraform/ │ └── docker-compose/ ├── docs/ │ ├── architecture/ │ ├── api/ │ └── deployment/ └── scripts/ ├── build.sh ├── deploy.sh └── test.sh ``` ### 2. Service Implementation ```java // Order Service Implementation @RestController @RequestMapping("/api/orders") @Validated public class OrderController { @Autowired private OrderService orderService; @PostMapping public ResponseEntity createOrder( @Valid @RequestBody CreateOrderRequest request) { Order order = orderService.createOrder(request); OrderResponse response = OrderMapper.toResponse(order); return ResponseEntity.status(HttpStatus.CREATED).body(response); } @GetMapping("/{id}") public ResponseEntity getOrder(@PathVariable Long id) { Order order = orderService.getOrder(id); OrderResponse response = OrderMapper.toResponse(order); return ResponseEntity.ok(response); } @PutMapping("/{id}/status") public ResponseEntity updateOrderStatus( @PathVariable Long id, @Valid @RequestBody UpdateOrderStatusRequest request) { Order order = orderService.updateOrderStatus(id, request.getStatus()); OrderResponse response = OrderMapper.toResponse(order); return ResponseEntity.ok(response); } } @Service @Transactional public class OrderService { @Autowired private OrderRepository orderRepository; @Autowired private OrderEventPublisher eventPublisher; @Autowired private InventoryServiceClient inventoryClient; @Autowired private PaymentServiceClient paymentClient; public Order createOrder(CreateOrderRequest request) { // Валидация заказа validateOrderRequest(request); // Создание заказа Order order = new Order(request); order = orderRepository.save(order); // Резервирование товаров inventoryClient.reserveItems(order.getId(), request.getItems()); // Публикация события eventPublisher.publishOrderCreated(order); return order; } public Order updateOrderStatus(Long orderId, OrderStatus status) { Order order = orderRepository.findById(orderId) .orElseThrow(() -> new OrderNotFoundException("Order not found: " + orderId)); order.updateStatus(status); order = orderRepository.save(order); // Публикация события eventPublisher.publishOrderStatusUpdated(order); return order; } private void validateOrderRequest(CreateOrderRequest request) { if (request.getItems().isEmpty()) { throw new ValidationException("Order must contain at least one item"); } // Дополнительные проверки... } } ``` ## Проектирование API ### 1. REST API Specification ```yaml # OpenAPI Specification openapi: 3.0.0 info: title: E-commerce Platform API version: 1.0.0 description: API for e-commerce platform servers: - url: https://api.ecommerce.com/v1 description: Production server paths: /orders: post: summary: Create a new order requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateOrderRequest' responses: '201': description: Order created successfully content: application/json: schema: $ref: '#/components/schemas/OrderResponse' '400': description: Bad request content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /orders/{id}: get: summary: Get order by ID parameters: - name: id in: path required: true schema: type: integer responses: '200': description: Order retrieved successfully content: application/json: schema: $ref: '#/components/schemas/OrderResponse' '404': description: Order not found components: schemas: CreateOrderRequest: type: object required: - customerId - items properties: customerId: type: integer format: int64 items: type: array items: $ref: '#/components/schemas/OrderItem' shippingAddress: $ref: '#/components/schemas/Address' paymentMethod: $ref: '#/components/schemas/PaymentMethod' OrderResponse: type: object properties: id: type: integer format: int64 customerId: type: integer format: int64 status: type: string enum: [PENDING, CONFIRMED, SHIPPED, DELIVERED, CANCELLED] totalAmount: type: number format: decimal items: type: array items: $ref: '#/components/schemas/OrderItem' createdAt: type: string format: date-time updatedAt: type: string format: date-time ``` ### 2. Event Schema ```json { "orderCreated": { "eventType": "OrderCreated", "version": "1.0", "timestamp": "2023-12-01T10:00:00Z", "data": { "orderId": "12345", "customerId": "67890", "items": [ { "productId": "prod-001", "quantity": 2, "price": 29.99 } ], "totalAmount": 59.98, "status": "PENDING" } }, "orderStatusUpdated": { "eventType": "OrderStatusUpdated", "version": "1.0", "timestamp": "2023-12-01T10:05:00Z", "data": { "orderId": "12345", "oldStatus": "PENDING", "newStatus": "CONFIRMED", "updatedBy": "system" } } } ``` ## Проектирование базы данных ### 1. Database Schema ```sql -- Order Service Database Schema CREATE TABLE orders ( id BIGSERIAL PRIMARY KEY, customer_id BIGINT NOT NULL, status VARCHAR(20) NOT NULL DEFAULT 'PENDING', total_amount DECIMAL(10,2) NOT NULL, shipping_address JSONB, payment_method JSONB, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE order_items ( id BIGSERIAL PRIMARY KEY, order_id BIGINT NOT NULL REFERENCES orders(id), product_id VARCHAR(50) NOT NULL, quantity INTEGER NOT NULL, unit_price DECIMAL(10,2) NOT NULL, total_price DECIMAL(10,2) NOT NULL ); CREATE TABLE order_events ( id BIGSERIAL PRIMARY KEY, order_id BIGINT NOT NULL, event_type VARCHAR(50) NOT NULL, event_data JSONB NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Индексы для оптимизации CREATE INDEX idx_orders_customer_id ON orders(customer_id); CREATE INDEX idx_orders_status ON orders(status); CREATE INDEX idx_orders_created_at ON orders(created_at); CREATE INDEX idx_order_items_order_id ON order_items(order_id); CREATE INDEX idx_order_events_order_id ON order_events(order_id); ``` ### 2. Data Access Layer ```java @Repository public interface OrderRepository extends JpaRepository { List findByCustomerId(Long customerId); List findByStatus(OrderStatus status); @Query("SELECT o FROM Order o WHERE o.createdAt BETWEEN :startDate AND :endDate") List findOrdersByDateRange( @Param("startDate") LocalDateTime startDate, @Param("endDate") LocalDateTime endDate ); @Query("SELECT o FROM Order o WHERE o.customerId = :customerId AND o.status = :status") List findByCustomerIdAndStatus( @Param("customerId") Long customerId, @Param("status") OrderStatus status ); } @Repository public class OrderEventRepository { @Autowired private JdbcTemplate jdbcTemplate; public void saveEvent(OrderEvent event) { String sql = "INSERT INTO order_events (order_id, event_type, event_data) VALUES (?, ?, ?)"; jdbcTemplate.update(sql, event.getOrderId(), event.getEventType(), event.getEventData() ); } public List findEventsByOrderId(Long orderId) { String sql = "SELECT * FROM order_events WHERE order_id = ? ORDER BY created_at"; return jdbcTemplate.query(sql, new OrderEventRowMapper(), orderId); } } ```