File History: src/main/java/com/paymentlink/service/OrderService.java

← View file content

File Content at Commit 9c24ca4

1 package com.paymentlink.service;
2
3 import com.paymentlink.model.entity.Order;
4 import com.paymentlink.model.entity.OrderItem;
5 import com.paymentlink.model.entity.Product;
6 import com.paymentlink.repository.OrderRepository;
7 import com.paymentlink.reservation.ReservationService;
8 import com.paymentlink.util.IdGenerator;
9 import org.slf4j.Logger;
10 import org.slf4j.LoggerFactory;
11 import org.springframework.stereotype.Service;
12 import org.springframework.transaction.annotation.Transactional;
13
14 import java.util.List;
15 import java.util.Optional;
16
17 @Service
18 public class OrderService {
19
20 private static final Logger logger = LoggerFactory.getLogger(OrderService.class);
21
22 private final OrderRepository orderRepository;
23 private final ProductService productService;
24 private final TaxService taxService;
25 private final ShippingService shippingService;
26 private final ReservationService reservationService;
27 private final NodeIdService nodeIdService;
28
29 public OrderService(OrderRepository orderRepository,
30 ProductService productService,
31 TaxService taxService,
32 ShippingService shippingService,
33 ReservationService reservationService,
34 NodeIdService nodeIdService) {
35 this.orderRepository = orderRepository;
36 this.productService = productService;
37 this.taxService = taxService;
38 this.shippingService = shippingService;
39 this.reservationService = reservationService;
40 this.nodeIdService = nodeIdService;
41 }
42
43 /**
44 * Create a new order
45 */
46 @Transactional
47 public Order createOrder(List<OrderItem> items, String customerEmail, String customerName,
48 String customerPhone, String customerContactPreference,
49 String shippingAddress, String shippingCity, String shippingState,
50 String shippingZip, String shippingCountry, String shippingMethod,
51 String sessionId) {
52
53 logger.info("Creating order for customer: {}", customerEmail);
54
55 // Validate stock and calculate totals
56 long subtotal = 0;
57 String currency = "USD";
58
59 for (OrderItem item : items) {
60 Optional<Product> productOpt = productService.getProductByIdRaw(item.getProductId());
61 if (productOpt.isEmpty()) {
62 throw new IllegalArgumentException("Product not found: " + item.getProductId());
63 }
64
65 Product product = productOpt.get();
66 currency = product.getCurrency();
67
68 // Check stock availability (considering reservations)
69 if (product.getStock() != null) {
70 int reservedByOthers = reservationService.getReservedCountExcludingSession(
71 product.getId(), sessionId
72 );
73 int effectiveStock = product.getStock() - reservedByOthers;
74
75 if (effectiveStock < item.getQuantity()) {
76 throw new IllegalStateException(
77 String.format("Insufficient stock for %s. Only %d available.",
78 product.getName(), effectiveStock)
79 );
80 }
81 }
82
83 // Set item details
84 item.setProductName(product.getName());
85 item.setPrice(product.getPrice());
86 subtotal += product.getPrice() * item.getQuantity();
87 }
88
89 // Calculate shipping
90 long shippingCost = shippingService.calculateShippingCost(shippingMethod, shippingCountry);
91
92 // Calculate tax
93 long taxAmount = taxService.calculateTax(subtotal, shippingCountry, shippingState);
94
95 // Calculate total
96 long total = subtotal + shippingCost + taxAmount;
97
98 // Create order
99 Order order = Order.builder()
100 .orderId(IdGenerator.generateOrderId())
101 .status("pending")
102 .subtotal(subtotal)
103 .total(total)
104 .currency(currency)
105 .customerEmail(customerEmail)
106 .customerName(customerName)
107 .customerPhone(customerPhone)
108 .customerContactPreference(customerContactPreference)
109 .shippingAddress(shippingAddress)
110 .shippingCity(shippingCity)
111 .shippingState(shippingState)
112 .shippingZip(shippingZip)
113 .shippingCountry(shippingCountry)
114 .shippingMethod(shippingMethod)
115 .shippingCost(shippingCost)
116 .taxAmount(taxAmount)
117 .nodeId(nodeIdService.getNodeId())
118 .build();
119
120 // Add items
121 for (OrderItem item : items) {
122 order.addItem(item);
123 }
124
125 // Save order
126 order = orderRepository.save(order);
127 logger.info("Created order: {}", order.getOrderId());
128
129 return order;
130 }
131
132 /**
133 * Complete an order (update stock, release reservations)
134 */
135 @Transactional
136 public void completeOrder(String orderId, String sessionId) {
137 Optional<Order> orderOpt = orderRepository.findByOrderId(orderId);
138 if (orderOpt.isEmpty()) {
139 throw new IllegalArgumentException("Order not found: " + orderId);
140 }
141
142 Order order = orderOpt.get();
143
144 // Update stock for each item
145 for (OrderItem item : order.getItems()) {
146 productService.decreaseStock(item.getProductId(), item.getQuantity());
147
148 // Release reservation
149 if (sessionId != null) {
150 reservationService.release(sessionId, item.getProductId());
151 }
152 }
153
154 // Update order status
155 order.setStatus("completed");
156 orderRepository.save(order);
157
158 logger.info("Completed order: {}", orderId);
159 }
160
161 /**
162 * Get order by ID
163 */
164 public Optional<Order> getOrderById(String orderId) {
165 return orderRepository.findByOrderIdWithItems(orderId);
166 }
167
168 /**
169 * Get orders by customer email
170 */
171 public List<Order> getOrdersByCustomerEmail(String email) {
172 return orderRepository.findByCustomerEmail(email);
173 }
174
175 /**
176 * Get all orders (admin)
177 */
178 public List<Order> getAllOrders() {
179 return orderRepository.findAllWithItems();
180 }
181
182 /**
183 * Update order tracking information
184 */
185 @Transactional
186 public Optional<Order> updateTracking(String orderId, String trackingId, String carrier) {
187 return orderRepository.findByOrderId(orderId).map(order -> {
188 order.setTrackingId(trackingId);
189 order.setCarrier(carrier);
190 return orderRepository.save(order);
191 });
192 }
193
194 /**
195 * Verify email matches order
196 */
197 public boolean verifyOrderEmail(String orderId, String email) {
198 Optional<Order> order = orderRepository.findByOrderId(orderId);
199 return order.isPresent() && order.get().getCustomerEmail().equalsIgnoreCase(email);
200 }
201 }
202
203

Commits

Commit Author Date Message File SHA Actions
f0438c2 <f69e50@finnacloud.com> 1766443042 +0300 12/22/2025, 10:37:22 PM increment once more 89660e7 View
188fc92 <f69e50@finnacloud.com> 1766442998 +0300 12/22/2025, 10:36:38 PM increment 89660e7 View
4617f76 <f69e50@finnacloud.com> 1766442953 +0300 12/22/2025, 10:35:53 PM rename branch from main to master oops 89660e7 View
e6d1548 <f69e50@finnacloud.com> 1766442769 +0300 12/22/2025, 10:32:49 PM add initial test workflow file 89660e7 View
9c24ca4 <f69e50@finnacloud.com> 1766442705 +0300 12/22/2025, 10:31:45 PM add CI configuration and test script for Jenkins build 89660e7 Hide
690c1f6 <f69e50@finnacloud.com> 1766368110 +0300 12/22/2025, 1:48:30 AM initialize backend structure with controllers, DTOs, and configuration files 89660e7 View