-
Notifications
You must be signed in to change notification settings - Fork 1
feat: 商品とお店の編集・削除機能を追加 #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| # Java バージョン対応方法 | ||
|
|
||
| ## 問題 | ||
|
|
||
| ビルドや実行時にJavaバージョンが合わない場合のエラー: | ||
|
|
||
| - `UnsupportedClassVersionError: has been compiled by a more recent version of the Java Runtime` | ||
| - `class file version 65.0` (Java 21) vs `class file version 61.0` (Java 17) | ||
|
|
||
| ## 解決方法 | ||
|
|
||
| JAVA_HOMEに適切なJavaバージョンをセットして実行する | ||
|
|
||
| ### miseでインストールされたJavaを使用する場合 | ||
|
|
||
| ```bash | ||
| # Javaのパスを確認 | ||
| mise which java | ||
| # 例: $HOME/.local/share/mise/installs/java/openjdk-21.0.2/bin/java | ||
|
|
||
| # JAVA_HOMEをセットして実行 | ||
| export JAVA_HOME=$HOME/.local/share/mise/installs/java/openjdk-21.0.2 && ./gradlew bootRun | ||
| ``` | ||
|
|
||
| ### プロジェクト要件 | ||
|
|
||
| - **必要なJavaバージョン**: Java 21 | ||
| - **ビルド時**: `./gradlew build -x detekt` | ||
| - **実行時**: `./gradlew bootRun` | ||
|
|
||
| ### 注意事項 | ||
|
|
||
| - プロジェクトはJava 21でコンパイルされているため、Java 21以降が必要 | ||
| - miseでJava環境を管理している場合は、miseのJavaパスを使用する |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| # プライバシーとパス記述ルール【最重要】 | ||
|
|
||
| ## 絶対に守るべきルール | ||
|
|
||
| ### ❌ 禁止事項 | ||
|
|
||
| - **絶対にローカルパスを含めない** | ||
| - `/Users/username/` | ||
| - `/home/username/` | ||
| - 個人を特定できる具体的なユーザーパス | ||
|
|
||
| ### ✅ 正しい記述方法 | ||
|
|
||
| - **環境変数や抽象パスを使用** | ||
| - `$HOME` | ||
| - `~` | ||
| - `$USER_HOME$` | ||
| - `{Java インストールディレクトリ}` | ||
| - 相対パス | ||
|
|
||
| ### 具体例 | ||
|
|
||
| ❌ 悪い例: | ||
|
|
||
| ``` | ||
| /Users/{username}/.local/share/mise/installs/java/ | ||
| /Users/{username}/projects/KidsPOS-Server/ | ||
| ``` | ||
|
|
||
| ✅ 良い例: | ||
|
|
||
| ``` | ||
| $HOME/.local/share/mise/installs/java/ | ||
| ~/projects/KidsPOS-Server/ | ||
| ./relative/path/ | ||
| ``` | ||
|
|
||
| ## 理由 | ||
|
|
||
| - **個人情報の保護**: ユーザー名などの個人情報を露出させない | ||
| - **セキュリティ**: システムパス情報の漏洩を防ぐ | ||
| - **ポータビリティ**: 他の環境でも動作する汎用的な記述 | ||
|
|
||
| ## 適用範囲 | ||
|
|
||
| - コード内のパス | ||
| - ドキュメント | ||
| - コメント | ||
| - ログ出力 | ||
| - エラーメッセージ | ||
| - メモリファイル | ||
| - **すべての出力において厳守** |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -36,4 +36,24 @@ class StoresController { | |
| storeService.save(store) | ||
| return "redirect:/stores" | ||
| } | ||
|
|
||
| @PostMapping("{id}/update") | ||
| fun update(@PathVariable id: Int, @ModelAttribute store: StoreBean): String { | ||
| val existingStore = storeService.findStore(id) | ||
| if (existingStore != null) { | ||
| val updatedStore = StoreBean( | ||
| id = id, | ||
| name = store.name, | ||
| printerUri = store.printerUri | ||
| ) | ||
| storeService.save(updatedStore) | ||
| } | ||
| return "redirect:/stores" | ||
| } | ||
|
Comment on lines
+40
to
+52
|
||
|
|
||
| @PostMapping("{id}/delete") | ||
| fun delete(@PathVariable id: Int): String { | ||
| storeService.delete(id) | ||
| return "redirect:/stores" | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -65,11 +65,16 @@ class StoreService( | |||||||||||||
| ] | ||||||||||||||
| ) | ||||||||||||||
| fun save(storeBean: StoreBean): StoreEntity { | ||||||||||||||
| logger.info("Creating store with name: {}", storeBean.name) | ||||||||||||||
| val id = idGenerationService.generateNextId(repository) | ||||||||||||||
| val store = StoreEntity(id, storeBean.name, storeBean.printerUri) | ||||||||||||||
| logger.info("Saving store with name: {}", storeBean.name) | ||||||||||||||
|
||||||||||||||
| logger.info("Saving store with name: {}", storeBean.name) | |
| if (storeBean.id == null || storeBean.id <= 0) { | |
| logger.info("Creating store with name: {}", storeBean.name) | |
| } else { | |
| logger.info("Updating store with ID: {}, name: {}", storeBean.id, storeBean.name) | |
| } |
Copilot
AI
Sep 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The log message should differentiate between create and update operations. Consider using 'Store created successfully' for new stores and 'Store updated successfully' for existing stores to improve debugging clarity.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| <!DOCTYPE html> | ||
| <html lang="ja" xmlns:th="http://www.thymeleaf.org"> | ||
| <head th:replace="~{layout::base_header('商品編集')}"> | ||
| </head> | ||
| <body> | ||
| <div class="container"> | ||
| <h2>商品編集</h2> | ||
| <form th:action="@{/items/{id}/update(id=${item.id})}" method="post"> | ||
| <div class="form-group mb-3"> | ||
| <label for="barcode">バーコード</label> | ||
| <input type="text" class="form-control" id="barcode" name="barcode" th:value="${item.barcode}" required> | ||
| </div> | ||
| <div class="form-group mb-3"> | ||
| <label for="name">商品名</label> | ||
| <input type="text" class="form-control" id="name" name="name" th:value="${item.name}" required> | ||
| </div> | ||
| <div class="form-group mb-3"> | ||
| <label for="price">値段</label> | ||
| <input type="number" class="form-control" id="price" name="price" th:value="${item.price}" required> | ||
| </div> | ||
| <button type="submit" class="btn btn-primary">更新</button> | ||
| <a href="/items" class="btn btn-secondary">キャンセル</a> | ||
| </form> | ||
|
|
||
| <form th:action="@{/items/{id}/delete(id=${item.id})}" method="post" class="mt-3" | ||
| onsubmit="return confirm('この商品を削除しますか?')"> | ||
| <button type="submit" class="btn btn-danger">削除</button> | ||
| </form> | ||
| </div> | ||
| </body> | ||
| </html> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| <!DOCTYPE html> | ||
| <html lang="ja" xmlns:th="http://www.thymeleaf.org"> | ||
| <head th:replace="~{layout::base_header('お店編集')}"> | ||
| </head> | ||
| <body> | ||
| <div class="container"> | ||
| <h2>お店編集</h2> | ||
| <form th:action="@{/stores/{id}/update(id=${store.id})}" method="post"> | ||
| <div class="form-group mb-3"> | ||
| <label for="name">お店の名前</label> | ||
| <input type="text" class="form-control" id="name" name="name" th:value="${store.name}" required> | ||
| </div> | ||
| <div class="form-group mb-3"> | ||
| <label for="printerUri">プリンターURI</label> | ||
| <input type="text" class="form-control" id="printerUri" name="printerUri" th:value="${store.printerUri}" | ||
| required> | ||
| </div> | ||
| <button type="submit" class="btn btn-primary">更新</button> | ||
| <a href="/stores" class="btn btn-secondary">キャンセル</a> | ||
| </form> | ||
|
|
||
| <form th:action="@{/stores/{id}/delete(id=${store.id})}" method="post" class="mt-3" | ||
| onsubmit="return confirm('このお店を削除しますか?')"> | ||
| <button type="submit" class="btn btn-danger">削除</button> | ||
| </form> | ||
| </div> | ||
| </body> | ||
| </html> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method silently ignores updates when the item doesn't exist. Consider returning an error response or throwing an exception when attempting to update a non-existent item to provide clearer feedback to users.