Skip to content

Commit b8754ba

Browse files
Atsumi3claude
andcommitted
feat: 商品とお店の編集・削除機能を追加
- 商品とお店の編集画面を実装 - 更新・削除のエンドポイントを追加 - 一覧画面に編集ボタンを追加 - ServiceクラスにCRUD操作を追加 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent d2b0381 commit b8754ba

8 files changed

Lines changed: 132 additions & 9 deletions

File tree

src/main/kotlin/info/nukoneko/kidspos/server/controller/front/ItemsController.kt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,25 @@ class ItemsController {
3838
itemService.save(item)
3939
return "redirect:/items"
4040
}
41+
42+
@PostMapping("{id}/update")
43+
fun update(@PathVariable id: Int, @ModelAttribute item: ItemBean): String {
44+
val existingItem = itemService.findItem(id)
45+
if (existingItem != null) {
46+
val updatedItem = ItemBean(
47+
id = id,
48+
barcode = item.barcode,
49+
name = item.name,
50+
price = item.price
51+
)
52+
itemService.save(updatedItem)
53+
}
54+
return "redirect:/items"
55+
}
56+
57+
@PostMapping("{id}/delete")
58+
fun delete(@PathVariable id: Int): String {
59+
itemService.delete(id)
60+
return "redirect:/items"
61+
}
4162
}

src/main/kotlin/info/nukoneko/kidspos/server/controller/front/StoresController.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,24 @@ class StoresController {
3636
storeService.save(store)
3737
return "redirect:/stores"
3838
}
39+
40+
@PostMapping("{id}/update")
41+
fun update(@PathVariable id: Int, @ModelAttribute store: StoreBean): String {
42+
val existingStore = storeService.findStore(id)
43+
if (existingStore != null) {
44+
val updatedStore = StoreBean(
45+
id = id,
46+
name = store.name,
47+
printerUri = store.printerUri
48+
)
49+
storeService.save(updatedStore)
50+
}
51+
return "redirect:/stores"
52+
}
53+
54+
@PostMapping("{id}/delete")
55+
fun delete(@PathVariable id: Int): String {
56+
storeService.delete(id)
57+
return "redirect:/stores"
58+
}
3959
}

src/main/kotlin/info/nukoneko/kidspos/server/service/ItemService.kt

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,30 @@ class ItemService(
7474
)
7575
fun save(itemBean: ItemBean): ItemEntity {
7676
logger.info("Creating item with barcode: {}, name: {}", itemBean.barcode, itemBean.name)
77-
val id = if (itemBean.id != null && itemBean.id > 0) {
78-
itemBean.id
77+
val itemId = itemBean.id
78+
val generatedId = if (itemId != null && itemId > 0) {
79+
itemId
7980
} else {
8081
idGenerationService.generateNextId(repository)
8182
}
82-
val item = ItemEntity(id, itemBean.barcode, itemBean.name, itemBean.price)
83+
val item = ItemEntity(generatedId, itemBean.barcode, itemBean.name, itemBean.price)
8384
val savedItem = repository.save(item)
8485
logger.info("Item created successfully with ID: {}", savedItem.id)
8586
return savedItem
8687
}
88+
89+
@Caching(
90+
evict = [
91+
CacheEvict(value = [CacheConfig.ITEMS_CACHE], allEntries = true),
92+
CacheEvict(value = [CacheConfig.ITEM_BY_ID_CACHE], key = "#id")
93+
]
94+
)
95+
fun delete(id: Int) {
96+
logger.info("Deleting item with ID: {}", id)
97+
val item = repository.findByIdOrNull(id)
98+
if (item != null) {
99+
repository.delete(item)
100+
logger.info("Item deleted successfully with ID: {}", id)
101+
}
102+
}
87103
}

