Commit: e6d1548

Commit Details

SHAe6d1548c463d8763fb5547ff07a35c521f15c296
Tree2d2b62527861022ccf13eb205ea2bf7c0e4013fd
Author<f69e50@finnacloud.com> 1766442769 +0300
Committer<f69e50@finnacloud.com> 1766442769 +0300
Message
add initial test workflow file
GPG Signature
-----BEGIN PGP SIGNATURE-----

iQJSBAABCAA8FiEEWJb139mJI+vZ81KkoAIVSUsXI0oFAmlJxxEeHHNvcGhpYS5l
cmFzbGFuQGZpbm5hY2xvdWQuY29tAAoJEKACFUlLFyNKb7YP/2QctdaPuHu4+vFn
fh0Opgqt1brKy9JQxV9JZ9tF5XA+rWVi6pyIZK4lywX+a4er+h29sQY7TEHZt9Xn
meAyRUhPbRPmIpRJMMCgstfILUpjNMkMcPE80kJfpp6+ZmLtO8vC4TnW3ATCK1tv
XISV00T4ajCAhZUmYTveNsvSiMMv/Tq4sF9Is4ix+JN7O/lSLseRtuUE1Vv7T7nY
citxLPwR42Eb/1CYhy0JbRYXP816cbe6dGeDeiDZp7EHKx5D8VAqULKRsAL19tSX
hup8N7owBXieuzNQ4RyaDfDJAfNoN3o9pFeD6vQPq8s7x6AloN625g58p0ssxfK+
CGhR0YHR7atR0pEens22p7g2dVJ7NsrKqDBE3TTeUOpfXfjOwqpVh1Bn/v7a2Vg9
o9mhIClSOLfYv2SXJ06+fn8l6oc70nLJkBfcTevmeF//Z9yGH7TXZNUcedxuBbFg
xfEHeJibTamiE3Z1SfHW1YLwe7QqbBogCIxq4RrpYtN15a65vT5HxyLHDJDGG20V
7z34QJhKXIni/AIGscZqx2kE/C42KSD2fBvqvA4YnPwEUQyMvnSSDSKuJ6flXPTv
RsPZMdNsWWWyJ8P/NTo0Y/PPwA/28p9pX064H2lHFNvSEzUYJdKyQXNV3pGWYAvc
PR8Z+nHfbK/EF5jOVJ8+erXzzXUN
=COmA
-----END PGP SIGNATURE-----

✓ Verified

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

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