読者です 読者をやめる 読者になる 読者になる

かんがるーさんの日記

最近自分が興味をもったものを調べた時の手順等を書いています。今は Spring Boot をいじっています。

Spring Boot で書籍の貸出状況確認・貸出申請する Web アプリケーションを作る ( その44 )( 貸出承認画面の作成4 )

概要

Spring Boot で書籍の貸出状況確認・貸出申請する Web アプリケーションを作る ( その43 )( 貸出承認画面の作成3 ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • 貸出承認画面の作成
      • 「確定」ボタンをクリックした時の処理の実装。
      • 2回目の更新処理&メール送信処理を実装します。

参照したサイト・書籍

  1. Velocity - User Guide
    https://velocity.apache.org/engine/releases/velocity-1.7/user-guide.html

    • メールの中に書籍名と承認・却下の結果を出力するための Velocity のテンプレートでの記述方法を調べた時に参照しました。

目次

  1. LendingBookDao インターフェースの変更
  2. Mail003Helper クラスの作成
  3. LendingapprovalService クラスの変更
  4. LendingapprovalController クラスの変更
  5. lendingapproval.html の変更
  6. 動作確認
  7. 次回は。。。

手順

LendingBookDao インターフェースの変更

  1. lending_book テーブルの approval_result, approval_reason だけを更新するメソッドを作成します。src/main/java/ksbysample/webapp/lending/dao の下の LendingBookDao.javaリンク先の内容 に変更します。

Mail003Helper クラスの作成

  1. src/main/java/ksbysample/webapp/lending/helper/mail の下に Mail003Helper.java を作成します。作成後、リンク先の内容 に変更します。

  2. src/main/resources/templates/mail の下に mail003-body.vm を作成します。作成後、リンク先の内容 に変更します。

LendingapprovalService クラスの変更

  1. 更新処理を実装します。src/main/java/ksbysample/webapp/lending/web/lendingapproval の下の LendingapprovalService.javaリンク先の内容 に変更します。

LendingapprovalController クラスの変更

  1. src/main/java/ksbysample/webapp/lending/web/lendingapproval の下の LendingapprovalController.javaリンク先の内容 に変更します。

lendingapproval.html の変更

  1. src/main/resources/templates/lendingapproval の下の lendingapproval.html を リンク先の内容 に変更します。

動作確認

  1. 動作確認します。データは以下の状態です。

    f:id:ksby:20160117125516p:plain

  2. メールを受信するので smtp4dev が起動していない場合には起動します。

  3. Gradle projects View から bootRun タスクを実行して Tomcat を起動します。

  4. ブラウザを起動し http://localhost:8080/lendingapproval?lendingAppId=105 へアクセスします。最初はログイン画面が表示されますので ID に "tanaka.taro@sample.com"、Password に "taro" を入力して、「次回から自動的にログインする」をチェックせずに「ログイン」ボタンをクリックします。

    貸出承認画面が表示されます。

    f:id:ksby:20160117125705p:plain

  5. まずは全て「承認」を選択した後「確定」ボタンをクリックしてみます。

    f:id:ksby:20160117130026p:plain

  6. 画面は貸出承認画面のままですが、画面上部に「確定しました」のメッセージが表示され、「承認/却下」「却下理由」欄は表示状態になりました。

    f:id:ksby:20160117130201p:plain

    DB のデータも正常に更新されていることが確認できます。

    f:id:ksby:20160117133247p:plain

    smtp4dev にもメールが送信されており、

    f:id:ksby:20160117130427p:plain

    受信したメールを表示すると承認対象の書籍一覧と、「承認/却下」欄が全て承認で表示されていることが確認できます。

    f:id:ksby:20160117130538p:plain

  7. データを version カラム以外は元の状態に戻します。

  8. 今度は全て「却下」を選択して「却下理由」を入力した後「確定」ボタンをクリックしてみます。

    f:id:ksby:20160117131626p:plain

  9. 画面上部に「確定しました」のメッセージが表示され、「承認/却下」「却下理由」欄は表示状態になりました。

    f:id:ksby:20160117131752p:plain

    DB のデータも正常に更新されていることが確認できます。

    f:id:ksby:20160117133824p:plain

    smtp4dev にもメールが送信されており、

    f:id:ksby:20160117134147p:plain

    受信したメールを表示すると承認対象の書籍一覧と、「承認/却下」欄が全て却下で表示されていることが確認できます。

    f:id:ksby:20160117134312p:plain

  10. Ctrl+F2 を押して Tomcat を停止します。

  11. 一旦 commit します。

次回は。。。

承認権限 ( ROLE_APPROVER ) を付与されていないユーザが /lendingapproval にアクセスした場合にはエラーにする処理を実装します。

ソースコード

LendingBookDao.java

package ksbysample.webapp.lending.dao;

import ksbysample.webapp.lending.entity.LendingBook;
import ksbysample.webapp.lending.util.doma.ComponentAndAutowiredDomaConfig;
import org.seasar.doma.Dao;
import org.seasar.doma.Delete;
import org.seasar.doma.Insert;
import org.seasar.doma.Select;
import org.seasar.doma.Update;
import org.seasar.doma.jdbc.SelectOptions;

import java.util.List;

/**
 */
@Dao
@ComponentAndAutowiredDomaConfig
public interface LendingBookDao {

    /**
     * @param lendingBookId
     * @return the LendingBook entity
     */
    @Select
    LendingBook selectById(Long lendingBookId);
    @Select(ensureResult = true)
    LendingBook selectByIdAndVersion(Long lendingBookId, Long version);
    @Select
    List<LendingBook> selectByLendingAppId(Long lendingAppId);
    @Select
    List<LendingBook> selectByLendingAppId(Long lendingAppId, SelectOptions options);
    @Select
    List<LendingBook> selectByLendingAppIdAndLendingAppFlg(Long lendingAppId, String lendingAppFlg);
    @Select
    List<LendingBook> selectByLendingAppIdAndLendingAppFlg(Long lendingAppId, String lendingAppFlg, SelectOptions options);
    
    /**
     * @param entity
     * @return affected rows
     */
    @Insert
    int insert(LendingBook entity);

    /**
     * @param entity
     * @return affected rows
     */
    @Update
    int update(LendingBook entity);
    @Update(include = {"lendingState"})
    int updateLendingState(LendingBook entity);
    @Update(include = {"lendingAppFlg", "lendingAppReason"})
    int updateLendingAppFlgAndReason(LendingBook entity);
    @Update(include = {"approvalResult", "approvalReason"})
    int updateApprovalResultAndReason(LendingBook entity);
    
    /**
     * @param entity
     * @return affected rows
     */
    @Delete
    int delete(LendingBook entity);
}
  • @Update(include = {"approvalResult", "approvalReason"}) int updateApprovalResultAndReason(LendingBook entity); を追加します。

Mail003Helper.java

package ksbysample.webapp.lending.helper.mail;

import ksbysample.webapp.lending.entity.LendingBook;
import ksbysample.webapp.lending.util.velocity.VelocityUtils;
import ksbysample.webapp.lending.values.ValuesHelper;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
public class Mail003Helper {

    private final String TEMPLATE_LOCATION_TEXTMAIL = "mail/mail003-body.vm";

    private final String FROM_ADDR = "lendingapp@sample.com";
    private final String SUBJECT = "貸出申請が承認・却下されました";

    @Autowired
    private VelocityUtils velocityUtils;

    @Autowired
    private JavaMailSender mailSender;

    @Autowired
    private ValuesHelper<?> vh;

    public MimeMessage createMessage(String toAddr, Long lendingAppId, List<LendingBook> lendingBookList)
            throws MessagingException {
        List<Mail003BookData> mail003BookDataList = lendingBookList.stream()
                .map(Mail003BookData::new)
                .collect(Collectors.toList());

        MimeMessage mimeMessage = this.mailSender.createMimeMessage();
        MimeMessageHelper message = new MimeMessageHelper(mimeMessage, false, "UTF-8");
        message.setFrom(FROM_ADDR);
        message.setTo(toAddr);
        message.setSubject(SUBJECT);
        message.setText(generateTextUsingVelocity(lendingAppId, mail003BookDataList), false);
        return message.getMimeMessage();
    }

    private String generateTextUsingVelocity(Long lendingAppId, List<Mail003BookData> mail003BookDataList) {
        Map<String, Object> model = new HashMap<>();
        model.put("lendingAppId", lendingAppId);
        model.put("mail003BookDataList", mail003BookDataList);
        return velocityUtils.merge(this.TEMPLATE_LOCATION_TEXTMAIL, model);
    }

    @Data
    public class Mail003BookData {
        private String approvalResultStr;
        private String bookName;

        public Mail003BookData(LendingBook lendingBook) {
            try {
                this.approvalResultStr = vh.getText("LendingBookApprovalResultValues", lendingBook.getApprovalResult());
                this.bookName = lendingBook.getBookName();
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            }
        }
    }

}

mail003-body.vm

貸出申請が承認・却下されました。
========================================================================
承認/却下 書籍
------------------------------------------------------------------------
#foreach ($bookData in $mail003BookDataList)
 $bookData.approvalResultStr   $bookData.bookName
#end
========================================================================

詳細は以下のURLから確認してください。

http://localhost:8080/confirmresult?lendingAppId=${lendingAppId}

LendingapprovalService.java

package ksbysample.webapp.lending.web.lendingapproval;

import ksbysample.webapp.lending.dao.LendingAppDao;
import ksbysample.webapp.lending.dao.LendingBookDao;
import ksbysample.webapp.lending.dao.UserInfoDao;
import ksbysample.webapp.lending.entity.LendingApp;
import ksbysample.webapp.lending.entity.LendingBook;
import ksbysample.webapp.lending.entity.UserInfo;
import ksbysample.webapp.lending.helper.mail.EmailHelper;
import ksbysample.webapp.lending.helper.mail.Mail003Helper;
import org.seasar.doma.jdbc.SelectOptions;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static ksbysample.webapp.lending.values.LendingAppStatusValues.APPLOVED;
import static ksbysample.webapp.lending.values.LendingAppStatusValues.PENDING;
import static ksbysample.webapp.lending.values.LendingBookLendingAppFlgValues.APPLY;

@Service
public class LendingapprovalService {

    @Autowired
    private LendingAppDao lendingAppDao;

    @Autowired
    private UserInfoDao userInfoDao;

    @Autowired
    private LendingBookDao lendingBookDao;

    @Autowired
    private Mail003Helper mail003Helper;

    @Autowired
    private EmailHelper emailHelper;
    
    public void setDispData(Long lendingAppId, LendingapprovalForm lendingapprovalForm) {
        LendingApp lendingApp = lendingAppDao.selectByIdAndStatus(lendingAppId
                , Arrays.asList(PENDING.getValue(), APPLOVED.getValue()));
        String username = "";
        if (lendingApp != null) {
            UserInfo userInfo = userInfoDao.selectById(lendingApp.getLendingUserId());
            username = userInfo.getUsername();
        }
        List<LendingBook> lendingBookList
                = lendingBookDao.selectByLendingAppIdAndLendingAppFlg(lendingAppId, APPLY.getValue());

        lendingapprovalForm.setLendingApp(lendingApp);
        lendingapprovalForm.setUsername(username);
        lendingapprovalForm.setApplyingBookFormList(lendingBookList);
    }

    public void complete(LendingapprovalForm lendingapprovalForm) throws MessagingException {
        // 更新対象のデータを取得する(ロックする)
        Long lendingAppId = lendingapprovalForm.getLendingApp().getLendingAppId();
        LendingApp lendingApp = lendingAppDao.selectById(lendingAppId, SelectOptions.get().forUpdate());
        List<LendingBook> lendingBookList
                = lendingBookDao.selectByLendingAppId(lendingAppId, SelectOptions.get().forUpdate());

        // lending_app.status を 4(承認済) にする
        lendingApp.setStatus(APPLOVED.getValue());
        lendingAppDao.update(lendingApp);

        // lending_book の approval_result, approval_reason を更新する
        lendingBookList = new ArrayList<>();
        for (ApplyingBookForm applyingBookForm : lendingapprovalForm.getApplyingBookFormList()) {
            LendingBook lendingBook = new LendingBook();
            BeanUtils.copyProperties(applyingBookForm, lendingBook);
            lendingBookDao.updateApprovalResultAndReason(lendingBook);
            lendingBookList.add(lendingBook);
        }

        // 申請者にメールを送信する
        UserInfo userInfo = userInfoDao.selectById(lendingApp.getLendingUserId());
        MimeMessage mimeMessage = mail003Helper.createMessage(userInfo.getMailAddress(), lendingAppId, lendingBookList);
        emailHelper.sendMail(mimeMessage);
    }
    
}
  • complete メソッドを追加し、中の処理を実装します。

LendingapprovalController.java

package ksbysample.webapp.lending.web.lendingapproval;

import ksbysample.webapp.lending.exception.WebApplicationRuntimeException;
import ksbysample.webapp.lending.helper.message.MessagesPropertiesHelper;
import ksbysample.webapp.lending.helper.thymeleaf.SuccessMessagesHelper;
import org.seasar.doma.jdbc.OptimisticLockException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.mail.MessagingException;

@Controller
@RequestMapping("/lendingapproval")
public class LendingapprovalController {

    @Autowired
    private LendingapprovalService lendingapprovalService;

    @Autowired
    private MessagesPropertiesHelper messagesPropertiesHelper;

    @Autowired
    private LendingapprovalFormValidator lendingapprovalFormValidator;

    @InitBinder(value = "lendingapprovalForm")
    public void initBinder(WebDataBinder binder) {
        binder.addValidators(lendingapprovalFormValidator);
    }

    @RequestMapping
    public String index(@Validated LendingapprovalParamForm lendingapprovalParamForm
            , BindingResult bindingResult
            , LendingapprovalForm lendingapprovalForm
            , BindingResult bindingResultOfLendingapprovalForm) {
        if (bindingResult.hasErrors()) {
            throw new WebApplicationRuntimeException(
                    messagesPropertiesHelper.getMessage("LendingapprovalParamForm.lendingAppId.emptyerr", null));
        }

        // 画面に表示するデータを取得する
        lendingapprovalService.setDispData(lendingapprovalParamForm.getLendingAppId(), lendingapprovalForm);

        // 指定された貸出申請IDで申請中、承認済のデータがない場合には、貸出承認画面上にエラーメッセージを表示する
        if (lendingapprovalForm.getLendingApp() == null) {
            bindingResultOfLendingapprovalForm.reject("LendingapprovalForm.lendingApp.nodataerr");
        }
        
        return "lendingapproval/lendingapproval";
    }

    @RequestMapping(value = "/complete", method = RequestMethod.POST)
    public String complete(@Validated LendingapprovalForm lendingapprovalForm
            , BindingResult bindingResult
            , Model model) throws MessagingException {
        if (bindingResult.hasErrors()) {
            return "lendingapproval/lendingapproval";
        }

        try {
            // データを更新し、承認完了メールを送信する
            lendingapprovalService.complete(lendingapprovalForm);
    
            // 画面に表示するデータを取得する
            lendingapprovalService.setDispData(lendingapprovalForm.getLendingApp().getLendingAppId(), lendingapprovalForm);
    
            // 画面に表示する通常メッセージをセットする
            SuccessMessagesHelper successMessagesHelper = new SuccessMessagesHelper("確定しました");
            successMessagesHelper.setToModel(model);
        } catch (OptimisticLockException e) {
            bindingResult.reject("Global.optimisticLockException");
        }        

        return "lendingapproval/lendingapproval";
    }

}
  • complete メソッド内に「データを更新し、承認完了メールを送信する」~「画面に表示する通常メッセージをセットする」の処理を追加します。更新時の楽観的排他制御でエラーが発生した場合に、入力された内容を維持したまま画面にエラーメッセージが表示されるよう try { ... } catch (OptimisticLockException e) { bindingResult.reject("Global.optimisticLockException"); } で処理を囲みます。

lendingapproval.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <title>貸出承認</title>
    <!-- Tell the browser to be responsive to screen width -->
    <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"/>
    <link th:replace="common/head-cssjs"/>

    <style>
        .content-wrapper {
            background-color: #fffafa;
        }
        .selected-library {
            color: #ffffff !important;
            font-size: 100%;
            font-weight: 700;
        }
        .box-body.no-padding {
            padding-bottom: 10px !important;
        }
        .table>tbody>tr>td
        , .table>tbody>tr>th
        , .table>tfoot>tr>td
        , .table>tfoot>tr>th
        , .table>thead>tr>td
        , .table>thead>tr>th {
            padding: 5px;
            font-size: 90%;
        }
        .jp-gothic {
            font-family: Verdana, "游ゴシック", YuGothic, "Hiragino Kaku Gothic ProN", Meiryo, sans-serif;
        }
        .btn-approval.active {
            background-color: #00a65a;
        }
        .btn-reject.active {
            background-color: #dd4b39;
        }
        .has-error {
            background-color: #ffcccc;
        }
    </style>
</head>

<!-- ADD THE CLASS layout-top-nav TO REMOVE THE SIDEBAR. -->
<body class="skin-blue layout-top-nav">
<div class="wrapper">

    <!-- Main Header -->
    <div th:replace="common/mainparts :: main-header"></div>

    <!-- Full Width Column -->
    <div class="content-wrapper">
        <div class="container">
            <!-- Content Header (Page header) -->
            <section class="content-header">
                <h1>貸出承認</h1>
            </section>

            <!-- Main content -->
            <section class="content">
                <div class="row">
                    <div class="col-xs-12">
                        <form id="lendingapprovalForm" method="post" action="/lendingapproval/complete"
                              th:action="@{/lendingapproval/complete}" th:object="${lendingapprovalForm}">
                            <div class="alert alert-danger" th:if="${#fields.hasGlobalErrors()}">
                                <p th:each="err : ${#fields.globalErrors()}" th:text="${err}">共通エラーメッセージ表示エリア</p>
                            </div>
                            <div class="alert alert-success" th:if="${successMessages}">
                                <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
                                <p th:each="msg : ${successMessages}" th:text="${msg}">通常メッセージ表示エリア</p>
                            </div>
                            <div class="box" th:if="*{lendingApp != null}">
                                <div class="box-body no-padding">
                                    <div class="col-xs-6 no-padding">
                                        <table class="table table-bordered">
                                            <colgroup>
                                                <col width="30%"/>
                                                <col width="70%"/>
                                            </colgroup>
                                            <tr>
                                                <th class="bg-purple">貸出申請ID</th>
                                                <td th:text="*{lendingApp.lendingAppId}">1</td>
                                            </tr>
                                            <tr>
                                                <th class="bg-purple">ステータス</th>
                                                <td th:text="${@vh.getText('LendingAppStatusValues', lendingapprovalForm.lendingApp.status)}">申請中</td>
                                            </tr>
                                            <tr>
                                                <th class="bg-purple">申請者</th>
                                                <td th:text="*{username}">田中 太郎</td>
                                            </tr>
                                            <input type="hidden" th:field="*{lendingApp.lendingAppId}"/>
                                            <input type="hidden" th:field="*{lendingApp.status}"/>
                                            <input type="hidden" th:field="*{username}"/>
                                        </table>
                                    </div>
                                    <br/>
    
                                    <table class="table">
                                        <colgroup>
                                            <col width="5%"/>
                                            <col width="15%"/>
                                            <col width="15%"/>
                                            <col width="20%"/>
                                            <col width="20%"/>
                                            <col width="25%"/>
                                        </colgroup>
                                        <thead class="bg-purple">
                                        <tr>
                                            <th>No.</th>
                                            <th>ISBN</th>
                                            <th>書名</th>
                                            <th>申請理由</th>
                                            <th>承認/却下</th>
                                            <th>却下理由</th>
                                        </tr>
                                        </thead>
                                        <tbody class="jp-gothic">
                                        <tr th:each="applyingBookForm, iterStat : *{applyingBookFormList}">
                                            <td th:text="${iterStat.count}">1</td>
                                            <td th:text="${applyingBookForm.isbn}">978-4-7741-6366-6</td>
                                            <td th:text="${applyingBookForm.bookName}">GitHub実践入門</td>
                                            <td th:text="${applyingBookForm.lendingAppReason}">開発で使用する為</td>
                                            <td>
                                                <div class="btn-group-sm" data-toggle="buttons"
                                                     th:if="*{lendingApp.status} == ${@vh.getValue('LendingAppStatusValues', 'PENDING')}">
                                                    <label class="btn btn-default btn-approval"
                                                           th:classappend="*{applyingBookFormList[__${iterStat.index}__].approvalResult} == ${@vh.getValue('LendingBookApprovalResultValues', 'APPROVAL')} ? 'active' : ''">
                                                        <input type="radio"
                                                               th:field="*{applyingBookFormList[__${iterStat.index}__].approvalResult}"
                                                               th:value="${@vh.getValue('LendingBookApprovalResultValues', 'APPROVAL')}"/>
                                                        承認
                                                    </label>
                                                    <label class="btn btn-default btn-reject"
                                                           th:classappend="*{applyingBookFormList[__${iterStat.index}__].approvalResult} == ${@vh.getValue('LendingBookApprovalResultValues', 'REJECT')} ? 'active' : ''">
                                                        <input type="radio"
                                                               th:field="*{applyingBookFormList[__${iterStat.index}__].approvalResult}"
                                                               th:value="${@vh.getValue('LendingBookApprovalResultValues', 'REJECT')}"/>
                                                        却下
                                                    </label>
                                                </div>
                                                <span th:text="${@vh.getText('LendingBookApprovalResultValues', applyingBookForm.approvalResult)}"
                                                      th:if="*{lendingApp.status} != ${@vh.getValue('LendingAppStatusValues', 'PENDING')}">
                                                </span>
                                            </td>
                                            <td>
                                                <input type="text" class="form-control input-sm"                                                       
                                                       th:classappend="${#fields.hasErrors('*{applyingBookFormList[__${iterStat.index}__].approvalReason}')} ? 'has-error' : ''"
                                                       th:field="*{applyingBookFormList[__${iterStat.index}__].approvalReason}"
                                                       th:if="*{lendingApp.status} == ${@vh.getValue('LendingAppStatusValues', 'PENDING')}"/>
                                                <span th:text="${applyingBookForm.approvalReason}"
                                                        th:if="*{lendingApp.status} != ${@vh.getValue('LendingAppStatusValues', 'PENDING')}">
                                                </span>
                                            </td>
                                            <input type="hidden" th:field="*{applyingBookFormList[__${iterStat.index}__].lendingBookId}"/>
                                            <input type="hidden" th:field="*{applyingBookFormList[__${iterStat.index}__].isbn}"/>
                                            <input type="hidden" th:field="*{applyingBookFormList[__${iterStat.index}__].bookName}"/>
                                            <input type="hidden" th:field="*{applyingBookFormList[__${iterStat.index}__].lendingAppReason}"/>
                                            <input type="hidden" th:field="*{applyingBookFormList[__${iterStat.index}__].version}"/>
                                        </tr>
                                        </tbody>
                                    </table>
                                    <div class="text-center"
                                         th:if="*{lendingApp.status} == ${@vh.getValue('LendingAppStatusValues', 'PENDING')}">
                                        <button class="btn bg-blue js-btn-complete"><i class="fa fa-check-square-o"></i> 確定</button>
                                    </div>
                                </div>
                            </div>
                        </form>
                    </div>
                </div>
            </section>
            <!-- /.content -->
        </div>
        <!-- /.container -->
    </div>

</div>
<!-- ./wrapper -->

<script th:replace="common/bottom-js"></script>
<script type="text/javascript">
    <!--
    $(document).ready(function() {
        $(".js-btn-complete").click(function(){
            $("#lendingapprovalForm").submit();
            return false;
        });
    });
    -->
</script>
</body>
</html>
  • 通常メッセージ表示エリアの <div class="alert alert-success" th:if="${successMessages}">...</div> を追加します。
  • 「承認/却下」欄はステータスが申請中の時のみ変更可能にするために以下の点を変更します。
    • <div class="btn-group-sm" data-toggle="buttons">th:if="*{lendingApp.status} == ${@vh.getValue('LendingAppStatusValues', 'PENDING')}" を追加します。
    • <span th:text="${@vh.getText('LendingBookApprovalResultValues', applyingBookForm.approvalResult)}" ...></span> を追加します。
  • 「却下理由」欄もステータスが申請中の時のみ変更可能にするために以下の点を変更します。
    • <input type="text" class="form-control input-sm" .../>th:if="*{lendingApp.status} == ${@vh.getValue('LendingAppStatusValues', 'PENDING')}" を追加します。
    • <span th:text="${applyingBookForm.approvalReason}" ...></span> を追加します。
  • 「確定」ボタンはステータスが申請中の時のみ表示されるよう <div class="text-center">th:if="*{lendingApp.status} == ${@vh.getValue('LendingAppStatusValues', 'PENDING')}" を追加します。

履歴

2016/01/17
初版発行。