2019.04.15
今回もWEBアプリ作成の続きをしていこうと思います。
前回は本の注文ページを作りました。 今回は簡単な納品画面とその処理を実装します。
まずは新しいテーブル(エンティティのクラス)を定義します。
定義するテーブルは納品日や納品数、注文番号などのデータを格納するためのものです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | @Entity @Table(name="deliverydata") public class DeliveryData { @Id @Column @GeneratedValue(strategy = GenerationType.AUTO) private long id; @Column(nullable = true) private long orderId; @Column(length = 40, nullable = true) private String deliveryDate; private int numOfDelivery; @Column private String receiver; } |
以下がテンプレートです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | <!DOCTYPE html> <html xmln:th="http://www.thymeleaf.org"> <head> <meta http-equiv="Content-Type" charset="UTF-8" /> <title>TRANSONIC書店 在庫管理システム</title> <style> body { font-size:13pt; margin:5px 25px; } </style> </head> <body> <h2>納品</h2> <div class="box"> <table th:object="${book}"> <tr><th align="left" width="150">・ISBN :</th><td width="400" th:text="*{isbn}">XXXX</td></tr> <tr><th align="left">・タイトル :</th><td th:text="*{title}">XXXX</td></tr> <tr><th align="left">・単価 :</th><td th:text="*{unitPrice}">XXXX</td></tr> </table> </div> <br /> <table border="1"> <tr><th></th><th>【注文】</th><th>【納品】</th></tr> <tr><td width="150">・個数</td> <td align="right" width="200" th:text="${orderdata.numOfOrder}">XX</td> <td align="right" width="200" th:text="${delidata}? ${delidata.numOfDelivery} : ' '">XX</td></tr> <tr><td>・日付</td> <td align="right" th:text="${orderdata.orderDate}"></td> <td align="right" th:text="${delidata}? ${delidata.deliveryDate} : ' '"></td></tr> </table> <br /> <form method="post" action="/delivery"> <table> <tr><th>・納品数 : </th><td><input type="number" value="1" name="numOfDelivery" min="1" max="100" required /></td></tr> <tr><th>・納品日 : </th><td><input type="date" name="deliveryDate" required></td></tr> <tr><th>・受入者 : </th><td><input type="text" name="receiver" required></td></tr> </table> <input type="hidden" name="oid" th:value="${orderdata.orderId}" /> <input type="submit" name="submit" value="登録" /> </form> <a href="/"><button type="button">戻る</button></a> <h3>デバッグ用 - 納品マスタ</h3> <table width="470"> <tr><th>ID</th><th>注文番号</th><th>納品日</th><th>納品数</th><th>受入者</th></tr> <tr th:each="obj : ${vlist}"> <td align="center" th:text="${obj.id}"></td> <td align="center" th:text="${obj.orderId}"></td> <td align="center" th:text="${obj.deliveryDate}"></td> <td align="center" th:text="${obj.numOfDelivery}"></td> <td align="center" th:text="${obj.receiver}"></td> </tr> </table> </body> </html> |
主に①本の詳細を表示する部分②注文個数と日付、納品個数と日付③納品された際に入力するフォーム④デバッグ用に用意した納品データを表示する部分に分かれます。
27行目ですが、注文した商品は初めて納品するまではレコードは追加されないため、NULL処理をしています。
1 | <td align="right" th:text="${delidata}? ${delidata.deliveryDate} : ' '"></td></tr> |
このように記述することで、delidataがnullであれば空文字を挿入し、nullでなければデータを表示します。抽象的にすると以下のようになります。
1 | th:text=" 条件式 ? 真の場合の値 : 偽の場合の値" |
続いて以下のようにindex.htmlを修正します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | <!DOCTYPE html> <html xmlns:th="http://www.themeleaf.org"> <head> <title>TRANSONIC書店 在庫管理システム</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <link rel="stylesheet" media="all" th:href="@{/css/index.css}"/> </head> <body> <h2>在庫管理</h2> <div class="box"> <p>条件を記入してください</p> <form method="post" action="/" th:object="${formModel}"> <p><label for="genre">ジャンル:</label> <select name="genre"> <option selected th:text="*{genre}"></option> <option value="文学">文学</option> <option value="推理">推理</option> <option value="エッセイ">エッセイ</option> <option value="プログラミング">プログラミング</option> </select></p> <p><label for="isbn">ISBN: </label><input type="search" name="isbn" th:value="*{isbn}" /></p> <p><label for="author">著者 : </label><input type="search" name="author" th:value="*{author}" /></p> <p><label for="title">タイトル: </label><input type="search" name="title" th:value="*{title}" /></p> <input type="submit" name="submit" value="検索" /> </form> <a href="/"><button type="button">全データ表示</button></a> </div> <hr /> <table> <tr><th>ISBN番号</th><th>タイトル</th><th>著者名</th><th>在庫数</th><th>注文状態</th><th>注文日</th><th>注文</th><th>納品</th></tr> <tr th:each="obj : ${booklist}"> <td align="center"><a href="/detail" th:href="@{/detail/{isbn}(isbn=${obj.isbn})}" th:text="${obj.isbn}" ></a></td> <td align="left" th:text="${obj.title}"></td> <td align="left" th:text="${obj.author}"></td> <td align="center" th:text="${obj.stock}"></td> <td align="center" th:text="${obj.genre}"></td> <td align="center" ></td> <td align="center" ><a href="/order" th:href="@{/order/{isbn}(isbn=${obj.isbn})}">●</a></td> <td align="center" ><a href="/delivery" th:href="@{/delivery/{isbn}/(isbn=${obj.isbn})}">●</a></td> </tr> </table> </body> </html> |
主に変更されたのは41行目ですね、isbnをリクエストパラメータとして送り、動的なリンク先を生成しています。
DeliveryData用のRepositoryを作成します。 以下がRepositoryとなります。
1 2 3 4 | @Repository public interface DeliveryDataRepository extends JpaRepository<DeliveryData, Long> { public DeliveryData findByOrderId(long id); } |
では前回使用したStockControllerの中に以下を追加してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | @RequestMapping(value="/delivery/{isbn}", method = RequestMethod.GET) public ModelAndView deliveryDisp(@PathVariable("isbn") String isbn, ModelAndView mav) { mav.setViewName("delivery"); /* ISBNに一致する本のデータを取得 */ Optional bdata = bRepository.findByIsbn(isbn); /* ISBNに一致する注文データを取得 */ OrderData odata = oRepository.findByIsbn(isbn); /* 注文番号から納品データを取得 */ DeliveryData dvdata = dvRepository.findByOrderId(odata.getOrderId()); /* 各データをModelAndViewオブジェクトにセット */ mav.addObject("book", bdata.get()); mav.addObject("orderdata",odata); mav.addObject("delidata",dvdata); /* 全納品データをModelAndViewオブジェクトに格納 */ Iterable list = dvRepository.findAll(); mav.addObject("vlist",list); return mav; } @RequestMapping(value="/delivery", method = RequestMethod.POST) public ModelAndView deliveryRegist(@ModelAttribute DeliveryData formData, @RequestParam("oid") long orderId, ModelAndView mav) { mav.setViewName("delivery"); DeliveryData dvdata = dvRepository.findByOrderId(orderId); /* 商品の納品が初めての場合データを保存 */ if(dvdata == null) { formData.setOrderId(orderId); dvRepository.saveAndFlush(formData); /* 一度でも納品されていればデータを更新 */ } else { OrderData orderData = oRepository.findByOrderId(orderId); /* 前回までの納品数 + 今回の納品数 */ int receiveSum = dvdata.getNumOfDelivery() + formData.getNumOfDelivery(); /* データをセット */ dvdata.setDeliveryDate(formData.getDeliveryDate()); dvdata.setNumOfDelivery(receiveSum); dvdata.setReceiver(formData.getReceiver()); /* 納品数と注文数が一致した場合フラグをたてる */ if(receiveSum == orderData.getNumOfOrder()) orderData.setReceiptFlg(true); dvRepository.saveAndFlush(dvdata); } return new ModelAndView("redirect:/"); } |
GETリクエストのハンドラについては必要なデータをそれぞれ取得しているだけです。
POSTリクエストのハンドラですが、注文した商品に対して一度でも納品がされているか否かで処理をわけています。
ここらへんの処理は全てリクエストハンドラの中に記述するのではなく(あくまでもコントローラー内のメソッドであるため)、
Serviceというクラスを作りそこにロジックをかいたほうが良い気がします。そちらについても追々記事として上げようと思います。
では実際に動かしましょう。
トップ画面に納品ページのリンクが出ましたね。ここでは注文はすでにしてあるものとして進めます。
納品のリンクをクリックすると画面がでました。
数量を5で登録してみましょう。
ちゃんと表示されていますね。
では25個登録してみましょう。
しっかり表示されました。