Skip to content

Commit

Permalink
Update database schema and UI templates
Browse files Browse the repository at this point in the history
  • Loading branch information
tsviz committed Jan 30, 2024
1 parent dfd46ae commit 653e5b7
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 64 deletions.
59 changes: 31 additions & 28 deletions src/main/java/net/codejava/AppController.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import java.security.Principal;
import java.time.LocalDate;

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
Expand All @@ -26,6 +30,10 @@
import org.springframework.data.domain.Page; // Add this import statement
// import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.dao.DuplicateKeyException;
import java.util.Date;
// import java.util.logging.Logger;
// import java.util.logging.Level;

@EnableJpaRepositories(basePackages = "net.codejava")
@Controller
Expand All @@ -41,12 +49,7 @@ public class AppController {
@Autowired
private AuthenticationManager authenticationManager;

// @Autowired
// private final SalesRecordRepository salesRecordRepository;

// public AppController(SalesRecordRepository salesRecordRepository) {
// this.salesRecordRepository = salesRecordRepository;
// }
// private static final Logger logger = Logger.getLogger(AppController.class.getName());

@Value("${enableSearchFeature}")
private boolean enableSearchFeature;
Expand All @@ -65,24 +68,15 @@ public String viewHomePage(Model model , Principal principal, @RequestParam(defa
model.addAttribute("listSale", salePage.getContent());
model.addAttribute("currentPage", page);
model.addAttribute("totalPages", salePage.getTotalPages());

return "index";
}

// @GetMapping("/")
// public String showPage(Model model, @RequestParam(defaultValue="0") int page) {
// Pageable pageable = PageRequest.of(page, 5);
// Page<Sale> data = salesRecordRepository.findAll(pageable);
// data = data != null ? data : Page.empty(); // Assign an empty Page if data is null
// model.addAttribute("data", data);
// return "index";
// }

@RequestMapping("/new")
public ModelAndView showNewForm() {
ModelAndView mav = new ModelAndView("new_form");
Sale sale = new Sale();
mav.addObject("sale", sale);
mav.addObject("currentDate", LocalDate.now());
mav.addObject("enableSearchFeature", enableSearchFeature);
return mav;
}
Expand All @@ -101,17 +95,26 @@ public String search(@ModelAttribute("q") String query, Model model) {
List<Sale> listSale = dao.search(query);
model.addAttribute("listSale", listSale);

boolean enableSearchFeature = true; // or get this value from somewhere else
boolean enableSearchFeature = true;
model.addAttribute("enableSearchFeature", enableSearchFeature);

return "search";
}

@RequestMapping(value = "/save", method = RequestMethod.POST)
public String save(@ModelAttribute("sale") Sale sale) {
dao.save(sale);

return "redirect:/";
public String save(@ModelAttribute("sale") Sale sale, RedirectAttributes redirectAttributes) {

try {
if (sale.getDate() == null) {
sale.setDate(new Date());
}
dao.save(sale);
} catch (DuplicateKeyException e) {
redirectAttributes.addFlashAttribute("errorMessage", e.getMessage());
return "redirect:/new";
}

return "redirect:/";
}

@RequestMapping(value = "/login", method = RequestMethod.GET)
Expand Down Expand Up @@ -145,15 +148,15 @@ public String update(@ModelAttribute("sale") Sale sale) {
return "redirect:/";
}

@RequestMapping("/delete/{id}")
public String delete(@PathVariable(name = "id") int id) {
dao.delete(String.valueOf(id));
@RequestMapping("/delete/{serialNumber}")
public String delete(@PathVariable(name = "serialNumber") String serialNumber) {
dao.delete(serialNumber);
return "redirect:/";
}
}

@RequestMapping("/clear/{id}")
public String clearRecord(@PathVariable(name = "id") int id) {
dao.clearRecord(String.valueOf(id));
@RequestMapping("/clear/{serialNumber}")
public String clearRecord(@PathVariable(name = "serialNumber") String serialNumber) {
dao.clearRecord(serialNumber);
return "redirect:/";
}

Expand Down
6 changes: 5 additions & 1 deletion src/main/java/net/codejava/Sale.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import org.springframework.format.annotation.DateTimeFormat;

import java.util.Date;

@Entity
Expand All @@ -13,6 +15,8 @@ public class Sale {
private String item;
private int quantity;
private float amount;

@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date date;

protected Sale() {
Expand All @@ -27,7 +31,7 @@ protected Sale(final String serialNumber, final String item, final int quantity,
}

public String getSerialNumber() {
return this.serialNumber;
return serialNumber;
}

public void setSerialNumber(String serialNumber) {
Expand Down
51 changes: 34 additions & 17 deletions src/main/java/net/codejava/SalesDAO.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import org.springframework.data.domain.Page; // Import the Page class from the correct package
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable; // Import the Pageable class from the correct package

import org.springframework.dao.DuplicateKeyException;

@Repository
public class SalesDAO {
Expand All @@ -32,21 +32,38 @@ public List<Sale> list() {
return listSale;
}

public void save(Sale sale) {
if (sale == null) {
throw new IllegalArgumentException("Sale object cannot be null");
}

if (jdbcTemplate == null) {
throw new IllegalStateException("JdbcTemplate cannot be null");
public void save(Sale sale) throws DuplicateKeyException {
try {
System.out.println(sale); // log the Sale object

if (sale == null) {
throw new IllegalArgumentException("Sale object cannot be null");
}

if (jdbcTemplate == null) {
throw new IllegalStateException("JdbcTemplate cannot be null");
}
// Check if a record with the same primary key already exists
int count = jdbcTemplate.queryForObject(
"SELECT COUNT(*) FROM sales WHERE serial_number = ?", Integer.class, sale.getSerialNumber());

if (count > 0) {
// If such a record exists, throw an exception
throw new DuplicateKeyException("A record with the same serial number already exists.");
}

// If no such record exists, insert the new record
SimpleJdbcInsert insertActor =
new SimpleJdbcInsert(jdbcTemplate != null ? jdbcTemplate : new JdbcTemplate());
insertActor.withTableName("sales").usingColumns("serial_number", "item", "quantity", "amount", "date");
BeanPropertySqlParameterSource param = new BeanPropertySqlParameterSource(sale);

insertActor.execute(param);
} catch (DuplicateKeyException e) {
throw e; // rethrow the exception to be handled by the caller
} catch (Exception e) {
e.printStackTrace(); // log any other exceptions
}

SimpleJdbcInsert insertActor =
new SimpleJdbcInsert(jdbcTemplate != null ? jdbcTemplate : new JdbcTemplate());
insertActor.withTableName("sales").usingColumns("serialNumber", "item", "quantity", "amount");
BeanPropertySqlParameterSource param = new BeanPropertySqlParameterSource(sale);

insertActor.execute(param);
}

public Sale get(String serialNumber) {
Expand All @@ -61,7 +78,7 @@ public void update(Sale sale) {
throw new IllegalArgumentException("Sale object cannot be null");
}

String sql = "UPDATE SALES SET item=:item, quantity=:quantity, amount=:amount WHERE serial_number=:serial_number";
String sql = "UPDATE SALES SET item=:item, quantity=:quantity, amount=:amount WHERE serial_number=:serialNumber";
BeanPropertySqlParameterSource param = new BeanPropertySqlParameterSource(sale);

if (jdbcTemplate == null) {
Expand Down Expand Up @@ -97,7 +114,7 @@ public Page<Sale> findAll(Pageable pageable) {
// Check if totalInteger is null
int total = (totalInteger != null) ? totalInteger : 0;

String query = "SELECT * FROM sales ORDER BY serial_number ASC LIMIT ? OFFSET ?";
String query = "SELECT * FROM sales ORDER BY item ASC LIMIT ? OFFSET ?";
List<Sale> sales = jdbcTemplate.query(query, new BeanPropertyRowMapper<>(Sale.class), pageable.getPageSize(), pageable.getOffset());

return new PageImpl<>(sales, pageable, total);
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/db/changelog/changelog_version-3.3.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<column name="item" type="varchar(100)" />
<column name="amount" type="double" />
<column name="quantity" type="int" />
<column name="date" type="date" defaultValueComputed="CURRENT_DATE" />
<column name="date" type="date" defaultValueComputed="CURRENT_DATE"/>
</createTable>
</changeSet>
<!-- create a changeset that loads a csv file. -->
Expand Down
5 changes: 3 additions & 2 deletions src/main/resources/templates/edit_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@
<script src="/js/styles.js"></script>
</head>
<body>
<h1>Edit Sale</h1>
<h1>Edit Record</h1>
<div align="center">
<button onclick="window.location.href='/';">Go back to inventory table</button>
<form action="#" th:action="@{/update}" th:object="${sale}" method="post">
<div align="center">
<table style="width: 35%" border="1" cellpadding="10">
Expand All @@ -52,7 +53,7 @@ <h1>Edit Sale</h1>
</tr>
<tr>
<td>Item Name:</td>
<td><input type="text" th:field="*{item}" /></td>
<td><input type="text" th:field="*{item}" th:value="${sale != null ? sale.item : ''}" required minlength="3" maxlength="50" title="Item name must be between 2 and 50 characters long." /></td>
</tr>
<tr>
<td>Quantity:</td>
Expand Down
5 changes: 2 additions & 3 deletions src/main/resources/templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Sales Records</title>
<style>
body {
background-color: #f2f2f2;
Expand Down Expand Up @@ -90,8 +89,8 @@ <h1>Inventory Records</h1>
<td th:text="${sale.amount}">Amount</td>
<td class="actions">
<a th:href="@{'/edit/' + ${sale.serialNumber}}">Edit</a>
<a th:href="@{'/delete/' + ${sale.serialNumber}}">Delete</a>
<a th:href="@{'/clear/' + ${sale.serialNumber}}">Clear</a>
<a th:href="@{'/delete/' + ${sale.serialNumber}}" onclick="return confirm('Delete: This action is irreversible. Are you sure you want to delete the sale record?')" style="color: red;">Delete</a>
<a th:href="@{'/clear/' + ${sale.serialNumber}}" onclick="return confirm('Clear: This action is irreversible. Are you sure you want to clear the sale record?')" style="color: #ff7f7f;">Clear</a>
</td>
</tr>
</tbody>
Expand Down
27 changes: 19 additions & 8 deletions src/main/resources/templates/new_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8" />
<title>New Sale</title>
<title>New Item</title>
<style>
body {
background-color: #f2f2f2;
Expand Down Expand Up @@ -41,32 +41,43 @@
<script src="js/styles.js"></script>
</head>
<body>
<h1>Edit Sale</h1>
<h1>Enter Record</h1>
<div align="center">
<form action="#" th:action="@{/update}" th:object="${sale}" method="post">
<button onclick="window.location.href='/';">Go back to inventory table</button>
<form action="#" th:action="@{/save}" th:object="${sale}" method="post">
<div align="center">
<table style="width: 35%" border="1" cellpadding="10">
<tr>
<td>Serial Number:</td>
<td><input type="text" th:field="*{serialNumber}" /></td>
<td><input type="text" name="serialNumber" required pattern="[A-Z]\d{4}" title="Pattern: 'A0000' where 'A' is any uppercase letter and '0' represents any digit"></td>
</tr>
<tr>
<td>Item Name:</td>
<td><input type="text" th:field="*{item}" /></td>
<td><input type="text" th:field="*{item}" th:value="${sale != null ? sale.item : ''}" required minlength="3" maxlength="50" title="Item name must be between 2 and 50 characters long." /></td>
</tr>
<tr>
<td>Quantity:</td>
<td><input type="text" th:field="*{quantity}" /></td>
<td><input type="text" th:field="*{quantity}" th:value="${sale != null ? sale.quantity : ''}" /></td>
</tr>
<tr>
<td>Amount (USD):</td>
<td><input type="text" th:field="*{amount}" /></td>
</tr>
<td><input type="text" th:field="*{amount}" th:value="${sale != null ? sale.amount : ''}" /></td>
</tr>
<tr>
<td>Date:</td>
<td><input id="dateInput" type="date" th:field="*{date}" th:value="${currentDate}" required/></td>
</tr>
<tr>
<td colspan="2"><button type="submit">Save</button> </td>
</tr>
</table>
</form>
</div>
<div th:if="${errorMessage}" class="alert alert-danger" role="alert">
<p th:text="${errorMessage}" style="color: red;"></p>
</div>
<script>
document.getElementById('dateInput').valueAsDate = new Date();
</script>
</body>
</html>
8 changes: 4 additions & 4 deletions src/main/resources/templates/search.html
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,14 @@ <h1>Sales Records - Search Results</h1>
</thead>
<tbody>
<tr th:each="sale : ${listSale}">
<td th:text="${sale.id}">ID</td>
<td th:text="${sale.serialNumber}">ID</td>
<td th:text="${sale.item}">Item Name</td>
<td th:text="${sale.quantity}">Quantity</td>
<td th:text="${sale.amount}">Amount</td>
<td class="actions">
<a th:href="@{'/edit/' + ${sale.id}}">Edit</a>
<a th:href="@{'/delete/' + ${sale.id}}">Delete</a>
<a th:href="@{'/clear/' + ${sale.id}}">Clear</a>
<a th:href="@{'/edit/' + ${sale.serialNumber}}">Edit</a>
<a th:href="@{'/delete/' + ${sale.serialNumber}}">Delete</a>
<a th:href="@{'/clear/' + ${sale.serialNumber}}">Clear</a>
</td>
</tr>
</tbody>
Expand Down

0 comments on commit 653e5b7

Please sign in to comment.