Commit: 4617f76

Commit Details

SHA4617f76246bf039920879ae5497436d31494ed7c
Treee78bcb155880b8c167af124554a6db724c41264e
Author<f69e50@finnacloud.com> 1766442953 +0300
Committer<f69e50@finnacloud.com> 1766442953 +0300
Message
rename branch from main to master oops
GPG Signature
-----BEGIN PGP SIGNATURE-----

iQJSBAABCAA8FiEEWJb139mJI+vZ81KkoAIVSUsXI0oFAmlJx8keHHNvcGhpYS5l
cmFzbGFuQGZpbm5hY2xvdWQuY29tAAoJEKACFUlLFyNK2BQP/3EfkXtKsmQoqa4E
e9jdO5BKWUnHwF31PdpxExXwoogkZg2hSjSc0jB9htAKSbQspx+Pst7f9yj2Gf2u
ENGTEQHqqVeLEve2IPc1YJ+F+yedI3NE2PCZJ0+rh1/S14vQTT0kWMSqs6d8Te4K
x4hiTNNjfWidOXQ1vHMXl9iUnevmnko8XqNe3aBZ3JUSRLhhCvehsiPwSjfKGqB8
Sm9i1Y/HaTizFfl4WG5f6MppDgzV2I7Bm/c6K1oDIviO/Wken5vk4TXgLUWDfHJ5
d9m9gh4N9unX4Ivf5G22JVRzxPgox0Y0yFQwpj4IqQ9LzjT2Vz2s+hXoV6HZkfUW
BCLc/6oRmImcSflxOgV/TGaZrvysQ0pz32H8lyLoOI1QAS3o4u1icPFjfHlc5298
zpjGAqPjlVEx4Sjghrow4pb7sb/OyFihTwfjxlLgVfR4tXfb/l5rRt2f9vsm1HJB
qc9F/Qqc6xpb9ECyYZtuuCMToS0MRNkqy2KifrvOaKi2EznhcJu2VcLmjQJookFY
meevIkRenUvjwbs+aoDOa76HmycWkw1NtTtE9M+NSZ9SCBOD+Gp1rqO66z758bUQ
NmISh50GPDiZw5AKDrtsygWRZumLbrWHBleHm935V5O3gYkEKo9kb40Zf2sDsvlS
/wXQCTVz3XuSby3pyaMGgd3ol6gk
=YOD1
-----END PGP SIGNATURE-----

✓ Verified

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

1 package com.paymentlink.service;
2
3 import com.paymentlink.model.entity.PaymentLink;
4 import com.paymentlink.model.entity.PaymentLinkItem;
5 import com.paymentlink.model.entity.Product;
6 import com.paymentlink.repository.PaymentLinkRepository;
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 PaymentLinkService {
19
20 private static final Logger logger = LoggerFactory.getLogger(PaymentLinkService.class);
21
22 private final PaymentLinkRepository paymentLinkRepository;
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 PaymentLinkService(PaymentLinkRepository paymentLinkRepository,
30 ProductService productService,
31 TaxService taxService,
32 ShippingService shippingService,
33 ReservationService reservationService,
34 NodeIdService nodeIdService) {
35 this.paymentLinkRepository = paymentLinkRepository;
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 payment link
45 */
46 @Transactional
47 public PaymentLink createPaymentLink(List<PaymentLinkItem> items,
48 String customerEmail, String customerName, String customerPhone,
49 String shippingAddress, String shippingCity, String shippingState,
50 String shippingZip, String shippingCountry, String shippingMethod,
51 String sessionId) {
52
53 logger.info("Creating payment link for customer: {}", customerEmail);
54
55 // Validate stock and calculate totals
56 long subtotal = 0;
57 String currency = "USD";
58
59 for (PaymentLinkItem 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
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 payment link
99 PaymentLink paymentLink = PaymentLink.builder()
100 .linkId(IdGenerator.generatePaymentLinkId())
101 .status("pending")
102 .subtotal(subtotal)
103 .amount(total)
104 .shippingCost(shippingCost)
105 .taxAmount(taxAmount)
106 .currency(currency)
107 .customerEmail(customerEmail)
108 .customerName(customerName)
109 .customerPhone(customerPhone)
110 .shippingAddress(shippingAddress)
111 .shippingCity(shippingCity)
112 .shippingState(shippingState)
113 .shippingZip(shippingZip)
114 .shippingCountry(shippingCountry)
115 .shippingMethod(shippingMethod)
116 .nodeId(nodeIdService.getNodeId())
117 .build();
118
119 // Add items
120 for (PaymentLinkItem item : items) {
121 paymentLink.addItem(item);
122 }
123
124 // Save payment link
125 paymentLink = paymentLinkRepository.save(paymentLink);
126 logger.info("Created payment link: {}", paymentLink.getLinkId());
127
128 return paymentLink;
129 }
130
131 /**
132 * Get payment link by ID
133 */
134 public Optional<PaymentLink> getPaymentLinkById(String linkId) {
135 return paymentLinkRepository.findByLinkIdWithItems(linkId);
136 }
137
138 /**
139 * Update payment link status
140 */
141 @Transactional
142 public Optional<PaymentLink> updateStatus(String linkId, String status) {
143 return paymentLinkRepository.findByLinkId(linkId).map(link -> {
144 link.setStatus(status);
145 return paymentLinkRepository.save(link);
146 });
147 }
148
149 /**
150 * Associate payment link with Stripe payment intent
151 */
152 @Transactional
153 public Optional<PaymentLink> setStripePaymentIntent(String linkId, String paymentIntentId) {
154 return paymentLinkRepository.findByLinkId(linkId).map(link -> {
155 link.setStripePaymentIntentId(paymentIntentId);
156 return paymentLinkRepository.save(link);
157 });
158 }
159
160 /**
161 * Associate payment link with order
162 */
163 @Transactional
164 public Optional<PaymentLink> setOrderId(String linkId, String orderId) {
165 return paymentLinkRepository.findByLinkId(linkId).map(link -> {
166 link.setOrderId(orderId);
167 return paymentLinkRepository.save(link);
168 });
169 }
170
171 /**
172 * Complete payment link (mark as paid)
173 */
174 @Transactional
175 public void completePaymentLink(String linkId, String orderId) {
176 Optional<PaymentLink> linkOpt = paymentLinkRepository.findByLinkId(linkId);
177 if (linkOpt.isEmpty()) {
178 throw new IllegalArgumentException("Payment link not found: " + linkId);
179 }
180
181 PaymentLink link = linkOpt.get();
182 link.setStatus("paid");
183 link.setOrderId(orderId);
184 paymentLinkRepository.save(link);
185
186 logger.info("Completed payment link: {} -> order: {}", linkId, orderId);
187 }
188 }
189
190