Skip to content

Commit c04f69d

Browse files
author
bitscoder
committed
tested the code for all round functionalities
1 parent 21c0999 commit c04f69d

File tree

11 files changed

+348
-47
lines changed

11 files changed

+348
-47
lines changed

Readme.md

Whitespace-only changes.
Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
package com.bitscoderdotcom.link_generator_system.controller;
22

3+
import com.bitscoderdotcom.link_generator_system.exception.ResourceNotFoundException;
34
import com.bitscoderdotcom.link_generator_system.service.service.InvoiceService;
45
import lombok.AllArgsConstructor;
6+
import org.springframework.http.HttpStatus;
7+
import org.springframework.http.ResponseEntity;
58
import org.springframework.stereotype.Controller;
69
import org.springframework.ui.Model;
710
import org.springframework.web.bind.annotation.PathVariable;
811
import org.springframework.web.bind.annotation.PostMapping;
912
import org.springframework.web.bind.annotation.RequestParam;
13+
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
1014

1115
@Controller
1216
@AllArgsConstructor
@@ -15,11 +19,20 @@ public class PaymentController {
1519
private final InvoiceService invoiceService;
1620

1721
@PostMapping("/payment")
18-
public String processPayment(@RequestParam String linkId, @RequestParam String invoiceId, Model model) {
19-
String message = invoiceService.processPayment(linkId, invoiceId);
22+
public String processPayment(@RequestParam String linkId, @RequestParam String invoiceId, RedirectAttributes redirectAttributes) {
23+
try {
24+
ResponseEntity<String> responseEntity = invoiceService.processPayment(linkId, invoiceId);
25+
String message = responseEntity.getBody();
2026

21-
model.addAttribute("message", message);
22-
23-
return "paymentSuccess";
27+
if (responseEntity.getStatusCode() == HttpStatus.OK) {
28+
redirectAttributes.addFlashAttribute("message", message);
29+
return "/paymentSuccess";
30+
} else {
31+
redirectAttributes.addAttribute("error", message);
32+
return "/error";
33+
}
34+
} catch (Exception ex) {
35+
throw new RuntimeException("An error occurred while processing the payment.");
36+
}
2437
}
2538
}

src/main/java/com/bitscoderdotcom/link_generator_system/dto/InvoiceDto.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.bitscoderdotcom.link_generator_system.constant.Status;
44
import lombok.*;
55

6+
import java.time.LocalDate;
67
import java.util.Date;
78

89
@Setter
@@ -17,8 +18,8 @@ public class InvoiceDto {
1718
private long quantity;
1819
private double unitPrice;
1920
private double totalAmount;
20-
private Date invoiceGenerationDate;
21-
private Date paymentDueDate;
21+
private LocalDate invoiceGenerationDate;
22+
private LocalDate paymentDueDate;
2223
private Status status;
2324

2425
@Data
@@ -32,8 +33,8 @@ public static class Response {
3233
private long quantity;
3334
private double unitPrice;
3435
private double totalAmount;
35-
private Date invoiceGenerationDate;
36-
private Date paymentDueDate;
36+
private LocalDate invoiceGenerationDate;
37+
private LocalDate paymentDueDate;
3738
private Status status;
3839
}
3940
}

src/main/java/com/bitscoderdotcom/link_generator_system/entities/Invoice.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import lombok.Getter;
77
import lombok.Setter;
88

9+
import java.time.LocalDate;
910
import java.util.Date;
1011
import java.util.UUID;
1112

@@ -27,8 +28,8 @@ public class Invoice {
2728
private long quantity;
2829
private double unitPrice;
2930
private double totalAmount;
30-
private Date invoiceGenerationDate;
31-
private Date paymentDueDate;
31+
private LocalDate invoiceGenerationDate;
32+
private LocalDate paymentDueDate;
3233
@Enumerated(EnumType.STRING)
3334
private Status status;
3435
@OneToOne(mappedBy = "invoice", cascade = CascadeType.ALL)

src/main/java/com/bitscoderdotcom/link_generator_system/security/WebSecurityConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
8585
.authorizeHttpRequests()
8686
.requestMatchers("/lgsApp/v1/auth/**").permitAll()
8787
.requestMatchers("/h2-console/**").permitAll()
88-
.requestMatchers("/lgsApp/v1/invoice/{invoiceId}/payment", "/payment").permitAll()
88+
.requestMatchers("/lgsApp/v1/invoice/{invoiceId}/payment", "/payment", "/paymentSuccess", "/error" ).permitAll()
8989
.anyRequest().authenticated()
9090
.and()
9191
.formLogin();

src/main/java/com/bitscoderdotcom/link_generator_system/service/EmailService.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
import lombok.extern.slf4j.Slf4j;
77
import org.springframework.beans.factory.annotation.Autowired;
88
import org.springframework.beans.factory.annotation.Value;
9-
import org.springframework.mail.MailException;
10-
import org.springframework.mail.SimpleMailMessage;
119
import org.springframework.mail.javamail.JavaMailSender;
1210
import org.springframework.mail.javamail.MimeMessageHelper;
1311
import org.springframework.stereotype.Service;

src/main/java/com/bitscoderdotcom/link_generator_system/service/service/InvoiceService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@
1010
public interface InvoiceService {
1111

1212
ResponseEntity<ApiResponse<InvoiceDto.Response>> generateInvoice(InvoiceDto invoiceDto, Principal principal);
13-
String processPayment(String linkId, String invoiceId);
13+
ResponseEntity<String> processPayment(String linkId, String invoiceId);
1414
Invoice getInvoiceById(String id);
1515
}

src/main/java/com/bitscoderdotcom/link_generator_system/service/service/serviceImpl/InvoiceServiceImpl.java

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import com.bitscoderdotcom.link_generator_system.service.service.InvoiceService;
1616
import lombok.AllArgsConstructor;
1717
import lombok.extern.slf4j.Slf4j;
18+
import org.springframework.http.HttpStatus;
1819
import org.springframework.http.ResponseEntity;
1920
import org.springframework.stereotype.Service;
2021
import org.springframework.transaction.annotation.Transactional;
@@ -45,17 +46,7 @@ public ResponseEntity<ApiResponse<InvoiceDto.Response>> generateInvoice(InvoiceD
4546
.orElseThrow(() -> new ResourceNotFoundException("Company", "User email", principal.getName()));
4647

4748
// Create a new invoice
48-
Invoice invoice = new Invoice();
49-
invoice.setCompany(company);
50-
invoice.setCustomerName(invoiceDto.getCustomerName());
51-
invoice.setCustomerEmail(invoiceDto.getCustomerEmail());
52-
invoice.setDescription(invoiceDto.getDescription());
53-
invoice.setQuantity(invoiceDto.getQuantity());
54-
invoice.setUnitPrice(invoiceDto.getUnitPrice());
55-
invoice.setTotalAmount(invoiceDto.getTotalAmount());
56-
invoice.setInvoiceGenerationDate(invoiceDto.getInvoiceGenerationDate());
57-
invoice.setPaymentDueDate(invoiceDto.getPaymentDueDate());
58-
invoice.setStatus(Status.Unpaid);
49+
Invoice invoice = createInvoice(invoiceDto, company);
5950

6051
invoiceRepository.save(invoice);
6152

@@ -66,11 +57,13 @@ public ResponseEntity<ApiResponse<InvoiceDto.Response>> generateInvoice(InvoiceD
6657
paymentLink.setUrl(baseUrl + generateUniqueUrl(invoice.getId()));
6758
paymentLinkRepository.save(paymentLink);
6859

60+
String messageBody = createMessageBody(invoice, paymentLink);
61+
6962
// Send the payment link to the customer via email
7063
EmailDetails emailDetails = new EmailDetails();
7164
emailDetails.setRecipient(invoice.getCustomerEmail());
7265
emailDetails.setSubject("Invoice Payment Link");
73-
emailDetails.setMessageBody("Please click the following link to view and pay your invoice: <a href=\"" + paymentLink.getUrl() + "\">" + paymentLink.getUrl() + "</a>");
66+
emailDetails.setMessageBody(messageBody);
7467
emailService.sendEmail(emailDetails);
7568

7669
log.info("Invoice generated successfully for company with id: {}", company.getId());
@@ -95,7 +88,7 @@ public Invoice getInvoiceById(String id) {
9588
}
9689

9790
@Transactional
98-
public String processPayment(String linkId, String invoiceId) {
91+
public ResponseEntity<String> processPayment(String linkId, String invoiceId) {
9992
// Find the payment link by linkId
10093
PaymentLink paymentLink = paymentLinkRepository.findById(linkId)
10194
.orElseThrow(() -> new ResourceNotFoundException("PaymentLink", "id", linkId));
@@ -108,7 +101,7 @@ public String processPayment(String linkId, String invoiceId) {
108101

109102
// Check if the invoice has already been paid
110103
if (invoice.getStatus() == Status.Paid) {
111-
return "This invoice has already been paid for.";
104+
return new ResponseEntity<>("This invoice has already been paid for.", HttpStatus.BAD_REQUEST);
112105
}
113106

114107
// If the invoice has not been paid, process the payment
@@ -120,11 +113,48 @@ public String processPayment(String linkId, String invoiceId) {
120113
// Send a success email to the customer with the receipt
121114
EmailDetails emailDetails = new EmailDetails();
122115
emailDetails.setRecipient(invoice.getCustomerEmail());
123-
emailDetails.setSubject("Payment Successful, please check your email for details. Thank you and please come again.");
116+
emailDetails.setSubject("Payment Successful");
124117
emailDetails.setMessageBody(receipt);
125118
emailService.sendEmail(emailDetails);
126119

127-
return "Payment for invoice " + invoice.getId() + " was successful.";
120+
return new ResponseEntity<>("Payment for invoice " + invoice.getId() + " was successful.", HttpStatus.OK);
121+
}
122+
123+
private Invoice createInvoice(InvoiceDto invoiceDto, Company company) {
124+
Invoice invoice = new Invoice();
125+
invoice.setCompany(company);
126+
invoice.setCustomerName(invoiceDto.getCustomerName());
127+
invoice.setCustomerEmail(invoiceDto.getCustomerEmail());
128+
invoice.setDescription(invoiceDto.getDescription());
129+
invoice.setQuantity(invoiceDto.getQuantity());
130+
invoice.setUnitPrice(invoiceDto.getUnitPrice());
131+
invoice.setTotalAmount(invoiceDto.getTotalAmount());
132+
invoice.setInvoiceGenerationDate(LocalDate.now());
133+
invoice.setPaymentDueDate(LocalDate.now().plusDays(1));
134+
invoice.setStatus(Status.Unpaid);
135+
136+
return invoiceRepository.save(invoice);
137+
}
138+
139+
private String createMessageBody(Invoice invoice, PaymentLink paymentLink) {
140+
String messageBody = "<html><body>";
141+
messageBody += "<p>Dear " + invoice.getCustomerName() + ",</p>";
142+
messageBody += "<p>An invoice has been generated for you. Here are the details:</p>";
143+
messageBody += "<hr />";
144+
messageBody += "<p>Description: " + invoice.getDescription() + "</p>";
145+
messageBody += "<p>Quantity: " + invoice.getQuantity() + "</p>";
146+
messageBody += "<p>Unit Price: $" + invoice.getUnitPrice() + "</p>";
147+
messageBody += "<hr />";
148+
messageBody += "<p>Total Amount: $" + invoice.getTotalAmount() + "</p>";
149+
messageBody += "<hr />";
150+
messageBody += "<p>Invoice Date: " + invoice.getInvoiceGenerationDate() + "</p>";
151+
messageBody += "<p>Payment Due Date: " + invoice.getPaymentDueDate() + "</p>";
152+
messageBody += "<hr />";
153+
messageBody += "<p>Please click the following link to view and pay your invoice: <a href=\"" +
154+
paymentLink.getUrl() + "\">" + paymentLink.getUrl() + "</a></p>";
155+
messageBody += "<p>Thank you.</p>";
156+
messageBody += "</body></html>";
157+
return messageBody;
128158
}
129159

130160
private String generateUniqueUrl(String invoiceId) {
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>Error</title>
5+
<style>
6+
body {
7+
font-family: Arial, sans-serif;
8+
background-color: #f0f0f0;
9+
color: #333;
10+
margin: 70px;
11+
display: flex;
12+
justify-content: center;
13+
align-items: center;
14+
text-align: center;
15+
}
16+
h1 {
17+
color: #333;
18+
}
19+
p {
20+
color: #666;
21+
}
22+
</style>
23+
</head>
24+
<body>
25+
<div>
26+
<h1>Error</h1>
27+
<p id="errorMessage"></p>
28+
<a href="/">Go Back</a>
29+
</div>
30+
<script>
31+
// Get the error message from the URL query string
32+
var urlParams = new URLSearchParams(window.location.search);
33+
var errorMessage = urlParams.get('error');
34+
35+
// Display the error message
36+
document.getElementById('errorMessage').textContent = errorMessage;
37+
</script>
38+
</body>
39+
</html>

src/main/resources/templates/payment.html

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -43,25 +43,54 @@
4343
</style>
4444
</head>
4545
<body>
46-
<div >
46+
<div >
47+
<h1>Invoice Details</h1>
4748

48-
<h1>Invoice Details</h1>
49+
<p><strong>Invoice ID:</strong> <span th:text="${invoice.id}"></span></p>
50+
<p><strong>Customer Name:</strong> <span th:text="${invoice.customerName}"></span></p>
51+
<p><strong>Customer Email:</strong> <span th:text="${invoice.customerEmail}"></span></p>
52+
<p><strong>Description:</strong> <span th:text="${invoice.description}"></span></p>
53+
<p><strong>Quantity:</strong> <span th:text="${invoice.quantity}"></span></p>
54+
<p><strong>Unit Price:</strong> <span th:text="${invoice.unitPrice}"></span></p>
55+
<p><strong>Total Amount:</strong> <span th:text="${invoice.totalAmount}"></span></p>
4956

50-
<p><strong>Invoice ID:</strong> <span th:text="${invoice.id}"></span></p>
51-
<p><strong>Customer Name:</strong> <span th:text="${invoice.customerName}"></span></p>
52-
<p><strong>Customer Email:</strong> <span th:text="${invoice.customerEmail}"></span></p>
53-
<p><strong>Description:</strong> <span th:text="${invoice.description}"></span></p>
54-
<p><strong>Quantity:</strong> <span th:text="${invoice.quantity}"></span></p>
55-
<p><strong>Unit Price:</strong> <span th:text="${invoice.unitPrice}"></span></p>
56-
<p><strong>Total Amount:</strong> <span th:text="${invoice.totalAmount}"></span></p>
57+
<form action="#" th:action="@{/payment}" method="post">
58+
<input type="text" placeholder="Enter Link ID" name="linkId" required>
59+
<input type="text" placeholder="Enter Invoice ID" name="invoiceId" required>
60+
<input type="submit" value="Pay">
61+
</form>
62+
</div>
63+
<script>
64+
document.getElementById('paymentForm').addEventListener('submit', function(event) {
65+
event.preventDefault();
5766

58-
<form action="#" th:action="@{/payment}" method="post">
59-
<input type="text" placeholder="Enter Link ID" name="linkId" required>
60-
<input type="text" placeholder="Enter Invoice ID" name="invoiceId" required>
61-
<input type="submit" value="Pay">
62-
</form>
63-
64-
</div>
67+
var linkId = event.target.elements.linkId.value;
68+
var invoiceId = event.target.elements.invoiceId.value;
6569

70+
fetch('/payment', {
71+
method: 'POST',
72+
headers: {
73+
'Content-Type': 'application/json'
74+
},
75+
body: JSON.stringify({
76+
linkId: linkId,
77+
invoiceId: invoiceId
78+
})
79+
})
80+
.then(function(response) {
81+
if (response.ok) {
82+
return response.text();
83+
} else {
84+
throw new Error('Bad request');
85+
}
86+
})
87+
.then(function(message) {
88+
alert(message);
89+
})
90+
.catch(function(error) {
91+
alert('An error occurred: ' + error.message);
92+
});
93+
});
94+
</script>
6695
</body>
6796
</html>

0 commit comments

Comments
 (0)