src/main/kotlin/info/nukoneko/kidspos/server/service/StoreService.kt

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,16 @@ class StoreService(
6565
]
6666
)
6767
fun save(storeBean: StoreBean): StoreEntity {
68-
logger.info("Creating store with name: {}", storeBean.name)
69-
val id = idGenerationService.generateNextId(repository)
70-
val store = StoreEntity(id, storeBean.name, storeBean.printerUri)
68+
logger.info("Saving store with name: {}", storeBean.name)
69+
val storeId = storeBean.id
70+
val generatedId = if (storeId != null && storeId > 0) {
71+
storeId
72+
} else {
73+
idGenerationService.generateNextId(repository)
74+
}
75+
val store = StoreEntity(generatedId, storeBean.name, storeBean.printerUri)
7176
val savedStore = repository.save(store)
72-
logger.info("Store created successfully with ID: {}", savedStore.id)
77+
logger.info("Store saved successfully with ID: {}", savedStore.id)
7378
return savedStore
7479
}
7580

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<!DOCTYPE html>
2+
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
3+
<head th:replace="~{layout::base_header('商品編集')}">
4+
</head>
5+
<body>
6+
<div class="container">
7+
<h2>商品編集</h2>
8+
<form th:action="@{/items/{id}/update(id=${item.id})}" method="post">
9+
<div class="form-group mb-3">
10+
<label for="barcode">バーコード</label>
11+
<input type="text" class="form-control" id="barcode" name="barcode" th:value="${item.barcode}" required>
12+
</div>
13+
<div class="form-group mb-3">
14+
<label for="name">商品名</label>
15+
<input type="text" class="form-control" id="name" name="name" th:value="${item.name}" required>
16+
</div>
17+
<div class="form-group mb-3">
18+
<label for="price">値段</label>
19+
<input type="number" class="form-control" id="price" name="price" th:value="${item.price}" required>
20+
</div>
21+
<button type="submit" class="btn btn-primary">更新</button>
22+
<a href="/items" class="btn btn-secondary">キャンセル</a>
23+
</form>
24+
25+
<form th:action="@{/items/{id}/delete(id=${item.id})}" method="post" class="mt-3"
26+
onsubmit="return confirm('この商品を削除しますか?')">
27+
<button type="submit" class="btn btn-danger">削除</button>
28+
</form>
29+
</div>
30+
</body>
31+
</html>

src/main/resources/templates/items/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<th>商品名</th>
1515
<th>バーコード</th>
1616
<th>値段</th>
17-
<th></th>
17+
<th>操作</th>
1818
</tr>
1919
</thead>
2020
<tbody>
@@ -27,7 +27,7 @@
2727
<td th:text="${item.name}"></td>
2828
<td th:text="${item.barcode}"></td>
2929
<td th:text="${item.price}"></td>
30-
<!--<td><a class="btn btn-default btn-xs" th:href="@{/items/{id}/edit(id=*{id})}">編集</a></td>-->
30+
<td><a class="btn btn-primary btn-sm" th:href="@{/items/{id}/edit(id=${item.id})}">編集</a></td>
3131
</tr>
3232
</tbody>
3333
</table>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<!DOCTYPE html>
2+
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
3+
<head th:replace="~{layout::base_header('お店編集')}">
4+
</head>
5+
<body>
6+
<div class="container">
7+
<h2>お店編集</h2>
8+
<form th:action="@{/stores/{id}/update(id=${store.id})}" method="post">
9+
<div class="form-group mb-3">
10+
<label for="name">お店の名前</label>
11+
<input type="text" class="form-control" id="name" name="name" th:value="${store.name}" required>
12+
</div>
13+
<div class="form-group mb-3">
14+
<label for="printerUri">プリンターURI</label>
15+
<input type="text" class="form-control" id="printerUri" name="printerUri" th:value="${store.printerUri}"
16+
required>
17+
</div>
18+
<button type="submit" class="btn btn-primary">更新</button>
19+
<a href="/stores" class="btn btn-secondary">キャンセル</a>
20+
</form>
21+
22+
<form th:action="@{/stores/{id}/delete(id=${store.id})}" method="post" class="mt-3"
23+
onsubmit="return confirm('このお店を削除しますか?')">
24+
<button type="submit" class="btn btn-danger">削除</button>
25+
</form>
26+
</div>
27+
</body>
28+
</html>

src/main/resources/templates/stores/index.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@
1010
<th>ID</th>
1111
<th>店名</th>
1212
<th>プリンタ</th>
13+
<th>操作</th>
1314
</tr>
1415
</thead>
1516
<tbody>
1617
<tr th:each="store: ${data}">
1718
<td th:text="${store.id}"></td>
1819
<td th:text="${store.name}"></td>
1920
<td th:text="${store.printerUri}"></td>
21+
<td><a class="btn btn-primary btn-sm" th:href="@{/stores/{id}/edit(id=${store.id})}">編集</a></td>
2022
</tr>
2123
</tbody>
2224
</table>

0 commit comments

Comments
 (0)