餐补规则
diff --git a/src/main/java/com/supwisdom/dlpay/restaurant/bean/DiscountRuleShowBean.java b/src/main/java/com/supwisdom/dlpay/restaurant/bean/DiscountRuleShowBean.java
new file mode 100644
index 0000000..4cac7ff
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/restaurant/bean/DiscountRuleShowBean.java
@@ -0,0 +1,76 @@
+package com.supwisdom.dlpay.restaurant.bean;
+
+public class DiscountRuleShowBean {
+  private Integer ruleid;
+  private String rulename;
+  private String timeperiod;
+  private String ruletype;
+  private Integer limitcnt;
+  private Double amount;
+  private String status;
+  private String remark;
+
+  public Integer getRuleid() {
+    return ruleid;
+  }
+
+  public void setRuleid(Integer ruleid) {
+    this.ruleid = ruleid;
+  }
+
+  public String getRulename() {
+    return rulename;
+  }
+
+  public void setRulename(String rulename) {
+    this.rulename = rulename;
+  }
+
+  public String getTimeperiod() {
+    return timeperiod;
+  }
+
+  public void setTimeperiod(String timeperiod) {
+    this.timeperiod = timeperiod;
+  }
+
+  public String getRuletype() {
+    return ruletype;
+  }
+
+  public void setRuletype(String ruletype) {
+    this.ruletype = ruletype;
+  }
+
+  public Integer getLimitcnt() {
+    return limitcnt;
+  }
+
+  public void setLimitcnt(Integer limitcnt) {
+    this.limitcnt = limitcnt;
+  }
+
+  public Double getAmount() {
+    return amount;
+  }
+
+  public void setAmount(Double amount) {
+    this.amount = amount;
+  }
+
+  public String getStatus() {
+    return status;
+  }
+
+  public void setStatus(String status) {
+    this.status = status;
+  }
+
+  public String getRemark() {
+    return remark;
+  }
+
+  public void setRemark(String remark) {
+    this.remark = remark;
+  }
+}
diff --git a/src/main/java/com/supwisdom/dlpay/restaurant/controller/DeviceDiscountRuleController.java b/src/main/java/com/supwisdom/dlpay/restaurant/controller/DeviceDiscountRuleController.java
new file mode 100644
index 0000000..f9026f1
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/restaurant/controller/DeviceDiscountRuleController.java
@@ -0,0 +1,137 @@
+package com.supwisdom.dlpay.restaurant.controller;
+
+import com.supwisdom.dlpay.api.bean.JsonResult;
+import com.supwisdom.dlpay.framework.util.PageResult;
+import com.supwisdom.dlpay.framework.util.StringUtil;
+import com.supwisdom.dlpay.framework.util.WebConstant;
+import com.supwisdom.dlpay.restaurant.bean.DiscountRuleShowBean;
+import com.supwisdom.dlpay.restaurant.service.DeviceDiscountRuleService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.*;
+
+@Controller
+public class DeviceDiscountRuleController {
+  @Autowired
+  private DeviceDiscountRuleService deviceDiscountRuleService;
+
+  @GetMapping("/discountrule/index")
+  public String DiscountRuleView() {
+    return "restaurant/discountrule/rule";
+  }
+
+  @GetMapping("/discountrule/rulelist")
+  @PreAuthorize("hasPermission('/discountrule/index','')")
+  @ResponseBody
+  public PageResult<DiscountRuleShowBean> searchDiscountRules(@RequestParam("page") Integer pageNo,
+                                                              @RequestParam("limit") Integer pageSize,
+                                                              @RequestParam(value = "rulename", required = false) String rulename,
+                                                              @RequestParam(value = "ruletype", required = false) String ruletype) {
+    try {
+      if (null == pageNo || pageNo < 1) pageNo = WebConstant.PAGENO_DEFAULT;
+      if (null == pageSize || pageSize < 1) pageSize = WebConstant.PAGESIZE_DEFAULT;
+      return deviceDiscountRuleService.getDiscountRuleInfos(rulename, ruletype, pageNo, pageSize);
+    } catch (Exception e) {
+      e.printStackTrace();
+      return new PageResult<>(99, "系统查询错误");
+    }
+  }
+
+  @PostMapping("/discountrule/deleterule")
+  @PreAuthorize("hasPermission('/discountrule/deleterule','')")
+  @ResponseBody
+  public JsonResult deleteDiscountRule(@RequestParam("ruleid") Integer ruleid) {
+    try {
+      if (null == ruleid) {
+        return JsonResult.error("参数传递错误");
+      }
+      if (deviceDiscountRuleService.deleteDiscountRule(ruleid)) {
+        return JsonResult.ok("删除成功!");
+      } else {
+        return JsonResult.error("删除失败!");
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+      return JsonResult.error("系统处理异常").put("exception", e);
+    }
+  }
+
+  @GetMapping("/discountrule/load4addrule")
+  @PreAuthorize("hasPermission('/discountrule/load4addrule','')")
+  public String load4addDiscountRule() {
+    return "restaurant/discountrule/ruleform";
+  }
+
+  @GetMapping("/discountrule/checkrulename")
+  @PreAuthorize("hasPermission('/discountrule/load4addrule','')")
+  @ResponseBody
+  public JsonResult checkRulename(@RequestParam("rulename") String rulename,
+                                  @RequestParam(value = "ruleid", required = false) Integer ruleid) {
+    try {
+      if (StringUtil.isEmpty(rulename)) {
+        return JsonResult.error("餐补规则名称不能为空");
+      }
+      if (deviceDiscountRuleService.checkDiscountRulenameExist(rulename.trim(), ruleid)) {
+        return JsonResult.error("餐补规则名称已存在");
+      } else {
+        return JsonResult.ok("success");
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+      return JsonResult.error("系统处理异常").put("exception", e);
+    }
+  }
+
+  @PostMapping("/discountrule/addrule")
+  @PreAuthorize("hasPermission('/discountrule/addrule','')")
+  @ResponseBody
+  public JsonResult addDiscountRule() {
+    try {
+
+      return JsonResult.error("系统处理异常").put("exception", "");
+    } catch (Exception e) {
+      e.printStackTrace();
+      return JsonResult.error("系统处理异常").put("exception", e);
+    }
+  }
+
+  /**
+   * ====================================================
+   * 餐补规则审核
+   * ====================================================
+   */
+  @GetMapping("/discountrule/check")
+  public String checkDiscountRulesView() {
+    return "restaurant/discountrule/rulecheck";
+  }
+
+  @GetMapping("/discountrule/checklist")
+  @PreAuthorize("hasPermission('/discountrule/check','')")
+  @ResponseBody
+  public PageResult<DiscountRuleShowBean> searchCheckDiscountRules(@RequestParam("page") Integer pageNo,
+                                                                   @RequestParam("limit") Integer pageSize,
+                                                                   @RequestParam(value = "status", required = false) String status) {
+    try {
+      if (null == pageNo || pageNo < 1) pageNo = WebConstant.PAGENO_DEFAULT;
+      if (null == pageSize || pageSize < 1) pageSize = WebConstant.PAGESIZE_DEFAULT;
+      return deviceDiscountRuleService.getCheckDiscountRuleInfos(status, pageNo, pageSize);
+    } catch (Exception e) {
+      e.printStackTrace();
+      return new PageResult<>(99, "系统查询错误");
+    }
+  }
+
+
+  /**
+   * ====================================================
+   * 餐补规则绑定设备
+   * ====================================================
+   */
+  @GetMapping("/discountrule/devbind")
+  public String bindDiscountRuleView() {
+    return "restaurant/discountrule/ruledevbind";
+  }
+
+
+}
diff --git a/src/main/java/com/supwisdom/dlpay/restaurant/dao/DiscountDevbindDao.java b/src/main/java/com/supwisdom/dlpay/restaurant/dao/DiscountDevbindDao.java
new file mode 100644
index 0000000..f200457
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/restaurant/dao/DiscountDevbindDao.java
@@ -0,0 +1,11 @@
+package com.supwisdom.dlpay.restaurant.dao;
+
+import com.supwisdom.dlpay.restaurant.domain.TDiscountDevbind;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+
+public interface DiscountDevbindDao extends JpaRepository<TDiscountDevbind, String> {
+
+  @Query("select count(t.id) from TDiscountDevbind t where t.ruleid=?1 ")
+  long getBindcntByRuleid(int ruleid);
+}
diff --git a/src/main/java/com/supwisdom/dlpay/restaurant/dao/DiscountRuleDao.java b/src/main/java/com/supwisdom/dlpay/restaurant/dao/DiscountRuleDao.java
new file mode 100644
index 0000000..9e2150e
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/restaurant/dao/DiscountRuleDao.java
@@ -0,0 +1,16 @@
+package com.supwisdom.dlpay.restaurant.dao;
+
+import com.supwisdom.dlpay.restaurant.domain.TDiscountRule;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Query;
+
+public interface DiscountRuleDao extends JpaRepository<TDiscountRule, Integer>, JpaSpecificationExecutor<TDiscountRule> {
+  TDiscountRule findByRuleid(int ruleid);
+
+  @Query("select count(t.ruleid) from TDiscountRule t where t.rulename=?1 ")
+  long checkRulenameExists(String rulename);
+
+  @Query("select count(t.ruleid) from TDiscountRule t where t.rulename=?1 and t.ruleid<>?2 ")
+  long checkRulenameExists(String rulename, int ruleid);
+}
diff --git a/src/main/java/com/supwisdom/dlpay/restaurant/domain/TDiscountDevbind.java b/src/main/java/com/supwisdom/dlpay/restaurant/domain/TDiscountDevbind.java
new file mode 100644
index 0000000..617e1ce
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/restaurant/domain/TDiscountDevbind.java
@@ -0,0 +1,68 @@
+package com.supwisdom.dlpay.restaurant.domain;
+
+import org.hibernate.annotations.GenericGenerator;
+
+import javax.persistence.*;
+
+@Entity
+@Table(name = "TB_DISCOUNT_DEVBIND",
+    indexes = {@Index(name = "discount_devbind_uk", unique = true, columnList = "deviceid,ruleid")})
+public class TDiscountDevbind {
+  @Id
+  @GenericGenerator(name = "idGenerator", strategy = "uuid")
+  @GeneratedValue(generator = "idGenerator")
+  @Column(name = "ID", nullable = false, length = 32)
+  private String id;
+
+  @Column(name = "DEVICEID", nullable = false, precision = 9)
+  private Integer deviceid;
+
+  @Column(name = "RULEID", nullable = false, precision = 9)
+  private Integer ruleid;
+
+  @Column(name = "CREATE_OPERID", length = 32)
+  private String createOperid;
+
+  @Column(name = "CREATETIME", length = 14)
+  private String createtime;
+
+  public String getId() {
+    return id;
+  }
+
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  public Integer getDeviceid() {
+    return deviceid;
+  }
+
+  public void setDeviceid(Integer deviceid) {
+    this.deviceid = deviceid;
+  }
+
+  public Integer getRuleid() {
+    return ruleid;
+  }
+
+  public void setRuleid(Integer ruleid) {
+    this.ruleid = ruleid;
+  }
+
+  public String getCreateOperid() {
+    return createOperid;
+  }
+
+  public void setCreateOperid(String createOperid) {
+    this.createOperid = createOperid;
+  }
+
+  public String getCreatetime() {
+    return createtime;
+  }
+
+  public void setCreatetime(String createtime) {
+    this.createtime = createtime;
+  }
+}
diff --git a/src/main/java/com/supwisdom/dlpay/restaurant/domain/TDiscountRule.java b/src/main/java/com/supwisdom/dlpay/restaurant/domain/TDiscountRule.java
new file mode 100644
index 0000000..9cdd8b9
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/restaurant/domain/TDiscountRule.java
@@ -0,0 +1,166 @@
+package com.supwisdom.dlpay.restaurant.domain;
+
+import javax.persistence.*;
+
+@Entity
+@Table(name = "TB_DISCOUNT_RULE")
+public class TDiscountRule {
+  @Id
+  @SequenceGenerator(name = "discount_ruleid", sequenceName = "SEQ_DISCOUNTRULEID", allocationSize = 1)
+  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "discount_ruleid")
+  @Column(name="RULEID", nullable = false, precision = 9)
+  private Integer ruleid;
+
+  @Column(name = "rulename", nullable = false, length = 200)
+  private String rulename;
+
+  @Column(name = "STARTTIME", nullable = false, length = 4)
+  private String starttime;
+
+  @Column(name = "ENDTIME", nullable = false, length = 4)
+  private String endtime;
+
+  @Column(name = "RULETYPE", nullable = false, length = 10)
+  private String ruletype;
+
+  @Column(name = "AMOUNT", nullable = false, precision = 9, scale = 2)
+  private Double amount;
+
+  @Column(name = "LIMITCNT", nullable = false, precision = 9)
+  private Integer limitcnt;
+
+  @Column(name = "STATUS", nullable = false, length = 10)
+  private String status;
+
+  @Version
+  @GeneratedValue(strategy = GenerationType.AUTO)
+  @Column(name="VERNO", nullable = false, precision = 9)
+  private Integer verno;
+
+  @Column(name = "CREATE_OPERID", length = 32)
+  private String createOperid;
+
+  @Column(name = "CHECK_OPERID", length = 32)
+  private String checkOperid;
+
+  @Column(name = "CREATETIME", length = 14)
+  private String createtime;
+
+  @Column(name = "LASTSAVED", length = 14)
+  private String lastsaved;
+
+  @Column(name = "REMARK", length = 600)
+  private String remark;
+
+  public Integer getRuleid() {
+    return ruleid;
+  }
+
+  public void setRuleid(Integer ruleid) {
+    this.ruleid = ruleid;
+  }
+
+  public String getRulename() {
+    return rulename;
+  }
+
+  public void setRulename(String rulename) {
+    this.rulename = rulename;
+  }
+
+  public String getStarttime() {
+    return starttime;
+  }
+
+  public void setStarttime(String starttime) {
+    this.starttime = starttime;
+  }
+
+  public String getEndtime() {
+    return endtime;
+  }
+
+  public void setEndtime(String endtime) {
+    this.endtime = endtime;
+  }
+
+  public String getRuletype() {
+    return ruletype;
+  }
+
+  public void setRuletype(String ruletype) {
+    this.ruletype = ruletype;
+  }
+
+  public Double getAmount() {
+    return amount;
+  }
+
+  public void setAmount(Double amount) {
+    this.amount = amount;
+  }
+
+  public Integer getLimitcnt() {
+    return limitcnt;
+  }
+
+  public void setLimitcnt(Integer limitcnt) {
+    this.limitcnt = limitcnt;
+  }
+
+  public String getStatus() {
+    return status;
+  }
+
+  public void setStatus(String status) {
+    this.status = status;
+  }
+
+  public String getCreateOperid() {
+    return createOperid;
+  }
+
+  public void setCreateOperid(String createOperid) {
+    this.createOperid = createOperid;
+  }
+
+  public String getCheckOperid() {
+    return checkOperid;
+  }
+
+  public void setCheckOperid(String checkOperid) {
+    this.checkOperid = checkOperid;
+  }
+
+  public String getCreatetime() {
+    return createtime;
+  }
+
+  public void setCreatetime(String createtime) {
+    this.createtime = createtime;
+  }
+
+  public String getLastsaved() {
+    return lastsaved;
+  }
+
+  public void setLastsaved(String lastsaved) {
+    this.lastsaved = lastsaved;
+  }
+
+  public Integer getVerno() {
+    return verno;
+  }
+
+  public void setVerno(Integer verno) {
+    this.verno = verno;
+  }
+
+  public String getRemark() {
+    return remark;
+  }
+
+  public void setRemark(String remark) {
+    this.remark = remark;
+  }
+}
diff --git a/src/main/java/com/supwisdom/dlpay/restaurant/service/DeviceDiscountRuleService.java b/src/main/java/com/supwisdom/dlpay/restaurant/service/DeviceDiscountRuleService.java
new file mode 100644
index 0000000..363f1a6
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/restaurant/service/DeviceDiscountRuleService.java
@@ -0,0 +1,22 @@
+package com.supwisdom.dlpay.restaurant.service;
+
+import com.supwisdom.dlpay.exception.WebCheckException;
+import com.supwisdom.dlpay.framework.util.PageResult;
+import com.supwisdom.dlpay.restaurant.bean.DiscountRuleShowBean;
+import org.springframework.transaction.annotation.Transactional;
+
+public interface DeviceDiscountRuleService {
+  @Transactional(rollbackFor = Exception.class, readOnly = true)
+  PageResult<DiscountRuleShowBean> getDiscountRuleInfos(String rulename, String ruletype, int pageNo, int pageSize);
+
+  @Transactional(rollbackFor = Exception.class)
+  boolean deleteDiscountRule(int ruleid)throws WebCheckException;
+
+  @Transactional(rollbackFor = Exception.class, readOnly = true)
+  boolean checkDiscountRulenameExist(String rulename,Integer ruleid);
+
+
+
+  @Transactional(rollbackFor = Exception.class, readOnly = true)
+  PageResult<DiscountRuleShowBean> getCheckDiscountRuleInfos(String status, int pageNo, int pageSize);
+}
diff --git a/src/main/java/com/supwisdom/dlpay/restaurant/service/impl/DeviceDiscountRuleServiceImpl.java b/src/main/java/com/supwisdom/dlpay/restaurant/service/impl/DeviceDiscountRuleServiceImpl.java
new file mode 100644
index 0000000..78321dd
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/restaurant/service/impl/DeviceDiscountRuleServiceImpl.java
@@ -0,0 +1,124 @@
+package com.supwisdom.dlpay.restaurant.service.impl;
+
+import com.supwisdom.dlpay.exception.WebCheckException;
+import com.supwisdom.dlpay.framework.service.SystemUtilService;
+import com.supwisdom.dlpay.framework.util.PageResult;
+import com.supwisdom.dlpay.framework.util.StringUtil;
+import com.supwisdom.dlpay.restaurant.bean.DiscountRuleShowBean;
+import com.supwisdom.dlpay.restaurant.dao.DiscountDevbindDao;
+import com.supwisdom.dlpay.restaurant.dao.DiscountRuleDao;
+import com.supwisdom.dlpay.restaurant.domain.TDiscountRule;
+import com.supwisdom.dlpay.restaurant.service.DeviceDiscountRuleService;
+import com.supwisdom.dlpay.restaurant.util.RestaurantConstant;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+public class DeviceDiscountRuleServiceImpl implements DeviceDiscountRuleService {
+  @Autowired
+  private DiscountRuleDao discountRuleDao;
+  @Autowired
+  private DiscountDevbindDao discountDevbindDao;
+  @Autowired
+  private SystemUtilService systemUtilService;
+
+
+  @PersistenceContext
+  private EntityManager entityManager;
+
+  private PageResult<DiscountRuleShowBean> getDiscountRuleBySearch(String rulename, String ruletype, String status, Pageable pageable) {
+    Page<TDiscountRule> page = discountRuleDao.findAll(new Specification<TDiscountRule>() {
+      @Override
+      public Predicate toPredicate(Root<TDiscountRule> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
+        List<Predicate> predicates = new ArrayList<>();
+        if (!StringUtil.isEmpty(rulename)) {
+          predicates.add(criteriaBuilder.like(root.get("rulename").as(String.class), "%" + rulename.trim() + "%"));
+        }
+        if (!StringUtil.isEmpty(ruletype)) {
+          predicates.add(criteriaBuilder.equal(root.get("ruletype").as(String.class), ruletype));
+
+        }
+        if (!StringUtil.isEmpty(status)) {
+          predicates.add(criteriaBuilder.equal(root.get("status").as(String.class), status));
+        }
+        return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
+      }
+    }, pageable);
+    List<DiscountRuleShowBean> result = new ArrayList<>(0);
+    if (null != page && page.getTotalElements() > 0) {
+      for (TDiscountRule rule : page.getContent()) {
+        DiscountRuleShowBean bean = new DiscountRuleShowBean();
+        bean.setRuleid(rule.getRuleid());
+        bean.setRulename(rule.getRulename());
+        bean.setRuletype(rule.getRuletype());
+        bean.setAmount(rule.getAmount());
+        bean.setStatus(rule.getStatus());
+        bean.setLimitcnt(rule.getLimitcnt());
+        bean.setRemark(rule.getRemark());
+        String period = rule.getStarttime().substring(0, 2) + ":" + rule.getStarttime().substring(2) + "~" + rule.getEndtime().substring(0, 2) + ":" + rule.getEndtime().substring(2);
+        bean.setTimeperiod(period);
+        result.add(bean);
+      }
+    }
+    return new PageResult<>(page.getTotalElements(), result);
+  }
+
+  @Override
+  public PageResult<DiscountRuleShowBean> getDiscountRuleInfos(String rulename, String ruletype, int pageNo, int pageSize) {
+    Pageable pageable = PageRequest.of(pageNo - 1, pageSize, Sort.by("ruleid"));
+    return getDiscountRuleBySearch(rulename, ruletype, null, pageable);
+  }
+
+  @Override
+  public boolean deleteDiscountRule(int ruleid) throws WebCheckException {
+    TDiscountRule rule = discountRuleDao.findByRuleid(ruleid);
+    if (null == rule) {
+      throw new WebCheckException("餐补规则不存在!");
+    } else if (RestaurantConstant.STATUS_DISCOUNTRULE_CLOSED.equals(rule.getStatus())) {
+      throw new WebCheckException("餐补规则已经失效!");
+    }
+    if (discountDevbindDao.getBindcntByRuleid(ruleid) > 0) {
+      throw new WebCheckException("有设备正在使用该餐补规则,请先解绑设备");
+    }
+
+    rule.setStatus(RestaurantConstant.STATUS_DISCOUNTRULE_CLOSED);
+    rule.setLastsaved(systemUtilService.getSysdatetime().getHostdatetime());
+    discountRuleDao.save(rule);
+    return true;
+  }
+
+  @Override
+  public boolean checkDiscountRulenameExist(String rulename, Integer ruleid) {
+    if (null == ruleid) {
+      if (discountRuleDao.checkRulenameExists(rulename) > 0) {
+        return true;
+      }
+    } else {
+      if (discountRuleDao.checkRulenameExists(rulename, ruleid) > 0) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @Override
+  public PageResult<DiscountRuleShowBean> getCheckDiscountRuleInfos(String status, int pageNo, int pageSize) {
+    Pageable pageable = PageRequest.of(pageNo - 1, pageSize, Sort.by(Sort.Direction.DESC, "createtime"));
+    return getDiscountRuleBySearch(null, null, status, pageable);
+  }
+}
diff --git a/src/main/java/com/supwisdom/dlpay/restaurant/util/RestaurantConstant.java b/src/main/java/com/supwisdom/dlpay/restaurant/util/RestaurantConstant.java
new file mode 100644
index 0000000..c0f7343
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/restaurant/util/RestaurantConstant.java
@@ -0,0 +1,12 @@
+package com.supwisdom.dlpay.restaurant.util;
+
+public class RestaurantConstant {
+  public static final String STATUS_DISCOUNTRULE_UNCHECK = "uncheck"; //待审核
+  public static final String STATUS_DISCOUNTRULE_NORMAL = "normal";  //有效
+  public static final String STATUS_DISCOUNTRULE_CLOSED = "closed";   //无效
+  public static final String STATUS_DISCOUNTRULE_REJECT = "reject";   //驳回
+
+  public static final String RULETYPE_QUOTA = "quota"; //定额
+  public static final String RULETYPE_REDUCTION = "reduction"; //减免
+
+}
diff --git a/src/main/resources/templates/restaurant/discountrule/rule.html b/src/main/resources/templates/restaurant/discountrule/rule.html
new file mode 100644
index 0000000..1cf7a9a
--- /dev/null
+++ b/src/main/resources/templates/restaurant/discountrule/rule.html
@@ -0,0 +1,147 @@
+<div class="layui-card">
+    <div class="layui-card-header">
+        <h2 class="header-title">餐补规则维护</h2>
+        <span class="layui-breadcrumb pull-right">
+          <a href="#">餐补规则管理</a>
+          <a><cite>餐补规则维护</cite></a>
+        </span>
+    </div>
+    <div class="layui-card-body">
+        <div class="layui-form toolbar">
+            搜索:
+            <select id="search-discountrule-ruletype">
+                <option value=""> 选择餐补类型 </option>
+                <option value="quota"> 定额 </option>
+                <option value="reduction"> 减免 </option>
+            </select>&emsp;
+            <input id="search-discountrule-rulename" class="layui-input search-input" maxlength="20" type="text" placeholder="输入名称查询"/>&emsp;
+            <button id="btn-search-discountrule" class="layui-btn icon-btn" data-type="search"><i class="layui-icon">&#xe615;</i>搜索
+            </button>
+            <button id="btn-discountrule-add" class="layui-btn icon-btn" data-type="add"><i class="layui-icon">&#xe654;</i>新 增</button>
+        </div>
+        <table class="layui-table" id="discountruleTable" lay-filter="discountruleTable-filter"></table>
+    </div>
+</div>
+
+
+<!-- 表格操作列 -->
+<script type="text/html" id="discountrule-table-bar">
+    <a class="layui-btn layui-btn layui-btn-xs" lay-event="edit">修改</a>
+</script>
+
+<script>
+    layui.use(['form', 'table', 'layer', 'admin', 'element'], function () {
+        var form = layui.form;
+        var table = layui.table;
+        var admin = layui.admin;
+
+        form.render("select");
+        // 渲染表格
+        table.render({
+            elem: '#discountruleTable',
+            url: '[[@{/discountrule/rulelist}]]',
+            page: true,
+            cols: [
+                [
+                    {field: 'rulename', title: '餐补名称', align: 'center', fixed: 'left' },
+                    {field: 'timeperiod', title: '优惠时间段',  align: 'center'},
+                    {
+                        field: 'ruletype', title: '餐补类型', align: 'center', width: 120,  sort: true, templet: function (d) {
+                            if ('quota' == d.ruletype) {
+                                return '定额';
+                            } else if ('reduction' == d.ruletype) {
+                                return '减免';
+                            } else {
+                                return d.ruletype;
+                            }
+                        }
+                    },
+                    {
+                        field: 'amount', title: '金额(元)', align: 'center', sort: true, templet: function (d) {
+                            return parseFloat(d.amount).toFixed(2);
+                        }
+                    },
+                    {field: 'limitcnt', title: '可使用次数/人',  align: 'center'},
+                    {
+                        field: 'status', title: '状态', align: 'center', width: 120, sort: true, templet: function (d) {
+                            if ('uncheck' == d.status) {
+                                return '<span class="layui-badge layui-bg-orange">待审核</span>'
+                            } else if ('normal' == d.status) {
+                                return '<span class="layui-badge layui-bg-green">有效</span>';
+                            } else if ('closed' == d.status) {
+                                return '<span class="layui-badge layui-bg-gray">无效</span>';
+                            } else if ('reject' == d.status) {
+                                return '<span class="layui-badge">驳回</span>';
+                            } else {
+                                return d.status;
+                            }
+                        }
+                    },
+                    {align: 'center', title: '操作', width: 250, toolbar: '#discountrule-table-bar',  fixed: 'right'}
+                ]
+            ]
+        });
+
+        // 搜索按钮点击事件
+        $('#btn-search-discountrule').click(function () {
+            var ruletype = $("#search-discountrule-ruletype").val();
+            var rulename = $("#search-discountrule-rulename").val();
+            table.reload('discountruleTable', {where: {ruletype: ruletype, rulename: rulename}, page: {curr: 1}});
+        });
+
+        $('#btn-discountrule-add').click(function () {
+            admin.popupCenter({
+                title: "新增餐补规则",
+                path: '[[@{/discountrule/load4addrule}]]',
+                area: '500px',
+                finish: function () {
+                    table.reload('discountruleTable');
+                }
+            });
+        });
+
+        //监听单元格
+        table.on('tool(discountruleTable-filter)', function (obj) {
+            var data = obj.data;
+
+            if('del' == obj.event){
+                layer.confirm('确定要删除设备参数组【'+data.groupname+'】?', {
+                    btn: ['确定', '取消']
+                },function(){
+                    layer.closeAll('dialog');
+                    layer.load(2);
+                    admin.go('[[@{/device/deletedevpara}]]', {
+                        groupid: data.groupid,
+                        _csrf: $("meta[name='_csrf_token']").attr("value")
+                    }, function (data) {
+                        console.log(data.code);
+                        layer.closeAll('loading');
+                        if (data.code == 200) {
+                            layer.msg(data.msg, {icon: 1});
+                        } else if (data.code == 401) {
+                            layer.msg(data.msg, {icon: 2, time: 1500}, function () {
+                                location.replace('[[@{/login}]]');
+                            }, 1000);
+                            return;
+                        } else {
+                            layer.msg(data.msg, {icon: 2});
+                        }
+                        table.reload('devparagroupTable');
+                    }, function (err) {
+                        admin.errorBack(err)
+                    });
+                });
+            }else if('edit' == obj.event){
+                admin.popupCenter({
+                    title: "修改参数组【" + data.groupid + "_" + data.groupname + "】",
+                    path: '[[@{/device/load4editdevpara}]]?groupid=' + data.groupid,
+                    area: '1200px',
+                    finish: function () {
+                        table.reload('devparagroupTable');
+                    }
+                });
+            }
+        });
+
+    });
+</script>
\ No newline at end of file
diff --git a/src/main/resources/templates/restaurant/discountrule/rulecheck.html b/src/main/resources/templates/restaurant/discountrule/rulecheck.html
new file mode 100644
index 0000000..71121d2
--- /dev/null
+++ b/src/main/resources/templates/restaurant/discountrule/rulecheck.html
@@ -0,0 +1,104 @@
+<div class="layui-card">
+    <div class="layui-card-header">
+        <h2 class="header-title">餐补规则审核</h2>
+        <span class="layui-breadcrumb pull-right">
+          <a href="#">餐补规则管理</a>
+          <a><cite>餐补规则审核</cite></a>
+        </span>
+    </div>
+    <div class="layui-card-body">
+        <div class="layui-form toolbar">
+            搜索:
+            <select id="search-discountrule-check-status">
+                <option value=""> 选择餐补规则状态</option>
+                <option value="uncheck" selected> 待审核</option>
+                <option value="normal"> 有效</option>
+                <option value="closed"> 无效</option>
+                <option value="reject"> 驳回</option>
+            </select>&emsp;
+            <button id="btn-search-discountrule-check" class="layui-btn icon-btn" data-type="search"><i
+                    class="layui-icon">&#xe615;</i>搜索
+            </button>
+        </div>
+        <table class="layui-table" id="discountrulecheckTable" lay-filter="discountrulecheckTable-filter"></table>
+    </div>
+</div>
+
+
+<!-- 表格操作列 -->
+<script type="text/html" id="discountrule-check-table-bar">
+    <a class="layui-btn layui-btn layui-btn-xs" lay-event="edit">修改</a>
+</script>
+
+<script>
+    layui.use(['form', 'table', 'layer', 'admin', 'element'], function () {
+        var form = layui.form;
+        var table = layui.table;
+        var admin = layui.admin;
+
+        form.render("select");
+        // 渲染表格
+        table.render({
+            elem: '#discountrulecheckTable',
+            url: '[[@{/discountrule/checklist}]]',
+            page: true,
+            cols: [
+                [
+                    {field: 'rulename', title: '餐补名称', align: 'center', fixed: 'left'},
+                    {field: 'timeperiod', title: '优惠时间段', align: 'center'},
+                    {
+                        field: 'ruletype',
+                        title: '餐补类型',
+                        align: 'center',
+                        width: 120,
+                        sort: true,
+                        templet: function (d) {
+                            if ('quota' == d.ruletype) {
+                                return '定额';
+                            } else if ('reduction' == d.ruletype) {
+                                return '减免';
+                            } else {
+                                return d.ruletype;
+                            }
+                        }
+                    },
+                    {
+                        field: 'amount', title: '金额(元)', align: 'center', sort: true, templet: function (d) {
+                            return parseFloat(d.amount).toFixed(2);
+                        }
+                    },
+                    {field: 'limitcnt', title: '可使用次数/人', align: 'center'},
+                    {
+                        field: 'status', title: '状态', align: 'center', width: 120, sort: true, templet: function (d) {
+                            if ('uncheck' == d.status) {
+                                return '<span class="layui-badge layui-bg-orange">待审核</span>'
+                            } else if ('normal' == d.status) {
+                                return '<span class="layui-badge layui-bg-green">有效</span>';
+                            } else if ('closed' == d.status) {
+                                return '<span class="layui-badge layui-bg-gray">无效</span>';
+                            } else if ('reject' == d.status) {
+                                return '<span class="layui-badge">驳回</span>';
+                            } else {
+                                return d.status;
+                            }
+                        }
+                    },
+                    {align: 'center', title: '操作', width: 250, toolbar: '#discountrule-check-table-bar', fixed: 'right'}
+                ]
+            ]
+        });
+
+        // 搜索按钮点击事件
+        $('#btn-search-discountrule-check').click(function () {
+            var state = $("#search-discountrule-check-status").val();
+            table.reload('discountrulecheckTable', {where: {status: state}, page: {curr: 1}});
+        });
+
+        //监听单元格
+        table.on('tool(discountrulecheckTable-filter)', function (obj) {
+            var data = obj.data;
+
+        });
+
+    });
+</script>
\ No newline at end of file
diff --git a/src/main/resources/templates/restaurant/discountrule/ruledevbind.html b/src/main/resources/templates/restaurant/discountrule/ruledevbind.html
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/main/resources/templates/restaurant/discountrule/ruledevbind.html
diff --git a/src/main/resources/templates/restaurant/discountrule/ruleform.html b/src/main/resources/templates/restaurant/discountrule/ruleform.html
new file mode 100644
index 0000000..aaf81ba
--- /dev/null
+++ b/src/main/resources/templates/restaurant/discountrule/ruleform.html
@@ -0,0 +1,137 @@
+<form id="discountrule-form" lay-filter="discountrule-form-filter" class="layui-form model-form" style="padding: 30px 25px 10px 25px;">
+    <input name="ruleid" id="form-discountrule-ruleid" type="hidden"/>
+    <div class="layui-form-item">
+        <label class="layui-form-label">餐补类型</label>
+        <div class="layui-input-block">
+            <input type="radio" name="ruletype" id="form-discountrule-ruletype-quota" lay-filter="discountrule-ruletype-filter" value="quota" title="定额" checked/>
+            <input type="radio" name="ruletype" id="form-discountrule-ruletype-reduction" lay-filter="discountrule-ruletype-filter" value="reduction" title="减免"/>
+        </div>
+    </div>
+
+    <div class="layui-form-item">
+        <label class="layui-form-label">餐补名称</label>
+        <div class="layui-input-block">
+           <input type="text" class="layui-input" name="rulename" id="form-discountrule-rulename" maxlength="20" style="width: 90%;"
+                  autocomplete="off" lay-verify="required|Rulename"/>
+        </div>
+    </div>
+
+    <div class="layui-form-item">
+        <label class="layui-form-label">可用时间段</label>
+        <div class="layui-input-inline" style="width: 100px;">
+            <input type="text" name="starttime" placeholder="9:00" id="form-discountrule-starttime" autocomplete="off" maxlength="5"
+                   class="layui-input" lay-verify="required"/>
+        </div>
+        <div class="layui-form-mid">-</div>
+        <div class="layui-input-inline" style="width: 100px;">
+            <input type="text" name="endtime" placeholder="12:00" id="form-discountrule-endtime" autocomplete="off" maxlength="5"
+                   class="layui-input" lay-verify="required"/>
+        </div>
+    </div>
+
+    <div class="layui-form-item">
+        <label class="layui-form-label" id="form-discountrule-amount-text">固定金额(元)</label>
+        <div class="layui-input-block">
+            <input type="text" name="amount" id="form-discountrule-amount" maxlength="9" autocomplete="off" style="width: 90%;"
+                   class="layui-input" lay-verify="required|Amount"/>
+        </div>
+    </div>
+
+    <div class="layui-form-item">
+        <label class="layui-form-label">可以次数/人</label>
+        <div class="layui-input-block">
+            <input type="text" name="limitcnt" id="form-discountrule-limitcnt" maxlength="9" autocomplete="off" style="width: 90%;"
+                   class="layui-input" lay-verify="required|number"/>
+        </div>
+    </div>
+
+
+    <div class="layui-form-item">
+        <label class="layui-form-label">餐补对象</label>
+        <div class="layui-input-inline" style="width: auto;">
+            <button type="button" class="layui-btn" id="form-discountrule-records">
+                <i class="layui-icon">&#xe67c;</i>上传名单
+            </button>
+        </div>
+        <div class="layui-input-inline" style="padding-top: 15px;">
+            <a style="color: blue;text-decoration: none;cursor: pointer;">下载名单模板</a>
+        </div>
+    </div>
+
+    <div class="layui-form-item model-form-footer">
+        <button class="layui-btn layui-btn-primary" type="button" ew-event="closeDialog">取消</button>
+        <button class="layui-btn" lay-filter="discountrule-form-submit" lay-submit id="submitbtn">保存</button>
+    </div>
+</form>
+
+<script>
+    layui.use(['layer', 'admin', 'form', 'laydate', 'upload'], function () {
+        var layer = layui.layer;
+        var admin = layui.admin;
+        var form = layui.form;
+        var laydate = layui.laydate;
+        var upload = layui.upload;
+
+        laydate.render({
+            elem: '#form-discountrule-starttime',
+            type: 'time',
+            format: 'HH:mm'
+        });
+        laydate.render({
+            elem: '#form-discountrule-endtime',
+            type: 'time',
+            format: 'HH:mm'
+        });
+
+        // 表单提交事件
+        form.render("radio");
+        form.verify({
+            "Amount": function (e) {
+                if (null != e && e.length > 0 && !(/^\d+(\.)?(\.\d{1,2})?$/.test(e))) {
+                    return "请正确输入金额(单位:元,最多两位小数)";
+                }
+            },
+            "Rulename": function (e) {
+                if(""==e|| ""==$.trim(e)){
+                    return "餐补名称不能为空";
+                }
+
+                var msg = "";
+                $.ajax({
+                    type: "GET",
+                    url: '[[@{/discountrule/checkrulename}]]',
+                    async: false, //同步提交。不设置则默认异步,异步的话,最后执行ajax
+                    data: {
+                        rulename: e,
+                        ruleid: $("#form-discountrule-ruleid").val()
+                    },
+                    success: function (result) {
+                        if (result.code != 200) {
+                            msg = result.msg;
+                        }
+                    },
+                    error: function (error) {
+                        msg = "请求服务器校验账号失败";
+                    }
+                });
+                if (msg != "") {
+                    return msg;
+                }
+            }
+        });
+        form.on('radio(discountrule-ruletype-filter)', function (data) {
+            if ('reduction' == data.value) {
+                $("#form-discountrule-amount-text").text("减免金额(元)");
+            } else {
+                $("#form-discountrule-amount-text").text("固定金额(元)");
+            }
+        });
+
+
+
+
+        form.on('submit(discountrule-form-submit)', function (data) {
+            var vdata = data.field;
+        });
+    });
+</script>
\ No newline at end of file