diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..73a1f7d --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "java", + "name": "Launch Spring Boot App (local profile)", + "request": "launch", + "cwd": "${workspaceFolder}/backend", + "mainClass": "com.example.todoapp.TodoApplication", + "projectName": "todo-app", + "args": "", + "envFile": "${workspaceFolder}/backend/.env", + "vmArgs": "-Dspring.profiles.active=local" + } + ] +} \ No newline at end of file diff --git a/backend/src/main/java/com/example/todoapp/controller/StocksController.java b/backend/src/main/java/com/example/todoapp/controller/StocksController.java new file mode 100644 index 0000000..8de929c --- /dev/null +++ b/backend/src/main/java/com/example/todoapp/controller/StocksController.java @@ -0,0 +1,148 @@ +package com.example.todoapp.controller; + +import com.example.todoapp.dto.ResponseStockDTO; +import com.example.todoapp.dto.DeleteStockRequest; +import com.example.todoapp.dto.StockDTO; +import com.example.todoapp.model.Stocks; +import com.example.todoapp.model.User; +import com.example.todoapp.repository.UserRepository; +import com.example.todoapp.service.StocksService; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 在庫管理のコントローラー + *

+ * このコントローラーは在庫の取得、作成、更新、削除などの + * エンドポイントを提供します。すべてのエンドポイントは認証が必要です。 + *

