Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Задачи по бизнес-процессам в Java разработке
В своей практике я решал множество задач, связанных с автоматизацией и оптимизацией бизнес-процессов. Эта область требует глубокого понимания как технических аспектов, так и бизнес-логики.
1. Система управления заказами (E-commerce)
Задача: Разработать систему обработки заказов для онлайн-магазина с множественными этапами и состояниями.
Бизнес-процесс:
Новый заказ → Оплата → Подтверждение → Сборка → Отправка → Доставка → Завершение
Техническое решение:
@Entity
public class Order {
@Id
private Long id;
@Enumerated(EnumType.STRING)
private OrderStatus status;
private BigDecimal totalAmount;
private LocalDateTime createdAt;
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
private List<OrderItem> items = new ArrayList<>();
@OneToMany(mappedBy = "order")
private List<OrderStatusHistory> history = new ArrayList<>();
}
public enum OrderStatus {
PENDING, // Ожидание оплаты
PAID, // Оплачено
CONFIRMED, // Подтверждено
PREPARING, // Подготовка к отправке
SHIPPED, // Отправлено
DELIVERED, // Доставлено
CANCELLED // Отменено
}
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private PaymentService paymentService;
@Autowired
private InventoryService inventoryService;
@Autowired
private NotificationService notificationService;
@Transactional
public Order createOrder(CreateOrderRequest request) {
Order order = new Order();
order.setStatus(OrderStatus.PENDING);
order.setCreatedAt(LocalDateTime.now());
// Проверяем наличие товаров
for (OrderItemRequest item : request.getItems()) {
if (!inventoryService.hasStock(item.getProductId(), item.getQuantity())) {
throw new OutOfStockException(item.getProductId());
}
}
return orderRepository.save(order);
}
@Transactional
public void processPayment(Long orderId, PaymentDetails payment) {
Order order = orderRepository.findById(orderId)
.orElseThrow(() -> new OrderNotFoundException(orderId));
if (order.getStatus() != OrderStatus.PENDING) {
throw new InvalidOrderStatusException(order.getStatus());
}
// Обрабатываем платёж
PaymentResult result = paymentService.processPayment(order, payment);
if (result.isSuccessful()) {
order.setStatus(OrderStatus.PAID);
notificationService.sendPaymentConfirmation(order);
} else {
order.setStatus(OrderStatus.CANCELLED);
notificationService.sendPaymentFailed(order);
}
orderRepository.save(order);
}
@Transactional
public void confirmOrder(Long orderId) {
Order order = orderRepository.findById(orderId)
.orElseThrow();
if (order.getStatus() != OrderStatus.PAID) {
throw new InvalidStatusTransitionException();
}
// Зарезервировать товары
for (OrderItem item : order.getItems()) {
inventoryService.reserve(item.getProductId(), item.getQuantity());
}
order.setStatus(OrderStatus.CONFIRMED);
orderRepository.save(order);
notificationService.sendOrderConfirmed(order);
}
@Transactional
public void shipOrder(Long orderId) {
Order order = orderRepository.findById(orderId).orElseThrow();
if (order.getStatus() != OrderStatus.PREPARING) {
throw new InvalidStatusTransitionException();
}
// Обновляем инвентарь (списываем товары)
for (OrderItem item : order.getItems()) {
inventoryService.deduct(item.getProductId(), item.getQuantity());
}
order.setStatus(OrderStatus.SHIPPED);
orderRepository.save(order);
notificationService.sendOrderShipped(order);
}
}
2. Система утверждения документов (Workflow)
Задача: Реализовать многоуровневую систему утверждения документов с разными ролями.
Бизнес-процесс:
Создание → Проверка отделом → Проверка менеджером → Финальное одобрение → Активирование
Техническое решение:
public enum DocumentStatus {
DRAFT, // Черновик
DEPARTMENT_REVIEW, // На проверке у отдела
MANAGER_REVIEW, // На проверке у менеджера
FINAL_APPROVAL, // На финальном одобрении
APPROVED, // Одобрено
REJECTED // Отклонено
}
@Entity
public class Document {
@Id
private Long id;
@Enumerated(EnumType.STRING)
private DocumentStatus status;
@OneToMany(mappedBy = "document", cascade = CascadeType.ALL)
private List<ApprovalRecord> approvals = new ArrayList<>();
}
@Entity
public class ApprovalRecord {
@Id
private Long id;
@ManyToOne
private Document document;
@ManyToOne
private User approver;
@Enumerated(EnumType.STRING)
private ApprovalLevel level; // DEPARTMENT, MANAGER, FINAL
@Enumerated(EnumType.STRING)
private ApprovalDecision decision; // APPROVED, REJECTED, PENDING
private String comment;
private LocalDateTime approvedAt;
}
public enum ApprovalLevel {
DEPARTMENT,
MANAGER,
FINAL
}
public enum ApprovalDecision {
PENDING,
APPROVED,
REJECTED
}
@Service
public class WorkflowService {
@Autowired
private DocumentRepository documentRepository;
@Autowired
private ApprovalRecordRepository approvalRepository;
@Autowired
private NotificationService notificationService;
@Transactional
public void submitForApproval(Long documentId, ApprovalLevel nextLevel) {
Document doc = documentRepository.findById(documentId).orElseThrow();
// Обновляем статус документа
doc.setStatus(mapLevelToStatus(nextLevel));
// Создаём запись утверждения
ApprovalRecord approval = new ApprovalRecord();
approval.setDocument(doc);
approval.setLevel(nextLevel);
approval.setDecision(ApprovalDecision.PENDING);
documentRepository.save(doc);
approvalRepository.save(approval);
// Уведомляем ответственных
List<User> approvers = getUsersByApprovalLevel(nextLevel);
approvers.forEach(approver ->
notificationService.sendApprovalRequest(approver, doc, nextLevel)
);
}
@Transactional
public void approveDocument(Long documentId, Long approverId, String comment) {
ApprovalRecord record = approvalRepository
.findPendingByDocumentAndApprover(documentId, approverId)
.orElseThrow();
record.setDecision(ApprovalDecision.APPROVED);
record.setComment(comment);
record.setApprovedAt(LocalDateTime.now());
Document doc = record.getDocument();
// Проверяем, есть ли ещё уровни
ApprovalLevel nextLevel = getNextApprovalLevel(record.getLevel());
if (nextLevel != null) {
submitForApproval(doc.getId(), nextLevel);
} else {
// Все утверждения прошли успешно
doc.setStatus(DocumentStatus.APPROVED);
documentRepository.save(doc);
notificationService.sendDocumentApproved(doc);
}
}
@Transactional
public void rejectDocument(Long documentId, Long approverId, String reason) {
ApprovalRecord record = approvalRepository
.findPendingByDocumentAndApprover(documentId, approverId)
.orElseThrow();
Document doc = record.getDocument();
record.setDecision(ApprovalDecision.REJECTED);
record.setComment(reason);
record.setApprovedAt(LocalDateTime.now());
doc.setStatus(DocumentStatus.REJECTED);
documentRepository.save(doc);
notificationService.sendDocumentRejected(doc, reason);
}
}
3. Система управления складом (Inventory Management)
Задача: Автоматизация процесса управления товарным складом с отслеживанием движения.
Процесс:
Приход → Приёмка → Размещение → Продажа → Отправка → Списание
@Service
public class InventoryService {
@Autowired
private StockRepository stockRepository;
@Autowired
private MovementService movementService;
@Transactional
public void receiveGoods(ReceiptDetails receipt) {
for (ReceiptItem item : receipt.getItems()) {
Stock stock = stockRepository
.findByProductId(item.getProductId())
.orElseGet(() -> createNewStock(item.getProductId()));
int oldQuantity = stock.getQuantity();
stock.setQuantity(oldQuantity + item.getQuantity());
stock.setLastUpdated(LocalDateTime.now());
stockRepository.save(stock);
// Логируем движение
movementService.recordMovement(
item.getProductId(),
MovementType.RECEIPT,
item.getQuantity(),
receipt.getDocumentNumber()
);
}
}
@Transactional(isolation = Isolation.SERIALIZABLE)
public void deductForSale(Long productId, int quantity) {
Stock stock = stockRepository.findByProductId(productId)
.orElseThrow(() -> new ProductNotFoundException(productId));
if (stock.getQuantity() < quantity) {
throw new InsufficientStockException(productId, stock.getQuantity(), quantity);
}
stock.setQuantity(stock.getQuantity() - quantity);
stockRepository.save(stock);
movementService.recordMovement(
productId,
MovementType.SALE,
-quantity,
null
);
}
public boolean hasStock(Long productId, int requiredQuantity) {
return stockRepository.findByProductId(productId)
.map(stock -> stock.getQuantity() >= requiredQuantity)
.orElse(false);
}
}
4. Система управления HR процессами
Задача: Автоматизация найма, адаптации и управления сотрудниками.
Процесс:
Публикация → Резюме → Интервью → Предложение → Найм → Адаптация → Работа
5. Система биллинга и платежей
Задача: Управление счётами, платежами и финансовыми отчётами.
Техники:
- Асинхронная обработка платежей (Spring Task)
- Retry logic для неудачных платежей
- Reconciliation (сверка) с банковскими системами
- Аудит всех финансовых операций
Общие решения
1. State Machine для управления состояниями:
@Configuration
public class OrderStateMachineConfig extends EnumStateMachineConfigurerAdapter<OrderStatus, OrderEvent> {
@Override
public void configure(StateMachineStateConfigurer<OrderStatus, OrderEvent> states) {
states.withStates()
.initial(OrderStatus.PENDING)
.states(EnumSet.allOf(OrderStatus.class));
}
@Override
public void configure(StateMachineTransitionConfigurer<OrderStatus, OrderEvent> transitions) {
transitions
.withExternal().source(OrderStatus.PENDING).target(OrderStatus.PAID)
.event(OrderEvent.PAY).and()
.withExternal().source(OrderStatus.PAID).target(OrderStatus.CONFIRMED)
.event(OrderEvent.CONFIRM);
}
}
2. Event-driven архитектура:
@Component
public class OrderEventListener {
@EventListener
public void onOrderCreated(OrderCreatedEvent event) {
// Отправить письмо клиенту
}
@EventListener
public void onPaymentReceived(PaymentReceivedEvent event) {
// Зарезервировать товары
// Отправить уведомление
}
}
3. Async обработка:
@Service
public class OrderService {
@Async
public CompletableFuture<Void> processOrderAsync(Long orderId) {
// Тяжелая обработка
return CompletableFuture.completedFuture(null);
}
}
Выводы
Решение задач по бизнес-процессам требует:
- Глубокого понимания бизнес-логики
- Правильного выбора архитектуры (FSM, Event-driven, SAGA)
- Надёжной обработки ошибок и retry логики
- Тщательного логирования и аудита
- Управления состояниями и переходами между ними
- Интеграции с различными внешними системами
Это требует не только технических навыков, но и способности слушать бизнес и предлагать оптимальные решения.