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

← View file content

File Content at Commit 4617f76

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

Commits

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