+ */ +@RestController +@RequestMapping("/stocks") +public class StocksController { + + @Autowired + private StocksService stockService; + + @Autowired + private UserRepository userRepository; + + /** + * ログインユーザーのすべての在庫を取得する + * + * @param authentication 認証情報 + * @return ユーザーの在庫リスト + */ + @GetMapping("/get") + public ResponseEntity> getAllStocks(Authentication authentication) { + List stocks = stockService.getALLStocksByUser(authentication.getName()); + // エンティティからDTOへの変換 + List stockDTOs = stocks.stream() + .map(ResponseStockDTO::fromEntity) + .collect(Collectors.toList()); + return ResponseEntity.ok(stockDTOs); + } + + /** + * 指定されたIDの在庫を取得する + * + * @param authentication 認証情報 + * @param stockId 在庫ID + * @return 在庫情報 + */ + @GetMapping("/{id}") + public ResponseEntity getStockById( + Authentication authentication, + @PathVariable("id") Long stockId) { + Stocks stock = stockService.getStockById(authentication.getName(), stockId); + return ResponseEntity.ok(StockDTO.fromEntity(stock)); + } + + /** + * 新しい在庫を作成する + * + * @param authentication 認証情報 + * @param stock 作成する在庫の情報 + * @return 作成された在庫 + */ + @PostMapping("/add") + public ResponseEntity createStock( + Authentication authentication, + @Valid @RequestBody Stocks stock) { + Stocks createdStock = stockService.createStock(authentication.getName(), stock); + return ResponseEntity.ok(StockDTO.fromEntity(createdStock)); + } + + /** + * 指定されたIDの在庫を更新する + * + * @param authentication 認証情報 + * @param stockId 更新する在庫のID + * @param stockDetails 更新内容 + * @return 更新された在庫 + */ + @PutMapping("/update") + public ResponseEntity> updateStock( + Authentication authentication, + @Valid @RequestBody StockDTO stockDTO) { + + Stocks updatedStock = stockService.updateStocks(authentication.getName(), stockDTO); + + Map response = new HashMap<>(); + + if (updatedStock == null) { + response.put("result", false); + response.put("message", "指定されたIDの在庫が見つかりませんでした"); + return ResponseEntity.ok(response); + }else { + response.put("result", true); + response.put("message", "变更成功しました"); + } + + return ResponseEntity.ok(response); + } + + /** + * 指定されたIDの在庫を削除する + * + * @param authentication 認証情報 + * @param taskId 削除する在庫のID + * @return 空のレスポンス + */ + @DeleteMapping("/delete") + public ResponseEntity deleteStock( + Authentication authentication, + @RequestBody DeleteStockRequest request + ) { + + // 認証されたユーザー名を取得 + String username = authentication.getName(); + + // ユーザー情報を取得 + User user = userRepository.findByUsername(username) + .orElseThrow(() -> new UsernameNotFoundException("User not found")); + + int deletedCount = stockService.deleteStockById(user.getId(), request.getStockId()); + + Map response = new HashMap<>(); + + if (deletedCount > 0) { + response.put("result", true); + response.put("message", "削除成功しました"); + } else { + response.put("result", false); + response.put("message", "指定された在庫が見つかりませんでした"); + } + + return ResponseEntity.ok(response); + } +} \ No newline at end of file diff --git a/backend/src/main/java/com/example/todoapp/controller/StuffsController.java b/backend/src/main/java/com/example/todoapp/controller/StuffsController.java new file mode 100644 index 0000000..68722f6 --- /dev/null +++ b/backend/src/main/java/com/example/todoapp/controller/StuffsController.java @@ -0,0 +1,64 @@ +//-------------------------------- +// StuffsController.java +// +// 更新履歴:2025/06/09 新規作成 +// Copyright(c) 2025 IVIS All rights reserved. +//-------------------------------------------- +package com.example.todoapp.controller; + +import com.example.todoapp.dto.StuffsDTO; +import com.example.todoapp.model.Stuffs; +import com.example.todoapp.service.StuffsService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.Collections; + + +/** + * 材料リストに関するRESTコントローラー + * + * このコントローラーは、材料 (stuffs) の管理に関するエンドポイントを提供します。 + * + */ +@RestController +@RequestMapping("/stuff") +public class StuffsController { + + @Autowired + private StuffsService stuffsService; + + + /** + * カテゴリ指定で材料を取得するメソッド + * + * @param category カテゴリ名 + * @return 指定されたカテゴリに属する材料のリスト + */ + @GetMapping("/get") + public ResponseEntity getAllStuffsByCategory(String category) { + List stuffsList = stuffsService.getAllStuffsByCategory(category); + //DTOに変換 + List responceList = stuffsList.stream() + .map(stuff -> { + StuffsDTO resp = new StuffsDTO(); + resp.setStuffId(stuff.getStuffId()); + resp.setStuffName(stuff.getStuffName()); + resp.setSummary(stuff.getSummary()); + resp.setCategory(stuff.getCategory()); + return resp; + }) + .collect(Collectors.toList()); + // 空のリストの場合は空のリストを返す + if (responceList.isEmpty()) { + return ResponseEntity.ok(Collections.emptyList()); + } + return ResponseEntity.ok(responceList); + } + +} diff --git a/backend/src/main/java/com/example/todoapp/controller/ToBuysController.java b/backend/src/main/java/com/example/todoapp/controller/ToBuysController.java index 7b81ea3..8467c37 100644 --- a/backend/src/main/java/com/example/todoapp/controller/ToBuysController.java +++ b/backend/src/main/java/com/example/todoapp/controller/ToBuysController.java @@ -7,9 +7,11 @@ package com.example.todoapp.controller; +import com.example.todoapp.dto.BuyRequestDTO; import com.example.todoapp.dto.DeleteToBuyRequest; import com.example.todoapp.dto.ToBuyResponse; import com.example.todoapp.dto.ToBuysDTO; +import com.example.todoapp.model.Stuffs; import com.example.todoapp.model.ToBuys; import com.example.todoapp.model.User; import com.example.todoapp.repository.UserRepository; @@ -20,6 +22,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import java.util.Collections; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; @@ -30,7 +33,7 @@ import org.springframework.web.bind.annotation.*; /** * 購入リストに関するRESTコントローラー *

- * このコントローラーは、購入リスト (to_buys) へのアイテム追加機能を提供します。 + * このコントローラーは、購入リスト (toBuys) へのアイテム追加機能を提供します。 * リクエストボディには ToBuyDTO 形式のデータが期待されます。 *

*/ @@ -52,19 +55,41 @@ public class ToBuysController { */ @PostMapping("/add") - public ResponseEntity addToBuys( + public ResponseEntity> addToBuys( @Valid @RequestBody ToBuysDTO dto, Authentication authentication) { - toBuysService.addToBuys(dto, authentication); - return ResponseEntity.ok("Item added to 'To Buys' successfully"); + + ToBuys createdToBuy = toBuysService.addToBuys(dto, authentication); + + Map response = new HashMap<>(); + response.put("result", true); + response.put("tobuyId", createdToBuy.getTobuyId()); + response.put("stuffId", createdToBuy.getStuff().getStuffId()); + response.put("message", "追加に成功しました"); + + return ResponseEntity.ok(response); } + /** + * 指定されたIDの在庫を更新する + * + * @param authentication 認証情報 + * @param dto 更新内容 + * @return 更新された + */ @PutMapping("/update") - public ResponseEntity updateToBuys( + public ResponseEntity> updateToBuys( @Valid @RequestBody ToBuysDTO dto, Authentication authentication) { toBuysService.updateToBuys(dto, authentication); - return ResponseEntity.ok("Item updated to 'To Buys' successfully"); + + ToBuys updatedToBuy = toBuysService.updateToBuys(dto, authentication); + + Map response = new HashMap<>(); + response.put("tobuyId", updatedToBuy.getTobuyId()); + response.put("stuffId", updatedToBuy.getStuff().getStuffId()); + + return ResponseEntity.ok(response); } @@ -85,23 +110,24 @@ public class ToBuysController { User user = userRepository.findByUsername(username) .orElseThrow(() -> new UsernameNotFoundException("User not found")); - List toBuysList = toBuysService.getToBuysByUserId(user.getId()); + List toBuysList = toBuysService.getToBuysByUser(user); // DTO形式に変換して返す List responseList = toBuysList.stream() .map(toBuy -> { ToBuyResponse resp = new ToBuyResponse(); - resp.setTobuy_id(toBuy.getTobuy_id()); - resp.setStuff_id(toBuy.getStuffs().getStuff_id()); - resp.setStuff_name(toBuy.getStuffs().getStuff_name()); + Stuffs stuff = toBuy.getStuff(); + resp.setTobuyId(toBuy.getTobuyId()); + resp.setStuffId(stuff.getStuffId()); + resp.setStuffName(stuff.getStuffName()); resp.setAmount(toBuy.getAmount()); resp.setShop(toBuy.getStore()); return resp; }) .collect(Collectors.toList()); - Map responseBody = new HashMap<>(); - responseBody.put("tobuy_array", responseList); + // Map responseBody = new HashMap<>(); + // responseBody.put("tobuy_array", responseList); return ResponseEntity.ok(responseList); } @@ -116,19 +142,11 @@ public class ToBuysController { public ResponseEntity> deleteToBuy( @RequestBody DeleteToBuyRequest request, Authentication authentication) { - - // 認証されたユーザー名を取得 - String username = authentication.getName(); - - // ユーザー情報を取得 - User user = userRepository.findByUsername(username) - .orElseThrow(() -> new UsernameNotFoundException("User not found")); - int deletedCount = toBuysService.deleteToBuyByIds(user.getId(), request.getTobuy_id()); + int deletedCount = toBuysService.deleteToBuyById(request.getTobuyId()); Map response = new HashMap<>(); - if (deletedCount > 0) { response.put("result", true); } else { @@ -137,4 +155,24 @@ public class ToBuysController { return ResponseEntity.ok(response); } + + /** + * 買うものリストの在庫登録(購入処理) + * 買うものリストから削除し,追加情報を付加して在庫リストに追加 + * + * @param request 「買うもの」の情報を含むリクエストボディ + * @return + */ + @PostMapping("/buy") + public ResponseEntity> buyToBuys( + Authentication authentication, + @RequestBody BuyRequestDTO toBuysDTO) { + + toBuysService.buyToBuys(authentication.getName(), toBuysDTO); + + Map response = new HashMap<>(); + response.put("result", true); + return ResponseEntity.ok(response); + } + } \ No newline at end of file diff --git a/backend/src/main/java/com/example/todoapp/dto/BuyRequestDTO.java b/backend/src/main/java/com/example/todoapp/dto/BuyRequestDTO.java new file mode 100644 index 0000000..38438f9 --- /dev/null +++ b/backend/src/main/java/com/example/todoapp/dto/BuyRequestDTO.java @@ -0,0 +1,14 @@ +package com.example.todoapp.dto; + +import java.time.LocalDate; + +import lombok.Data; + +@Data +public class BuyRequestDTO { + private Long tobuyId; + private int price; + private LocalDate expDate; + private LocalDate lastUpdate; + private LocalDate buyDate; +} \ No newline at end of file diff --git a/backend/src/main/java/com/example/todoapp/dto/DeleteStockRequest.java b/backend/src/main/java/com/example/todoapp/dto/DeleteStockRequest.java new file mode 100644 index 0000000..7eee296 --- /dev/null +++ b/backend/src/main/java/com/example/todoapp/dto/DeleteStockRequest.java @@ -0,0 +1,8 @@ +package com.example.todoapp.dto; + +import lombok.Data; + +@Data +public class DeleteStockRequest { + private Long stockId; +} \ No newline at end of file diff --git a/backend/src/main/java/com/example/todoapp/dto/DeleteToBuyRequest.java b/backend/src/main/java/com/example/todoapp/dto/DeleteToBuyRequest.java index b19c196..07b2a37 100644 --- a/backend/src/main/java/com/example/todoapp/dto/DeleteToBuyRequest.java +++ b/backend/src/main/java/com/example/todoapp/dto/DeleteToBuyRequest.java @@ -4,6 +4,6 @@ import lombok.Data; @Data public class DeleteToBuyRequest { - private Long user_id; - private int tobuy_id; + private Long userId; + private Long tobuyId; } \ No newline at end of file diff --git a/backend/src/main/java/com/example/todoapp/dto/ResponseStockDTO.java b/backend/src/main/java/com/example/todoapp/dto/ResponseStockDTO.java new file mode 100644 index 0000000..1de5012 --- /dev/null +++ b/backend/src/main/java/com/example/todoapp/dto/ResponseStockDTO.java @@ -0,0 +1,54 @@ +package com.example.todoapp.dto; + +import com.example.todoapp.model.Stocks; +import com.example.todoapp.model.Stuffs; + +import lombok.Data; + +import java.time.LocalDate; + +/** + * 在庫のデータ転送オブジェクト(DTO) + *

+ * このクラスはクライアントとサーバー間で在庫情報をやり取りするために使用されます。 + * エンティティとは異なり、必要な情報のみを含み、関連エンティティへの参照ではなくIDのみを保持します。 + *

+ */ + +@Data +public class ResponseStockDTO { + private Long stockId; + private Long stuffId; + private Long userId; + private int amount; + private int price; + private LocalDate buyDate; + private LocalDate lastUpdate; + private LocalDate expDate; + private String stuffName; + private String category; + + /** + * 在庫エンティティからDTOを作成する + * + * @param stock 変換元の在庫エンティティ + * @return 変換されたStockDTOオブジェクト + */ + public static ResponseStockDTO fromEntity(Stocks stock) { + ResponseStockDTO dto = new ResponseStockDTO(); + Stuffs stuff = stock.getStuff(); + + dto.setStockId(stock.getStockId()); + dto.setStuffId(stock.getStuff().getStuffId()); + dto.setUserId(stock.getUser().getId()); + dto.setAmount(stock.getAmount()); + dto.setPrice(stock.getPrice()); + dto.setBuyDate(stock.getBuyDate()); + dto.setLastUpdate(stock.getLastUpdate()); + dto.setExpDate(stock.getExpDate()); + dto.setStuffName(stuff.getStuffName()); + dto.setCategory(stuff.getCategory()); + + return dto; + } +} \ No newline at end of file diff --git a/backend/src/main/java/com/example/todoapp/dto/StockDTO.java b/backend/src/main/java/com/example/todoapp/dto/StockDTO.java new file mode 100644 index 0000000..284b134 --- /dev/null +++ b/backend/src/main/java/com/example/todoapp/dto/StockDTO.java @@ -0,0 +1,46 @@ +package com.example.todoapp.dto; + +import com.example.todoapp.model.Stocks; + +import lombok.Data; + +import java.time.LocalDate; + +/** + * 在庫のデータ転送オブジェクト(DTO) + *

+ * このクラスはクライアントとサーバー間で在庫情報をやり取りするために使用されます。 + * エンティティとは異なり、必要な情報のみを含み、関連エンティティへの参照ではなくIDのみを保持します。 + *

+ */ + +@Data +public class StockDTO { + private Long stockId; + private Long stuffId; + private Long userId; + private int amount; + private int price; + private LocalDate buyDate; + private LocalDate lastUpdate; + private LocalDate expDate; + + /** + * 在庫エンティティからDTOを作成する + * + * @param stock 変換元の在庫エンティティ + * @return 変換されたStockDTOオブジェクト + */ + public static StockDTO fromEntity(Stocks stock) { + StockDTO dto = new StockDTO(); + dto.setStockId(stock.getStockId()); + dto.setStuffId(stock.getStuff().getStuffId()); + dto.setUserId(stock.getUser().getId()); + dto.setAmount(stock.getAmount()); + dto.setPrice(stock.getPrice()); + dto.setBuyDate(stock.getBuyDate()); + dto.setLastUpdate(stock.getLastUpdate()); + dto.setExpDate(stock.getExpDate()); + return dto; + } +} \ No newline at end of file diff --git a/backend/src/main/java/com/example/todoapp/dto/StuffsDTO.java b/backend/src/main/java/com/example/todoapp/dto/StuffsDTO.java new file mode 100644 index 0000000..5dd6706 --- /dev/null +++ b/backend/src/main/java/com/example/todoapp/dto/StuffsDTO.java @@ -0,0 +1,42 @@ +//-------------------------------- +// StuffsDTO.java +// +// +// 更新履歴:2025/06/09 新規作成 +// Copyright(c) 2025 IVIS All rights reserved. +//-------------------------------------------- +package com.example.todoapp.dto; + +import com.example.todoapp.model.Stuffs; +import lombok.Data; + + +/** + * 材料のデータ転送オブジェクト(DTO)クラス + * + * このクラスは、材料情報をクライアントとサーバー間でやり取りするために使用されます。 + * エンティティとは異なり、必要な情報のみを含み、関連エンティティへの参照ではなくIDのみを保持します。 + */ +@Data +public class StuffsDTO { + private Long stuffId; // 材料ID + private String stuffName; // 材料名 + private String summary; // 概要 + private String category; // カテゴリ + + /** + * StuffsエンティティからDTOを作成する + * + * @param stuff 変換元のStuffsエンティティ + * @return 変換されたStuffsDTOオブジェクト + */ + public static StuffsDTO fromEntity(Stuffs stuff) { + StuffsDTO dto = new StuffsDTO(); + dto.setStuffId(stuff.getStuffId()); + dto.setStuffName(stuff.getStuffName()); + dto.setSummary(stuff.getSummary()); + dto.setCategory(stuff.getCategory()); + return dto; + } + +} diff --git a/backend/src/main/java/com/example/todoapp/dto/ToBuyResponse.java b/backend/src/main/java/com/example/todoapp/dto/ToBuyResponse.java index bf5730b..407ae91 100644 --- a/backend/src/main/java/com/example/todoapp/dto/ToBuyResponse.java +++ b/backend/src/main/java/com/example/todoapp/dto/ToBuyResponse.java @@ -4,9 +4,9 @@ import lombok.Data; @Data public class ToBuyResponse { - private int tobuy_id; - private Long stuff_id; - private String stuff_name; + private Long tobuyId; + private Long stuffId; + private String stuffName; private int amount; private String shop; } \ No newline at end of file diff --git a/backend/src/main/java/com/example/todoapp/dto/ToBuysDTO.java b/backend/src/main/java/com/example/todoapp/dto/ToBuysDTO.java index 90830fd..fd4a6ff 100644 --- a/backend/src/main/java/com/example/todoapp/dto/ToBuysDTO.java +++ b/backend/src/main/java/com/example/todoapp/dto/ToBuysDTO.java @@ -1,6 +1,9 @@ package com.example.todoapp.dto; +import java.time.LocalDate; + import lombok.Data; + /** * カテゴリDTOクラス * このクラスはタスクのカテゴリ情報を表します。 @@ -8,14 +11,17 @@ import lombok.Data; * */ - @Data - public class ToBuysDTO { - private Long stuff_id; - private Long user_id; - - private int amount; - private String shop; - - private String stuff_name; - private String category; - } \ No newline at end of file +@Data +public class ToBuysDTO { + private Long tobuyId; + private Long stuffId; + private Long userId; + private int price; + private int amount; + private String shop; + private String stuffName; + private String category; + private LocalDate expDate; + private LocalDate lastUpdate; + private LocalDate buyDate; +} \ No newline at end of file diff --git a/backend/src/main/java/com/example/todoapp/model/RecipeStuffs.java b/backend/src/main/java/com/example/todoapp/model/RecipeStuffs.java index fc94cd5..74d5738 100644 --- a/backend/src/main/java/com/example/todoapp/model/RecipeStuffs.java +++ b/backend/src/main/java/com/example/todoapp/model/RecipeStuffs.java @@ -28,7 +28,7 @@ import lombok.NoArgsConstructor; @Data @NoArgsConstructor @Entity -@Table(name = "recipe_stuffs") +@Table(name = "recipeStuffs") public class RecipeStuffs { @@ -37,7 +37,8 @@ public class RecipeStuffs { */ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private int recipe_stuffs_id ; + @Column(name="recipeStuffsId") + private Long recipeStuffsId ; /** * 料理の一意識別子 FK @@ -45,8 +46,8 @@ public class RecipeStuffs { @NotBlank @ManyToOne(fetch = FetchType.LAZY) @JoinColumn( - name = "recipe_id", - referencedColumnName = "recipe_id", + name = "recipeId", + referencedColumnName = "recipeId", nullable = false ) private Recipes recipes; @@ -58,17 +59,17 @@ public class RecipeStuffs { @NotBlank @ManyToOne(fetch = FetchType.LAZY) @JoinColumn( - name = "stuff_id", - referencedColumnName = "stuff_id", + name = "stuffId", + referencedColumnName = "stuffId", nullable = false ) - private Stuffs stuffs; + private Stuffs stuff; /** - * 材料の数量 + * 材料の数量(デフォルト1) */ @NotBlank @Column(nullable = false) - private int amount; + private int amount = 1; } diff --git a/backend/src/main/java/com/example/todoapp/model/Recipes.java b/backend/src/main/java/com/example/todoapp/model/Recipes.java index 98d3936..c4a986d 100644 --- a/backend/src/main/java/com/example/todoapp/model/Recipes.java +++ b/backend/src/main/java/com/example/todoapp/model/Recipes.java @@ -35,14 +35,15 @@ public class Recipes { */ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private int recipe_id ; + @Column(name="recipeId") + private Long recipeId ; /** * カテゴリ名 */ @NotNull - @Column(unique = true, length = 255, nullable = false) - private String recipie_name; + @Column(name="recipeName", unique = true, length = 255, nullable = false) + private String recipieName; /** * カテゴリ diff --git a/backend/src/main/java/com/example/todoapp/model/Stocks.java b/backend/src/main/java/com/example/todoapp/model/Stocks.java index d9f3f42..c9c47b2 100644 --- a/backend/src/main/java/com/example/todoapp/model/Stocks.java +++ b/backend/src/main/java/com/example/todoapp/model/Stocks.java @@ -39,7 +39,7 @@ public class Stocks { */ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private int stock_id ; + private Long stockId; /** @@ -48,24 +48,20 @@ public class Stocks { @NotNull @ManyToOne(fetch = FetchType.LAZY) @JoinColumn( - name = "stuff_id", - referencedColumnName = "stuff_id", + name = "stuffId", + referencedColumnName = "stuffId", nullable = false ) - private Stuffs stuffs; - + private Stuffs stuff; /** - * ユーザーテーブル参照用の外部キー + * タスクの所有者(ユーザー) + * 多対一の関係で、遅延ロードを使用 */ - @NotNull - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn( - name = "user_id", - referencedColumnName = "id", - nullable = false - ) - private User user_id; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "userId", nullable = false) + private User user; + /** * 在庫数量(デフォルト値: 1) @@ -83,18 +79,18 @@ public class Stocks { * 購入日 */ @Column(nullable = false) - private LocalDate buy_date; + private LocalDate buyDate; /** * 最後の操作時間 */ @Column(nullable = false) - private LocalDate last_update; + private LocalDate lastUpdate; /** * 賞味期限 */ @Column(nullable = false) - private LocalDate exp_date; + private LocalDate expDate; } \ No newline at end of file diff --git a/backend/src/main/java/com/example/todoapp/model/Stuffs.java b/backend/src/main/java/com/example/todoapp/model/Stuffs.java index 55fe1f9..8807fcf 100644 --- a/backend/src/main/java/com/example/todoapp/model/Stuffs.java +++ b/backend/src/main/java/com/example/todoapp/model/Stuffs.java @@ -1,9 +1,8 @@ //-------------------------------- // Stuffs.java // -// 分類:社員管理システムV2・ビジネスロジック層 // -// 更新履歴:2025/06/02 新規作成 +// 更新履歴:2025/06/09 新規作成 // Copyright(c) 2025 IVIS All rights reserved. //-------------------------------------------- @@ -35,14 +34,15 @@ import lombok.NoArgsConstructor; */ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long stuff_id ; + @Column(name = "stuffId") + private Long stuffId; /** * カテゴリ名 */ @NotNull - @Column(unique = true, length = 255, nullable = false) - private String stuff_name; + @Column(name = "stuffName", unique = true, length = 255, nullable = false) + private String stuffName; /** * カテゴリ diff --git a/backend/src/main/java/com/example/todoapp/model/Task.java b/backend/src/main/java/com/example/todoapp/model/Task.java index 9e3ad8a..c2ba9bd 100644 --- a/backend/src/main/java/com/example/todoapp/model/Task.java +++ b/backend/src/main/java/com/example/todoapp/model/Task.java @@ -51,7 +51,7 @@ public class Task { * 多対一の関係で、遅延ロードを使用 */ @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id", nullable = false) + @JoinColumn(name = "userId", nullable = false) private User user; /** diff --git a/backend/src/main/java/com/example/todoapp/model/ToBuys.java b/backend/src/main/java/com/example/todoapp/model/ToBuys.java index 0670392..6ab9052 100644 --- a/backend/src/main/java/com/example/todoapp/model/ToBuys.java +++ b/backend/src/main/java/com/example/todoapp/model/ToBuys.java @@ -28,7 +28,7 @@ import lombok.NoArgsConstructor; @Data @NoArgsConstructor @Entity -@Table(name = "to_buys") +@Table(name = "toBuys") public class ToBuys { /** @@ -36,7 +36,8 @@ public class ToBuys { */ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private int tobuy_id ; + @Column(name = "tobuyId") + private Long tobuyId ; /** * 材料の一意識別子 FK @@ -44,22 +45,24 @@ public class ToBuys { @NotNull @ManyToOne(fetch = FetchType.LAZY) @JoinColumn( - name = "stuff_id", - referencedColumnName = "stuff_id", + name = "stuffId", + referencedColumnName = "stuffId", nullable = false ) - private Stuffs stuffs; + private Stuffs stuff; /** * ユーザーテーブル参照用の外部キー */ // @NotNull - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn( - name = "user_id", - referencedColumnName = "id" - ) - private User user_id; + + /** + * タスクの所有者(ユーザー) + * 多対一の関係で、遅延ロードを使用 + */ + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "userId", nullable = false) + private User user; /** * 購入する数量 diff --git a/backend/src/main/java/com/example/todoapp/repository/StocksRepository.java b/backend/src/main/java/com/example/todoapp/repository/StocksRepository.java new file mode 100644 index 0000000..9d275e1 --- /dev/null +++ b/backend/src/main/java/com/example/todoapp/repository/StocksRepository.java @@ -0,0 +1,67 @@ +//-------------------------------- +// ToBuysRepository.java +// +// +// 更新履歴:2025/06/05 新規作成 +// Copyright(c) 2025 IVIS All rights reserved. +//-------------------------------------------- +package com.example.todoapp.repository; + +import com.example.todoapp.model.Stocks; + +import jakarta.transaction.Transactional; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * 在庫エンティティのリポジトリインターフェース + *

+ * このインターフェースは在庫データへのアクセスと操作を提供します。 + * Spring Data JPAによって自動的に実装されます。 + *

+ */ + +@Repository +public interface StocksRepository extends JpaRepository { + /** + * userIdから在庫一覧をstockId順で取得する + * + * @param userId 検索するユーザーID + * @return 在庫リスト + */ + List findStocksByUserId(Long userId); + + /** + * 在庫情報を更新する + * + * @param stock 編集する新たな情報が入ったstockオブジェクト + * @return 編集に成功したらtrue + */ + // boolean updateStocksByStockId(Stocks stock); + + //updateをクエリ作成にて実装 + + @Modifying + @Transactional + @Query("UPDATE Stocks s SET s.amount = :#{#stock.amount}, s.price = :#{#stock.price}, s.buyDate = :#{#stock.buyDate}, s.lastUpdate = :#{#stock.lastUpdate}, s.expDate = :#{#stock.expDate} WHERE s.stockId = :#{#stock.stockId}") + int updateStocksById(@Param("stock") Stocks stock); + + /** + * 在庫リストから指定した食材を削除する + * + * @param stockId 削除する在庫 + * @param userId 削除するユーザー + */ + // void deleteStocksByStockIdAndUserId(Long stockId, Long userId); + + @Modifying + @Transactional + @Query("DELETE FROM Stocks t WHERE t.user.id = :userId AND t.stockId = :stockId") + int deleteByUserIdAndStockId(@Param("userId") Long userId, @Param("stockId") Long stockId); +} \ No newline at end of file diff --git a/backend/src/main/java/com/example/todoapp/repository/StuffsRepository.java b/backend/src/main/java/com/example/todoapp/repository/StuffsRepository.java index 1e2fa69..f2fb344 100644 --- a/backend/src/main/java/com/example/todoapp/repository/StuffsRepository.java +++ b/backend/src/main/java/com/example/todoapp/repository/StuffsRepository.java @@ -2,13 +2,19 @@ // StuffsRepository.java // // -// 更新履歴:2025/06/05 新規作成 +// 更新履歴:2025/06/09 新規作成 // Copyright(c) 2025 IVIS All rights reserved. //-------------------------------------------- package com.example.todoapp.repository; import com.example.todoapp.model.Stuffs; + +import java.util.Optional; + +import java.util.List; + + import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -22,4 +28,17 @@ import org.springframework.stereotype.Repository; @Repository public interface StuffsRepository extends JpaRepository { // 材料情報を主キーで取得するメソッド(必要に応じて追加) + Stuffs findByStuffId(Long stuffId); + + + Optional findByStuffName(String stuffName); + + /** + * 指定されたカテゴリに属する材料のリストを取得するメソッド. + * + * @param category カテゴリ名 + * @return 指定されたカテゴリに属する材料のリスト + */ + List findByCategory(String category); + } \ No newline at end of file diff --git a/backend/src/main/java/com/example/todoapp/repository/ToBuysRepository.java b/backend/src/main/java/com/example/todoapp/repository/ToBuysRepository.java index 57cd2cb..f07f742 100644 --- a/backend/src/main/java/com/example/todoapp/repository/ToBuysRepository.java +++ b/backend/src/main/java/com/example/todoapp/repository/ToBuysRepository.java @@ -18,32 +18,40 @@ import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; /** - * to_buys テーブルへのアクセスを行うリポジトリ + * toBuys テーブルへのアクセスを行うリポジトリ *

- * このクラスは to_buys テーブルに対する基本的なCRUD操作を提供します。 + * このクラスは toBuys テーブルに対する基本的なCRUD操作を提供します。 * Spring Data JPAによって自動的に実装されます。 *

*/ @Repository public interface ToBuysRepository extends JpaRepository { + /** + * 指定されたIDに基づいて「買うもの」レコードを取得する + * + * @param tobuyId 「買うもの」ID + * @return 「買うもの」レコード + */ + @Query("SELECT t FROM ToBuys t WHERE t.tobuyId = ?1") + ToBuys findById(Long tobuyId); + /** * 指定されたユーザーIDに基づいて「買うもの」リストを取得する * * @param userId ユーザーID * @return 「買うもの」リスト */ - @Query("SELECT t FROM ToBuys t WHERE t.user_id.id = ?1") - List findByUserId(Long user_id); + @Query("SELECT t FROM ToBuys t WHERE t.user.id = ?1") + List findByUser(Long userId); /** - * 指定されたユーザーIDに基づいて「買うもの」リストを取得する + * 指定された「買うもの」IDに基づいて「買うもの」リストを削除 * - * @param userId ユーザーID * @param tobuyId 「買うもの」ID * @return */ @Modifying - @Query("DELETE FROM ToBuys t WHERE t.user_id.id = :userId AND t.tobuy_id = :tobuyId") - int deleteByUserIdAndTobuyId(@Param("userId") Long userId, @Param("tobuyId") int tobuyId); + @Query("DELETE FROM ToBuys t WHERE t.tobuyId = :tobuyId") + int deleteByTobuyId(@Param("tobuyId") Long tobuyId); } \ No newline at end of file diff --git a/backend/src/main/java/com/example/todoapp/service/StocksService.java b/backend/src/main/java/com/example/todoapp/service/StocksService.java new file mode 100644 index 0000000..ee37129 --- /dev/null +++ b/backend/src/main/java/com/example/todoapp/service/StocksService.java @@ -0,0 +1,112 @@ +package com.example.todoapp.service; + +import com.example.todoapp.dto.StockDTO; +import com.example.todoapp.model.Stocks; +import com.example.todoapp.util.MessageUtils; +import com.example.todoapp.model.User; +import com.example.todoapp.repository.StocksRepository; +import com.example.todoapp.repository.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * Stocksテーブルのサービスクラス + *

+ * このクラスは在庫の追加、取得、更新、削除などのビジネスロジックを提供します。 + *

+ */ +@Service +public class StocksService { + @Autowired + private StocksRepository stocksRepository; + + @Autowired + private UserRepository userRepository; + + @Autowired + private MessageUtils messageUtils; + + /** + * 新たな在庫を追加する + * + * @param username ユーザー名 + * @param stock 追加する在庫情報 + * @return 保存された在庫エンティティ + */ + public Stocks createStock(String username, Stocks stock) { + User user = getUserByUsername(username); + stock.setUser(user); + return stocksRepository.save(stock); + + } + + /** + * 指定されたユーザのすべての在庫を取得する + * @param username ユーザー名 + * @return ユーザーの在庫リスト(stockId昇順) + */ + public List getALLStocksByUser(String username) { + User user = getUserByUsername(username); + return stocksRepository.findStocksByUserId(user.getId()); + } + + /** + * 指定されたユーザーの特定の在庫を取得する + * + * @param username ユーザー名 + * @param stockId 在庫ID + * @return 在庫エンティティ + * @throws RuntimeException 在庫が見つからない場合、または他のユーザーの在庫にアクセスしようとした場合 + */ + public Stocks getStockById(String username, Long stockId) { + User user = getUserByUsername(username); + return stocksRepository.findById(stockId) + .filter(stock -> stock.getUser().equals(user)) // ユーザーの在庫かどうかを確認 + .orElseThrow(() -> new RuntimeException(messageUtils.getMessage("error.stock.not.found"))); + } + + /** + * 指定された在庫情報を編集する + * + * @param username ユーザー名 + * @param stockId 変数する在庫ID + * @param stockDetails 編集内容(新しい情報) + * @return 編集された在庫エンティティ + */ + public Stocks updateStocks(String username, StockDTO stockDto) { + Stocks stock = getStockById(username, stockDto.getStockId()); + stock.setAmount(stockDto.getAmount()); + stock.setPrice(stockDto.getPrice()); + stock.setLastUpdate(stockDto.getLastUpdate()); + stock.setBuyDate(stockDto.getBuyDate()); + stock.setExpDate(stockDto.getExpDate()); + return stocksRepository.save(stock); + } + + /** + * 指定された在庫を削除する + * + * @param userId ユーザー名 + * @param stockId 削除する在庫のID + */ + public int deleteStockById(Long userId, Long stockId) { + return stocksRepository.deleteByUserIdAndStockId(userId, stockId); + } + + + /** + * ユーザー名からユーザーエンティティを取得する + * + * @param username ユーザー名 + * @return ユーザーエンティティ + * @throws UsernameNotFoundException ユーザーが見つからない場合 + */ + private User getUserByUsername(String username) { + return userRepository.findByUsername(username) + .orElseThrow(() -> new UsernameNotFoundException(messageUtils.getMessage("error.auth.user.not.found.with.name", new Object[]{username}))); + } + +} diff --git a/backend/src/main/java/com/example/todoapp/service/StuffsService.java b/backend/src/main/java/com/example/todoapp/service/StuffsService.java new file mode 100644 index 0000000..18b3924 --- /dev/null +++ b/backend/src/main/java/com/example/todoapp/service/StuffsService.java @@ -0,0 +1,39 @@ +//-------------------------------- +// StuffsService.java +// +// +// 更新履歴:2025/06/09 新規作成 +// Copyright(c) 2025 IVIS All rights reserved. +//-------------------------------------------- +package com.example.todoapp.service; + +import com.example.todoapp.model.Stuffs; +import com.example.todoapp.repository.StuffsRepository; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 材料 (stuffs) のサービスクラス + * + * このクラスは、材料 (stuffs) に関するビジネスロジックを提供します。 + */ + +@Service +public class StuffsService { + + @Autowired + private StuffsRepository stuffsRepository; + + /** + * カテゴリ指定で材料を取得するメソッド + * + * @param category カテゴリ名 + * @return 指定されたカテゴリに属する材料のリスト + */ + public List getAllStuffsByCategory(String category) { + return stuffsRepository.findByCategory(category); + } +} diff --git a/backend/src/main/java/com/example/todoapp/service/ToBuysService.java b/backend/src/main/java/com/example/todoapp/service/ToBuysService.java index 3fcaee2..5cc9cde 100644 --- a/backend/src/main/java/com/example/todoapp/service/ToBuysService.java +++ b/backend/src/main/java/com/example/todoapp/service/ToBuysService.java @@ -8,10 +8,14 @@ package com.example.todoapp.service; +import com.example.todoapp.util.MessageUtils; +import com.example.todoapp.dto.BuyRequestDTO; import com.example.todoapp.dto.ToBuysDTO; +import com.example.todoapp.model.Stocks; import com.example.todoapp.model.Stuffs; import com.example.todoapp.model.ToBuys; import com.example.todoapp.model.User; +import com.example.todoapp.repository.StocksRepository; import com.example.todoapp.repository.StuffsRepository; import com.example.todoapp.repository.ToBuysRepository; import com.example.todoapp.repository.UserRepository; @@ -19,6 +23,7 @@ import com.example.todoapp.repository.UserRepository; import jakarta.transaction.Transactional; import org.springframework.security.core.Authentication; +import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -28,7 +33,7 @@ import java.util.Optional; /** * 購入リストのサービスクラス *

- * このクラスは、購入リスト (to_buys) の登録処理を提供します。 + * このクラスは、購入リスト (toBuys) の登録処理を提供します。 * 材料 (stuffs) の存在確認と新規作成、ユーザー情報の取得などを行います。 *

*/ @@ -44,6 +49,12 @@ public class ToBuysService { @Autowired private StuffsRepository stuffsRepository; + + @Autowired + private StocksRepository stocksRepository; + + @Autowired + private MessageUtils messageUtils; /** @@ -51,38 +62,38 @@ public class ToBuysService { * * @param toBuyDTO 追加する購入アイテムのデータ(DTO) */ - public void addToBuys(ToBuysDTO toBuyDTO, Authentication authentication) { + public ToBuys addToBuys(ToBuysDTO toBuyDTO, Authentication authentication) { // ユーザー情報を取得 String username = authentication.getName(); User user = userRepository.findByUsername(username) .orElseThrow(() -> new RuntimeException("ユーザーが見つかりません: " + username)); - Stuffs stuffs; - if (toBuyDTO.getStuff_id() == null) { + Stuffs stuff; + if (toBuyDTO.getStuffId() == null) { // 新しい材料を作成 - stuffs = new Stuffs(); - stuffs.setStuff_name(toBuyDTO.getStuff_name()); - stuffs.setCategory(toBuyDTO.getCategory()); - stuffs = stuffsRepository.save(stuffs); + stuff = new Stuffs(); + stuff.setStuffName(toBuyDTO.getStuffName()); + stuff.setCategory(toBuyDTO.getCategory()); + stuff = stuffsRepository.save(stuff); } else { // 材料情報を取得 - Optional optionalStuffs = stuffsRepository.findById(toBuyDTO.getStuff_id()); + Optional optionalStuffs = stuffsRepository.findById(toBuyDTO.getStuffId()); if (!optionalStuffs.isPresent()) { throw new RuntimeException("材料がありません"); } - stuffs = optionalStuffs.get(); + stuff = optionalStuffs.get(); } ToBuys toBuys = new ToBuys(); - toBuys.setUser_id(user); - toBuys.setStuffs(stuffs); + toBuys.setUser(user); + toBuys.setStuff(stuff); toBuys.setAmount(toBuyDTO.getAmount()); toBuys.setStore(toBuyDTO.getShop()); // データベースに保存 - toBuysRepository.save(toBuys); - + return toBuysRepository.save(toBuys); + } /** @@ -90,7 +101,7 @@ public class ToBuysService { * * @param toBuyDTO 変更する購入アイテムのデータ(DTO) */ - public void updateToBuys(ToBuysDTO toBuyDTO, Authentication authentication) { + public ToBuys updateToBuys(ToBuysDTO toBuyDTO, Authentication authentication) { // ユーザー情報を取得 String username = authentication.getName(); @@ -98,57 +109,106 @@ public class ToBuysService { .orElseThrow(() -> new RuntimeException("ユーザーが見つかりません: " + username)); Stuffs stuffs; - if (toBuyDTO.getStuff_id() == null) { + if (toBuyDTO.getStuffId() == null) { + + Optional existingStuffs = stuffsRepository.findByStuffName(toBuyDTO.getStuffName()); // 新しい材料を作成 - stuffs = new Stuffs(); - stuffs.setStuff_name(toBuyDTO.getStuff_name()); - stuffs.setCategory(toBuyDTO.getCategory()); - stuffs = stuffsRepository.save(stuffs); + if (existingStuffs.isPresent()) { + // 如果存在,更新已有材料的属性 + stuffs = existingStuffs.get(); + stuffs.setCategory(toBuyDTO.getCategory()); // 可选:更新分类 + } else { + // 否则新建材料 + stuffs = new Stuffs(); + stuffs.setStuffName(toBuyDTO.getStuffName()); + stuffs.setCategory(toBuyDTO.getCategory()); + } + stuffsRepository.save(stuffs); } else { // 材料情報を取得 - Optional optionalStuffs = stuffsRepository.findById(toBuyDTO.getStuff_id()); + Optional optionalStuffs = stuffsRepository.findById(toBuyDTO.getStuffId()); if (!optionalStuffs.isPresent()) { throw new RuntimeException("材料がありません"); } stuffs = optionalStuffs.get(); //update - // stuffs.setStuff_name(toBuyDTO.getStuff_name()); - // stuffs.setCategory(toBuyDTO.getCategory()); stuffs = stuffsRepository.save(stuffs); } - - ToBuys toBuys = new ToBuys(); - toBuys.setUser_id(user); - toBuys.setStuffs(stuffs); + toBuys.setTobuyId(toBuyDTO.getTobuyId()); + toBuys.setUser(user); + toBuys.setStuff(stuffs); toBuys.setAmount(toBuyDTO.getAmount()); toBuys.setStore(toBuyDTO.getShop()); // データベースに保存 - toBuysRepository.save(toBuys); - + return toBuysRepository.save(toBuys); } /** - * 指定されたユーザーIDに基づいてすべての「買うもの」リストを取得する + * 指定されたユーザーに基づいてすべての「買うもの」リストを取得する * - * @param userId ユーザーID + * @param user ユーザー * @return ユーザーに紐づく「買うもの」リスト */ - public List getToBuysByUserId(Long userId) { - return toBuysRepository.findByUserId(userId); + public List getToBuysByUser(User user) { + return toBuysRepository.findByUser(user.getId()); } /** - * 指定されたユーザーIDと購入リストIDに基づいて「買うもの」を削除する + * 指定された購入リストIDに基づいて「買うもの」を削除する * - * @param userId ユーザーID * @param tobuyId 購入リストID */ @Transactional - public int deleteToBuyByIds(Long userId, int tobuyId) { - return toBuysRepository.deleteByUserIdAndTobuyId(userId, tobuyId); + public int deleteToBuyById(Long tobuyId) { + return toBuysRepository.deleteByTobuyId(tobuyId); + } + + /** + * 指定されたユーザーIDと購入データに基づいて「買うもの」を購入する + * + * @param username ユーザーID + * @param dto 購入データ + */ + @Transactional + public Stocks buyToBuys(String username, BuyRequestDTO dto) { + // ユーザー情報を取得 + User user = getUserByUsername(username); + + // Tobuy情報の取得 + ToBuys tobuy = toBuysRepository.findById(dto.getTobuyId()); + + // 新しい在庫を作成 + Stocks stock = new Stocks(); + stock.setStuff(tobuy.getStuff()); + stock.setUser(user); + stock.setAmount(tobuy.getAmount()); + stock.setPrice(dto.getPrice()); + stock.setLastUpdate(dto.getLastUpdate()); + stock.setBuyDate(dto.getBuyDate()); + stock.setExpDate(dto.getExpDate()); + + // 買うものリストから削除 + System.out.println("tobuy.getTobuyId()=" + tobuy.getTobuyId()); + deleteToBuyById(tobuy.getTobuyId()); + + // データベースに保存 + return stocksRepository.save(stock); } + + /** + * ユーザー名からユーザーエンティティを取得する + * + * @param username ユーザー名 + * @return ユーザーエンティティ + * @throws UsernameNotFoundException ユーザーが見つからない場合 + */ + private User getUserByUsername(String username) { + return userRepository.findByUsername(username) + .orElseThrow(() -> new UsernameNotFoundException(messageUtils.getMessage("error.auth.user.not.found.with.name", new Object[]{username}))); + } + } \ No newline at end of file diff --git a/frontend/src/constants/errorMessages.ts b/frontend/src/constants/errorMessages.ts index 909bbfa..0aa0f98 100644 --- a/frontend/src/constants/errorMessages.ts +++ b/frontend/src/constants/errorMessages.ts @@ -14,18 +14,37 @@ export const AUTH_ERRORS = { REGISTER_FAILED: 'ユーザー登録に失敗しました', }; -// タスク関連のエラーメッセージ -export const TASK_ERRORS = { - FETCH_FAILED: 'タスクの取得に失敗しました', - CREATE_FAILED: 'タスクの作成に失敗しました', - UPDATE_FAILED: 'タスクの更新に失敗しました', - DELETE_FAILED: 'タスクの削除に失敗しました', -}; - // 買うものリスト関連のエラーメッセージ export const TOBUY_ERRORS = { FETCH_FAILED: '買うものリストの取得に失敗しました', CREATE_FAILED: '買うものリストの作成に失敗しました', UPDATE_FAILED: '買うものリストの更新に失敗しました', DELETE_FAILED: '買うものリストの削除に失敗しました', + BUY_FAILED: '買うものリストの購入処理に失敗しました', +}; + +// 材料リスト関連のエラーメッセージ(料理の追加編集で用いる) +export const STUFF_ERRORS = { + FETCH_FAILED: '材料リストの取得に失敗しました', + CREATE_FAILED: '材料リストの作成に失敗しました', + UPDATE_FAILED: '材料リストの更新に失敗しました', + DELETE_FAILED: '材料リストの削除に失敗しました', + BUY_FAILED: '材料リストの購入処理に失敗しました', }; + +// 在庫リスト関連のエラーメッセージ +export const STOCK_ERRORS = { + FETCH_FAILED: '在庫リストの取得に失敗しました', + CREATE_FAILED: '在庫リストの作成に失敗しました', + UPDATE_FAILED: '在庫リストの更新に失敗しました', + DELETE_FAILED: '在庫リストの削除に失敗しました', + BUY_FAILED: '在庫リストの購入処理に失敗しました', +}; + +// // タスク関連のエラーメッセージ +// export const TASK_ERRORS = { +// FETCH_FAILED: 'タスクの取得に失敗しました', +// CREATE_FAILED: 'タスクの作成に失敗しました', +// UPDATE_FAILED: 'タスクの更新に失敗しました', +// DELETE_FAILED: 'タスクの削除に失敗しました', +// }; \ No newline at end of file diff --git a/frontend/src/pages/AddDishes1.tsx b/frontend/src/pages/AddDishes1.tsx index d003ebd..5c28373 100644 --- a/frontend/src/pages/AddDishes1.tsx +++ b/frontend/src/pages/AddDishes1.tsx @@ -60,7 +60,7 @@ const AddDishes1: React.FC = () => { InputLabelProps={{ style: { fontSize: "40px" }}} style={{width: "80%" }} InputProps={{ style: { fontSize: "40px"} }} - name="dish_name" + name="dishName" // autoComplete="username" autoFocus value={dish} diff --git a/frontend/src/pages/AddDishes2.tsx b/frontend/src/pages/AddDishes2.tsx index d8aa62c..123f8b7 100644 --- a/frontend/src/pages/AddDishes2.tsx +++ b/frontend/src/pages/AddDishes2.tsx @@ -3,7 +3,7 @@ * 白紙の状態で表示されるテスト用のページ */ import React, { useState, useEffect } from 'react'; -import { taskApi, toBuyApi } from '../services/api'; +import { toBuyApi } from '../services/api'; import { Container, Typography, @@ -31,8 +31,7 @@ import { Add as AddIcon, Delete as DeleteIcon, ShoppingBasket as ShoppingBasketIcon, SoupKitchen as SoupKitchenIcon } from '@mui/icons-material'; -import { Task } from '../types/types'; -import { TASK_ERRORS } from '../constants/errorMessages'; +import { STUFF_ERRORS } from '../constants/errorMessages'; import { GENERAL_ERRORS } from '../constants/errorMessages'; import CategoryDropDown from "../components/CategoryDropDown"; @@ -42,7 +41,7 @@ const EMPTY_TASK = { id: 0, title: '', amount: 0, completed: false }; // 新規タスクの初期状態(データベース登録用) const EMPTY_TASK_DATA_BASE = { id: 0, title: '', amount: 0, completed: false }; -interface Empty_Task { +interface Stuff { title: string; // 食材名 amount: number; // 食材の個数 completed: boolean; // @@ -51,9 +50,9 @@ interface Empty_Task { const AddDishes2: React.FC = () => { const receivedData = localStorage.getItem("dishName"); // タスク一覧の状態管理 - const [tasks, setTasks] = useState([]); + const [tasks, setTasks] = useState([]); - const [addtasks, setAddTasks] = useState([]); + const [addtasks, setAddTasks] = useState([]); // エラーメッセージの状態管理 const [error, setError] = useState(false); // 新規タスク作成ダイアログの表示状態 @@ -61,23 +60,23 @@ const AddDishes2: React.FC = () => { // 新規タスクの入力内容 const [newTask, setNewTask] = useState(EMPTY_TASK); - // コンポーネントマウント時にタスク一覧を取得 - useEffect(() => { - fetchTasks(); - }, []); + // // コンポーネントマウント時にタスク一覧を取得 + // useEffect(() => { + // fetchTasks(); + // }, []); - /** - * APIからタスク一覧を取得する関数 - * 取得したタスクをstate(tasks)に設定 - */ - const fetchTasks = async () => { - try { - const tasks = await taskApi.getTasks(); - setTasks(tasks); - } catch (error) { - console.error(`${TASK_ERRORS.FETCH_FAILED}:`, error); - } - }; + // /** + // * APIからタスク一覧を取得する関数 + // * 取得したタスクをstate(tasks)に設定 + // */ + // const fetchTasks = async () => { + // try { + // const tasks = await taskApi.getTasks(); + // setTasks(tasks); + // } catch (error) { + // console.error(`${TASK_ERRORS.FETCH_FAILED}:`, error); + // } + // }; /** * タスクを削除するハンドラー * 指定されたIDのタスクをAPIを通じて削除 @@ -89,7 +88,7 @@ const AddDishes2: React.FC = () => { setAddTasks(newAddTasks); // fetchTasks(); // 削除後のタスク一覧を再取得 } catch (error) { - console.error(`${TASK_ERRORS.DELETE_FAILED}:`, error); + console.error(`${STUFF_ERRORS.DELETE_FAILED}:`, error); } }; @@ -120,7 +119,7 @@ const AddDishes2: React.FC = () => { setNewTask(EMPTY_TASK); // 入力内容をリセット // fetchTasks(); // 作成後のタスク一覧を再取得 } catch (error) { - console.error(`${TASK_ERRORS.CREATE_FAILED}:`, error); + console.error(`${STUFF_ERRORS.CREATE_FAILED}:`, error); } }; @@ -134,7 +133,7 @@ const AddDishes2: React.FC = () => { setNewTask(EMPTY_TASK); // 入力内容をリセット // fetchTasks(); // 作成後のタスク一覧を再取得 } catch (error) { - console.error(`${TASK_ERRORS.CREATE_FAILED}:`, error); + console.error(`${STUFF_ERRORS.CREATE_FAILED}:`, error); } }; diff --git a/frontend/src/pages/StockPage.tsx b/frontend/src/pages/StockPage.tsx index ecf3059..896bc2d 100644 --- a/frontend/src/pages/StockPage.tsx +++ b/frontend/src/pages/StockPage.tsx @@ -20,7 +20,7 @@ import { Box, } from '@mui/material'; -import { TASK_ERRORS } from '../constants/errorMessages'; +import { STOCK_ERRORS } from '../constants/errorMessages'; const StockPage: React.FC = () => { @@ -47,9 +47,10 @@ const StockPage: React.FC = () => { const fetchStocks = async () => { try { const stocks = await stockApi.getStocks(); - setStocks(stocks.stock_array); + console.log('Stocks=', stocks) + setStocks(stocks); } catch (error) { - console.error(`${TASK_ERRORS.FETCH_FAILED}:`, error); + console.error(`${STOCK_ERRORS.FETCH_FAILED}:`, error); } }; @@ -139,14 +140,14 @@ const StockPage: React.FC = () => { .filter(stock => stock.category == "乳製品") // 乳製品だけ抽出 .map(stock => ( handleRowClick(stock.stock_id)} - style={{ backgroundColor: selectedRow === stock.stock_id ? "yellow" : "white", cursor: "pointer" }}> - {stock.stuff_name} + key={stock.stockId} + onClick={() => handleRowClick(stock.stockId)} + style={{ backgroundColor: selectedRow === stock.stockId ? "yellow" : "white", cursor: "pointer" }}> + {stock.stuffName} {stock.amount} {stock.price} - {formatDate(stock.exp_date)} - {formatDate(stock.buy_date)} + {formatDate(stock.expDate)} + {formatDate(stock.buyDate)} ))} @@ -156,12 +157,12 @@ const StockPage: React.FC = () => { - 肉・魚 + 魚・肉 - {/* 肉・魚一覧表示エリア - 青い背景のコンテナ */} + {/* 魚・肉一覧表示エリア - 青い背景のコンテナ */}
- {stocks.filter(stock => stock.category == "肉" || stock.category == "魚").length === 0 ? null : ( + {stocks.filter(stock => stock.category == "魚・肉").length === 0 ? null : ( @@ -175,17 +176,17 @@ const StockPage: React.FC = () => { {stocks - .filter(stock => stock.category == "肉" || stock.category == "魚") // 肉と魚だけ抽出 + .filter(stock => stock.category == "魚・肉") // 「魚・肉」だけ抽出 .map(stock => ( handleRowClick(stock.stock_id)} - style={{ backgroundColor: selectedRow === stock.stock_id ? "yellow" : "white", cursor: "pointer" }}> - {stock.stuff_name} + key={stock.stockId} + onClick={() => handleRowClick(stock.stockId)} + style={{ backgroundColor: selectedRow === stock.stockId ? "yellow" : "white", cursor: "pointer" }}> + {stock.stuffName} {stock.amount} {stock.price} - {formatDate(stock.exp_date)} - {formatDate(stock.buy_date)} + {formatDate(stock.expDate)} + {formatDate(stock.buyDate)} ))} @@ -217,14 +218,14 @@ const StockPage: React.FC = () => { .filter(stock => stock.category == "野菜") // 野菜だけ抽出 .map(stock => ( handleRowClick(stock.stock_id)} - style={{ backgroundColor: selectedRow === stock.stock_id ? "yellow" : "white", cursor: "pointer" }}> - {stock.stuff_name} + key={stock.stockId} + onClick={() => handleRowClick(stock.stockId)} + style={{ backgroundColor: selectedRow === stock.stockId ? "yellow" : "white", cursor: "pointer" }}> + {stock.stuffName} {stock.amount} {stock.price} - {formatDate(stock.exp_date)} - {formatDate(stock.buy_date)} + {formatDate(stock.expDate)} + {formatDate(stock.buyDate)} ))} @@ -255,14 +256,14 @@ const StockPage: React.FC = () => { .filter(stock => stock.category == "調味料") // 調味料だけ抽出 .map(stock => ( handleRowClick(stock.stock_id)} - style={{ backgroundColor: selectedRow === stock.stock_id ? "yellow" : "white", cursor: "pointer" }}> - {stock.stuff_name} + key={stock.stockId} + onClick={() => handleRowClick(stock.stockId)} + style={{ backgroundColor: selectedRow === stock.stockId ? "yellow" : "white", cursor: "pointer" }}> + {stock.stuffName} {stock.amount} {stock.price} - {formatDate(stock.exp_date)} - {formatDate(stock.buy_date)} + {formatDate(stock.expDate)} + {formatDate(stock.buyDate)} ))} @@ -293,14 +294,14 @@ const StockPage: React.FC = () => { .filter(stock => stock.category == "その他") // その他だけ抽出 .map(stock => ( handleRowClick(stock.stock_id)} - style={{ backgroundColor: selectedRow === stock.stock_id ? "yellow" : "white", cursor: "pointer" }}> - {stock.stuff_name} + key={stock.stockId} + onClick={() => handleRowClick(stock.stockId)} + style={{ backgroundColor: selectedRow === stock.stockId ? "yellow" : "white", cursor: "pointer" }}> + {stock.stuffName} {stock.amount} {stock.price} - {formatDate(stock.exp_date)} - {formatDate(stock.buy_date)} + {formatDate(stock.expDate)} + {formatDate(stock.buyDate)} ))} diff --git a/frontend/src/pages/TaskListPage.tsx b/frontend/src/pages/TaskListPage.tsx index cc97ec7..ae7eeef 100644 --- a/frontend/src/pages/TaskListPage.tsx +++ b/frontend/src/pages/TaskListPage.tsx @@ -33,22 +33,28 @@ import { Add as AddIcon, Delete as DeleteIcon, ShoppingBasket as ShoppingBasketIcon, SoupKitchen as SoupKitchenIcon } from '@mui/icons-material'; -import { Task, ToBuy, Stuff } from '../types/types'; -import { TASK_ERRORS } from '../constants/errorMessages'; +import { ToBuy, Stuff, Stock } from '../types/types'; +import { TOBUY_ERRORS } from '../constants/errorMessages'; //import { FaCarrot } from "react-icons/fa6"; //エラー起きる いったん保留 // 新規タスクの初期状態 -const EMPTY_TASK: Omit & { stuff_id: number | null, category: string } & { newAddition: boolean } = { - stuff_id: null, - stuff_name: '', +const EMPTY_TOBUY: Omit & { stuffId: number | null, category: string } & { newAddition: boolean } = { + stuffId: null, + stuffName: '', amount: 0, shop: '', category: '', newAddition: false, } +const EMPTY_STOCK = { + price: 0, + buyDate: '', + expDate: '', +} + const TaskListPage: React.FC = () => { // タスク一覧の状態管理 const [tobuys, setToBuys] = useState([]); @@ -58,12 +64,14 @@ const TaskListPage: React.FC = () => { //在庫登録ダイアログの表示状態 const [openInfoDialog, setOpenInfoDialog] = useState(false); - const [selectedTask, setSelectedTask] = useState(0); + const [selectedTask, setSelectedTask] = useState(0); - const [newToBuy, setNewToBuy] = useState(EMPTY_TASK); + const [newToBuy, setNewToBuy] = useState(EMPTY_TOBUY); const [stuffs, setStuffs] = useState([]); + const [newStock, setNewStock] = useState(EMPTY_STOCK); + // コンポーネントマウント時にタスク一覧を取得 useEffect(() => { @@ -77,16 +85,16 @@ const TaskListPage: React.FC = () => { const fetchTasks = async () => { try { const tobuys = await toBuyApi.getToBuys(); - setToBuys(tobuys.tobuy_array); + setToBuys(tobuys); } catch (error) { - console.error(`${TASK_ERRORS.FETCH_FAILED}:`, error); + console.error(`${TOBUY_ERRORS.FETCH_FAILED}:`, error); } }; const onChangeCategory = async (category: string) => { setNewToBuy({ ...newToBuy, category }) const result = await stuffApi.getStuffs(category) - setStuffs(result.stuff_array) + setStuffs(result) } // /** @@ -112,9 +120,22 @@ const TaskListPage: React.FC = () => { const handleDeleteTask = async (toBuyId: number) => { try { await toBuyApi.deleteToBuy(toBuyId); - fetchTasks(); // 削除後のタスク一覧を再取得 + fetchTasks(); // 削除後の買うもの一覧を再取得 + } catch (error) { + console.error(`${TOBUY_ERRORS.DELETE_FAILED}:`, error); + } + }; + + /** + * 買うものリストの在庫登録(購入処理)を行うハンドラー + */ + const handleBuy = async (tobuyId: number) => { + try { + const today = new Date().toISOString().substring(0, 10); + await toBuyApi.buy({tobuyId, ...newStock, lastUpdate: today}); + fetchTasks(); // 削除後の買うもの一覧を再取得 } catch (error) { - console.error(`${TASK_ERRORS.DELETE_FAILED}:`, error); + console.error(`${TOBUY_ERRORS.BUY_FAILED}:`, error); } }; @@ -126,15 +147,15 @@ const TaskListPage: React.FC = () => { const handleCreateTask = async () => { try { if (newToBuy.newAddition) { - newToBuy.stuff_id = null; + newToBuy.stuffId = null; } console.log(newToBuy) await toBuyApi.addToBuy(newToBuy); setOpenDialog(false); // ダイアログを閉じる - setNewToBuy(EMPTY_TASK); // 入力内容をリセット + setNewToBuy(EMPTY_TOBUY); // 入力内容をリセット fetchTasks(); // 作成後のタスク一覧を再取得 } catch (error) { - console.error(`${TASK_ERRORS.CREATE_FAILED}:`, error); + console.error(`${TOBUY_ERRORS.CREATE_FAILED}:`, error); } }; @@ -149,7 +170,7 @@ const TaskListPage: React.FC = () => { {/* タスク一覧をマップして各タスクをリストアイテムとして表示 */} {tobuys && tobuys.map((tobuy) => ( { */} {/* タスクのタイトルと説明 - 完了状態に応じて取り消し線を表示 */} { aria-label="食材情報追加" onClick={() => { setOpenInfoDialog(true) - setSelectedTask(tobuy.tobuy_id) - // handleDeleteTask(tobuy.tobuy_id) + setSelectedTask(tobuy.tobuyId) + // handleDeleteTask(tobuy.tobuyId) }} > @@ -205,7 +226,7 @@ const TaskListPage: React.FC = () => { handleDeleteTask(tobuy.tobuy_id)} + onClick={() => handleDeleteTask(tobuy.tobuyId)} > @@ -273,12 +294,12 @@ const TaskListPage: React.FC = () => { 材料名(選択) @@ -290,8 +311,8 @@ const TaskListPage: React.FC = () => { margin="dense" label="材料名" fullWidth - value={newToBuy.stuff_name} - onChange={(e) => setNewToBuy({ ...newToBuy, stuff_name: e.target.value })} + value={newToBuy.stuffName} + onChange={(e) => setNewToBuy({ ...newToBuy, stuffName: e.target.value })} sx={{ marginBottom: 2 }} />} {/* 数量入力フィールド */} @@ -333,6 +354,8 @@ const TaskListPage: React.FC = () => { margin="dense" label="価格" fullWidth + value={newStock.price} + onChange={(e) => setNewStock({...newStock, price: parseInt(e.target.value)})} /> {/* 消費・賞味期限入力フィールド */} { label="消費・賞味期限(yyyy/MM/dd)" fullWidth multiline + value={newStock.expDate} + onChange={(e) => setNewStock({...newStock, expDate: e.target.value})} /> {/* 購入日入力フィールド */} { label="購入日(yyyy/MM/dd)" fullWidth multiline + value={newStock.buyDate} + onChange={(e) => setNewStock({...newStock, buyDate: e.target.value})} /> @@ -354,9 +381,9 @@ const TaskListPage: React.FC = () => {