大理考勤报表
diff --git a/src/main/java/com/supwisdom/dlpay/atte/bean/AtteReport.java b/src/main/java/com/supwisdom/dlpay/atte/bean/AtteReport.java
index 97527ef..e5b0a2c 100644
--- a/src/main/java/com/supwisdom/dlpay/atte/bean/AtteReport.java
+++ b/src/main/java/com/supwisdom/dlpay/atte/bean/AtteReport.java
@@ -16,6 +16,8 @@
     private Integer cnt3; // 请假
     private Integer cnt4; //旷工
     private Integer cnts;//
+    private String custtypename;
+    private String deptname;
 
     public String getCustid() {
         return custid;
@@ -96,4 +98,20 @@
     public void setCnt4(Integer cnt4) {
         this.cnt4 = cnt4;
     }
+
+    public String getCusttypename() {
+        return custtypename;
+    }
+
+    public void setCusttypename(String custtypename) {
+        this.custtypename = custtypename;
+    }
+
+    public String getDeptname() {
+        return deptname;
+    }
+
+    public void setDeptname(String deptname) {
+        this.deptname = deptname;
+    }
 }
diff --git a/src/main/java/com/supwisdom/dlpay/atte/bean/Sum.java b/src/main/java/com/supwisdom/dlpay/atte/bean/Sum.java
new file mode 100644
index 0000000..45c6dfd
--- /dev/null
+++ b/src/main/java/com/supwisdom/dlpay/atte/bean/Sum.java
@@ -0,0 +1,57 @@
+package com.supwisdom.dlpay.atte.bean;
+
+public class Sum {
+    private Integer cnt1;
+    private Integer cnt2;
+    private Integer cnt3;
+    private Integer cnt4;
+    private Integer cnts;
+
+    public Sum() {
+        this.cnt1=0;
+        this.cnt2=0;
+        this.cnt3=0;
+        this.cnt4=0;
+        this.cnts=0;
+    }
+
+    public Integer getCnt1() {
+        return cnt1;
+    }
+
+    public void setCnt1(Integer cnt1) {
+        this.cnt1 = cnt1;
+    }
+
+    public Integer getCnt2() {
+        return cnt2;
+    }
+
+    public void setCnt2(Integer cnt2) {
+        this.cnt2 = cnt2;
+    }
+
+    public Integer getCnt3() {
+        return cnt3;
+    }
+
+    public void setCnt3(Integer cnt3) {
+        this.cnt3 = cnt3;
+    }
+
+    public Integer getCnt4() {
+        return cnt4;
+    }
+
+    public void setCnt4(Integer cnt4) {
+        this.cnt4 = cnt4;
+    }
+
+    public Integer getCnts() {
+        return cnts;
+    }
+
+    public void setCnts(Integer cnts) {
+        this.cnts = cnts;
+    }
+}
diff --git a/src/main/java/com/supwisdom/dlpay/atte/controller/CustAtteController.java b/src/main/java/com/supwisdom/dlpay/atte/controller/CustAtteController.java
index a5bfaaa..ce6329e 100644
--- a/src/main/java/com/supwisdom/dlpay/atte/controller/CustAtteController.java
+++ b/src/main/java/com/supwisdom/dlpay/atte/controller/CustAtteController.java
@@ -1,6 +1,8 @@
 package com.supwisdom.dlpay.atte.controller;
 
+import com.supwisdom.dlpay.atte.bean.AtteReport;
 import com.supwisdom.dlpay.atte.bean.AttedtlSearchBean;
+import com.supwisdom.dlpay.atte.bean.Sum;
 import com.supwisdom.dlpay.atte.domain.TAtteClass;
 import com.supwisdom.dlpay.atte.domain.TAtteDtl;
 import com.supwisdom.dlpay.atte.domain.TSeaCusttype;
@@ -10,6 +12,7 @@
 import com.supwisdom.dlpay.atte.service.SeasonService;
 import com.supwisdom.dlpay.doorlist.bean.TCustomerInfo;
 import com.supwisdom.dlpay.framework.domain.TOperator;
+import com.supwisdom.dlpay.framework.service.SystemUtilService;
 import com.supwisdom.dlpay.framework.util.DateUtil;
 import com.supwisdom.dlpay.framework.util.StringUtil;
 import com.supwisdom.dlpay.mainservice.domain.TCustomer;
@@ -23,6 +26,7 @@
 import com.supwisdom.dlpay.system.domain.TDept;
 import com.supwisdom.dlpay.system.domain.TDictionaryId;
 import com.supwisdom.dlpay.system.page.Pagination;
+import com.supwisdom.dlpay.system.service.ManagerService;
 import com.supwisdom.dlpay.system.service.SystemService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -30,6 +34,7 @@
 import org.springframework.security.core.annotation.AuthenticationPrincipal;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
+import org.springframework.ui.ModelMap;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
@@ -54,6 +59,10 @@
     private SystemService systemService;
     @Autowired
     AtteClassService atteClassService;
+    @Autowired
+    private SystemUtilService systemUtilService;
+    @Autowired
+    private ManagerService managerService;
 
     @GetMapping("/rule/index")
     public String seasonindex(){
@@ -81,7 +90,7 @@
                 }else {
 
                     if(StringUtil.isEmpty(deptcode)){
-                        deptcode="-1";
+                        deptcode="-99";
                     }
                     page=seasonService.getSeasonWithPage(season,deptcode,pageNo,pageSize);
                 }
@@ -405,7 +414,7 @@
             }else {
 
                 if(StringUtil.isEmpty(deptcode)){
-                    deptcode="-1";
+                    deptcode="-99";
                 }
                 page=atteClassService.getClassWithPage(classname,deptcode,pageNo,pageSize);
             }
@@ -633,7 +642,7 @@
                 deptcode=null;
         }else {
             if(StringUtil.isEmpty(deptcode)){
-                deptcode="-1";
+                deptcode="-99";
             }
         }
         atteClassService.addBatchDtl(startdate,enddate,deptcode);
@@ -674,7 +683,7 @@
                 deptcode=null;
             }else {
                 if(StringUtil.isEmpty(deptcode)){
-                    deptcode="-1";
+                    deptcode="-99";
                 }
             }
             searchBean.setDeptcode(deptcode);
@@ -732,7 +741,7 @@
                 deptcode=null;
             }else {
                 if(StringUtil.isEmpty(deptcode)){
-                    deptcode="-1";
+                    deptcode="-99";
                 }
             }
             searchBean.setDeptcode(deptcode);
@@ -817,7 +826,7 @@
                 deptcode=null;
             }else {
                 if(StringUtil.isEmpty(deptcode)){
-                    deptcode="-1";
+                    deptcode="-99";
                 }
             }
             List<TCustomerInfo> allcust=atteClassService.getAllCustomer(perName,deptcode,custtypeid);
@@ -856,7 +865,7 @@
                 deptcode=null;
             }else {
                 if(StringUtil.isEmpty(deptcode)){
-                    deptcode="-1";
+                    deptcode="-99";
                 }
             }
             atteClassService.addReview(deptcode,operUser.getOpercode(),custids);
@@ -902,7 +911,7 @@
                     deptcode=null;
             }else {
                 if(StringUtil.isEmpty(deptcode)){
-                    deptcode="-1";
+                    deptcode="-99";
                 }
             }
             searchBean.setDeptcode(deptcode);
@@ -913,7 +922,6 @@
             List<TDept> deptlist=systemService.findAllDept();
             map.put("deptlist",deptlist);
             map.put("operator",operUser);
-
         }catch (Exception e) {
             e.printStackTrace();
             log.error("查询考勤规则失败:" + e.getMessage());
@@ -921,6 +929,57 @@
         return map;
     }
 
+    /**
+     *    打印报表   辅警干警
+     * @param searchBean
+     * @param map
+     * @return
+     */
+    @GetMapping("/print/printpreport")
+    public String printLaborCount(@ModelAttribute("searchBean") AttedtlSearchBean searchBean,
+                                  @RequestParam(value = "opercode",required = false) String opercode,ModelMap map) {
+        try {
+            TOperator operUser=managerService.getOperatorByOpercode(opercode);
+            String opertype=operUser.getOpertype();
+            String deptcode=operUser.getDeptcode();
+            if (!StringUtil.isEmpty(opertype) &&(opertype.equals("S")||opertype.equals("P"))){
+                deptcode=null;
+            }else {
+                if(StringUtil.isEmpty(deptcode)){
+                    deptcode="-99";
+                }
+            }
+            List<TDept> deptlist=systemService.findAllDept();
+            TDept tdept=null;
+            for(TDept dept:deptlist){
+                if(dept.getDeptcode().equals(deptcode)){
+                    tdept=dept;
+                }
+            }
+            map.addAttribute("deptname", tdept == null ? "unknow" :tdept.getDeptname());
+            map.addAttribute("startdate",DateUtil.reformatDatetime(searchBean.getStartdate(),"yyyyMMdd","yyyy-MM-dd"));
+            map.addAttribute("enddate",DateUtil.reformatDatetime(searchBean.getEnddate(),"yyyyMMdd","yyyy-MM-dd"));
+            searchBean.setDeptcode(deptcode);
+            List<AtteReport> list=atteClassService.getPReportList(searchBean);
+            map.addAttribute("showlist", list);
+            if(list!=null&&list.size()>0){
+                Sum sum=new Sum();
+                for(AtteReport report:list){
+                    sum.setCnt1(sum.getCnt1()+report.getCnt1());
+                    sum.setCnt2(sum.getCnt2()+report.getCnt2());
+                    sum.setCnt3(sum.getCnt3()+report.getCnt3());
+                    sum.setCnt4(sum.getCnt4()+report.getCnt4());
+                    sum.setCnts(sum.getCnts()+report.getCnts());
+                }
+                map.addAttribute("sum",sum);
+            }
+            map.addAttribute("opername", operUser == null ? "unknow" : operUser.getOpername());
+            map.addAttribute("printdatetime",DateUtil.reformatDatetime(systemUtilService.getSysdatetime().getHostdatetime(),DateUtil.DATETIME_FMT,"yyyy-MM-dd HH:mm:ss"));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return "atte/report/print/p_printindex";
+    }
 
     public static void main(String[] args) {
         String s1=DateUtil.getNow("yyyyMMdd")+"140000";
diff --git a/src/main/java/com/supwisdom/dlpay/atte/dao/AtteClassDao.java b/src/main/java/com/supwisdom/dlpay/atte/dao/AtteClassDao.java
index 7fc16d7..6896e79 100644
--- a/src/main/java/com/supwisdom/dlpay/atte/dao/AtteClassDao.java
+++ b/src/main/java/com/supwisdom/dlpay/atte/dao/AtteClassDao.java
@@ -1,6 +1,7 @@
 package com.supwisdom.dlpay.atte.dao;
 
 import com.supwisdom.dlpay.atte.bean.AtteDtl;
+import com.supwisdom.dlpay.atte.bean.AtteReport;
 import com.supwisdom.dlpay.atte.bean.AttedtlSearchBean;
 import com.supwisdom.dlpay.atte.bean.CustSearchBean;
 import com.supwisdom.dlpay.atte.domain.TAtteClass;
@@ -72,4 +73,5 @@
 
     //辅警干警报表
     public Pagination getPReportWithPage(AttedtlSearchBean searchBean,int pageNo,int pageSize);
+    public List<AtteReport> getPReportList(AttedtlSearchBean searchBean);
 }
diff --git a/src/main/java/com/supwisdom/dlpay/atte/dao/impl/AtteClassDaoImpl.java b/src/main/java/com/supwisdom/dlpay/atte/dao/impl/AtteClassDaoImpl.java
index 82fcf3b..7262bad 100644
--- a/src/main/java/com/supwisdom/dlpay/atte/dao/impl/AtteClassDaoImpl.java
+++ b/src/main/java/com/supwisdom/dlpay/atte/dao/impl/AtteClassDaoImpl.java
@@ -674,8 +674,8 @@
     @Override
     public Pagination getPReportWithPage(AttedtlSearchBean searchBean, int pageNo, int pageSize) {
         StringBuffer sql=new StringBuffer();
-        sql.append(" with a as ( select v.*,c.cardno from v_atte_info v left join t_card c on v. custid=c.custid    ")
-            .append(" where  c.status='normal' and c.transtatus='normal' ");
+        sql.append(" with a as ( select v.*,c.cardno,ct.custtypename,d.deptname from v_atte_info v left join t_card c on v. custid=c.custid  left join tb_custtype ct on v.custtypeid=ct.custtypeid left join tb_dept d on v.deptcode=d.deptcode   ")
+            .append(" where  c.status='normal' and c.transtatus='normal'   ");
         if(!StringUtil.isEmpty(searchBean.getStartdate())&&!StringUtil.isEmpty(searchBean.getEnddate())){
             sql.append(" and v.attedate between :sdate and :edate ");
         }
@@ -689,15 +689,15 @@
             sql.append("  and v.deptcode = :dcode ");
         }
         if(!StringUtil.isEmpty(searchBean.getCardno())){
-            sql.append("  and v.cardno like :cno ");
+            sql.append("  and c.cardno like :cno ");
         }
-        sql.append(" ) select a.custid,a.custname,a.cardno,a.custtypeid,a.deptcode, ")
-        .append(" (select count(*) from v_atte_info where custid=a.custid  ) cnts,")
-                .append(" (select count(*) from v_atte_info where custid=a.custid and state=1) cnt1,")
-                .append(" (select count(*) from v_atte_info where custid=a.custid and state=2) cnt2,")
-                .append(" (select count(*) from v_atte_info where custid=a.custid and state=3) cnt3,")
-                .append(" (select count(*) from v_atte_info where custid=a.custid and state=0) cnt4")
-        .append(" from a group by a.custname,a.cardno,a.custtypeid,a.deptcode,a.custid ")
+        sql.append(" ) select a.custid,a.custname,a.cardno,a.custtypeid,a.deptcode,a.deptname,a.custtypename, ")
+        .append(" (select count(*) from a aa where aa.custid=a.custid  ) cnts,")
+                .append(" (select count(*) from a aa where aa.custid=a.custid and aa.state=1) cnt1,")
+                .append(" (select count(*) from a aa where aa.custid=a.custid and aa.state=2) cnt2,")
+                .append(" (select count(*) from a aa where aa.custid=a.custid and aa.state=3) cnt3,")
+                .append(" (select count(*) from a aa where aa.custid=a.custid and aa.state=0) cnt4")
+        .append(" from a group by a.custname,a.cardno,a.custtypeid,a.deptcode,a.custid,a.deptname,a.custtypename  ")
          .append(" order by a.deptcode desc ,a.custtypeid desc ");
         Query query=entityManager.createNativeQuery(sql.toString(), AtteReport.class);
         if(!StringUtil.isEmpty(searchBean.getStartdate())&&!StringUtil.isEmpty(searchBean.getEnddate())){
@@ -705,10 +705,10 @@
             query.setParameter("edate",searchBean.getEnddate());
         }
         if(!StringUtil.isEmpty(searchBean.getCustname())){
-            query.setParameter("cname",searchBean.getCustname());
+            query.setParameter("cname","%"+searchBean.getCustname()+"%");
         }
         if(!StringUtil.isEmpty(searchBean.getCusttypeid())){
-           query.setParameter("ctypeid",searchBean.getCusttypeid());
+           query.setParameter("ctypeid",Integer.parseInt(searchBean.getCusttypeid()));
         }
         if(!StringUtil.isEmpty(searchBean.getDeptcode())){
            query.setParameter("dcode",searchBean.getDeptcode());
@@ -746,7 +746,7 @@
             sql.append("  and v.deptcode = :dcode ");
         }
         if(!StringUtil.isEmpty(searchBean.getCardno())){
-            sql.append("  and v.cardno like :cno ");
+            sql.append("  and c.cardno like :cno ");
         }
         sql.append(" ),  b as ( select distinct custid from a ) ")
                 .append("select count(*) from b ");
@@ -756,10 +756,10 @@
             query.setParameter("edate",searchBean.getEnddate());
         }
         if(!StringUtil.isEmpty(searchBean.getCustname())){
-            query.setParameter("cname",searchBean.getCustname());
+            query.setParameter("cname","%"+searchBean.getCustname()+"%");
         }
         if(!StringUtil.isEmpty(searchBean.getCusttypeid())){
-            query.setParameter("ctypeid",searchBean.getCusttypeid());
+            query.setParameter("ctypeid",Integer.parseInt(searchBean.getCusttypeid()));
         }
         if(!StringUtil.isEmpty(searchBean.getDeptcode())){
             query.setParameter("dcode",searchBean.getDeptcode());
@@ -774,4 +774,54 @@
         }
         return result;
     }
+
+    @Override
+    public List<AtteReport> getPReportList(AttedtlSearchBean searchBean) {
+        StringBuffer sql=new StringBuffer();
+        sql.append(" with a as ( select v.*,c.cardno,ct.custtypename,d.deptname from v_atte_info v left join t_card c on v. custid=c.custid left join tb_custtype ct on v.custtypeid=ct.custtypeid left join tb_dept d on v.deptcode=d.deptcode   ")
+                .append(" where  c.status='normal' and c.transtatus='normal' ");
+        if(!StringUtil.isEmpty(searchBean.getStartdate())&&!StringUtil.isEmpty(searchBean.getEnddate())){
+            sql.append(" and v.attedate between :sdate and :edate ");
+        }
+        if(!StringUtil.isEmpty(searchBean.getCustname())){
+            sql.append("  and v.custname like :cname ");
+        }
+        if(!StringUtil.isEmpty(searchBean.getCusttypeid())){
+            sql.append("  and v.custtypeid = :ctypeid ");
+        }
+        if(!StringUtil.isEmpty(searchBean.getDeptcode())){
+            sql.append("  and v.deptcode = :dcode ");
+        }
+        if(!StringUtil.isEmpty(searchBean.getCardno())){
+            sql.append("  and c.cardno like :cno ");
+        }
+        sql.append(" ) select a.custid,a.custname,a.cardno,a.custtypeid,a.deptcode,a.custtypename,a.deptname, ")
+                .append(" (select count(*) from a aa where aa.custid=a.custid  ) cnts,")
+                .append(" (select count(*) from a aa where aa.custid=a.custid and aa.state=1) cnt1,")
+                .append(" (select count(*) from a aa where aa.custid=a.custid and aa.state=2) cnt2,")
+                .append(" (select count(*) from a aa where aa.custid=a.custid and aa.state=3) cnt3,")
+                .append(" (select count(*) from a aa where aa.custid=a.custid and aa.state=0) cnt4")
+                .append(" from a group by a.custname,a.cardno,a.custtypeid,a.deptcode,a.custid,a.custtypename,a.deptname ")
+                .append(" order by a.deptcode desc ,a.custtypeid desc ");
+        Query query=entityManager.createNativeQuery(sql.toString(), AtteReport.class);
+
+        if(!StringUtil.isEmpty(searchBean.getStartdate())&&!StringUtil.isEmpty(searchBean.getEnddate())){
+            query.setParameter("sdate",searchBean.getStartdate());
+            query.setParameter("edate",searchBean.getEnddate());
+        }
+        if(!StringUtil.isEmpty(searchBean.getCustname())){
+            query.setParameter("cname","%"+searchBean.getCustname()+"%");
+        }
+        if(!StringUtil.isEmpty(searchBean.getCusttypeid())){
+            query.setParameter("ctypeid",Integer.parseInt(searchBean.getCusttypeid()));
+        }
+        if(!StringUtil.isEmpty(searchBean.getDeptcode())){
+            query.setParameter("dcode",searchBean.getDeptcode());
+        }
+        if(!StringUtil.isEmpty(searchBean.getCardno())){
+            query.setParameter("cno",searchBean.getCardno());
+        }
+        List<AtteReport> list=query.getResultList();
+        return list;
+    }
 }
diff --git a/src/main/java/com/supwisdom/dlpay/atte/service/AtteClassService.java b/src/main/java/com/supwisdom/dlpay/atte/service/AtteClassService.java
index 0f3a766..c184388 100644
--- a/src/main/java/com/supwisdom/dlpay/atte/service/AtteClassService.java
+++ b/src/main/java/com/supwisdom/dlpay/atte/service/AtteClassService.java
@@ -1,6 +1,7 @@
 package com.supwisdom.dlpay.atte.service;
 
 import com.supwisdom.dlpay.atte.bean.AtteDtl;
+import com.supwisdom.dlpay.atte.bean.AtteReport;
 import com.supwisdom.dlpay.atte.bean.AttedtlSearchBean;
 import com.supwisdom.dlpay.atte.domain.TAtteClass;
 import com.supwisdom.dlpay.atte.domain.TAtteDtl;
@@ -85,4 +86,7 @@
     // 考勤报表
     @Transactional(propagation = Propagation.REQUIRED,rollbackFor = {Exception.class})
     public Pagination getPReportWithPage(AttedtlSearchBean searchBean,int pageNo,int pageSize);
+
+    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = {Exception.class})
+    public List<AtteReport> getPReportList(AttedtlSearchBean searchBean);
 }
diff --git a/src/main/java/com/supwisdom/dlpay/atte/service/impl/AtteClassServiceImpl.java b/src/main/java/com/supwisdom/dlpay/atte/service/impl/AtteClassServiceImpl.java
index 9cb2372..b622d79 100644
--- a/src/main/java/com/supwisdom/dlpay/atte/service/impl/AtteClassServiceImpl.java
+++ b/src/main/java/com/supwisdom/dlpay/atte/service/impl/AtteClassServiceImpl.java
@@ -1,6 +1,7 @@
 package com.supwisdom.dlpay.atte.service.impl;
 
 import com.supwisdom.dlpay.atte.bean.AtteDtl;
+import com.supwisdom.dlpay.atte.bean.AtteReport;
 import com.supwisdom.dlpay.atte.bean.AttedtlSearchBean;
 import com.supwisdom.dlpay.atte.bean.CustSearchBean;
 import com.supwisdom.dlpay.atte.dao.AtteClassDao;
@@ -410,4 +411,9 @@
     public Pagination getPReportWithPage(AttedtlSearchBean searchBean, int pageNo, int pageSize) {
         return atteClassDao.getPReportWithPage(searchBean,pageNo,pageSize);
     }
+
+    @Override
+    public List<AtteReport> getPReportList(AttedtlSearchBean searchBean) {
+        return atteClassDao.getPReportList(searchBean);
+    }
 }
diff --git a/src/main/kotlin/com/supwisdom/dlpay/security.kt b/src/main/kotlin/com/supwisdom/dlpay/security.kt
index cfd7f4c..c264b71 100644
--- a/src/main/kotlin/com/supwisdom/dlpay/security.kt
+++ b/src/main/kotlin/com/supwisdom/dlpay/security.kt
@@ -198,6 +198,7 @@
                         .antMatchers("/login", "/login/form","/app/**").permitAll()
                         .antMatchers("/static/**").permitAll()
                         .antMatchers("/code/image").permitAll()
+                        .antMatchers("/atte/print/**").permitAll()
                         .antMatchers("/**").hasAnyRole("USER", "ADMIN")
                         .anyRequest().authenticated()
                         .and()
diff --git a/src/main/resources/atte.sql b/src/main/resources/atte.sql
index 87bab66..0d1fcae 100644
--- a/src/main/resources/atte.sql
+++ b/src/main/resources/atte.sql
@@ -20,11 +20,66 @@
 INSERT INTO "tb_businesspara" VALUES ('atte_min', '60');
 INSERT INTO "tb_businesspara" VALUES ('atte_emin', '60');
 
+create view v_atte_info as WITH a AS (
+SELECT t.custid,
+t.attedate,
+CASE
+WHEN (EXISTS ( SELECT d.atteno,
+d.custid,
+d.attedate,
+d.timeid,
+d.state,
+d.status,
+d.remark,
+d.oldstate,
+d.operid,
+d.updatetime
+FROM t_atte_dtl d
+WHERE (((t.custid)::text = (d.custid)::text) AND ((t.attedate)::text = (d.attedate)::text) AND (d.state = 0)))) THEN 0
+WHEN (EXISTS ( SELECT d.atteno,
+d.custid,
+d.attedate,
+d.timeid,
+d.state,
+d.status,
+d.remark,
+d.oldstate,
+d.operid,
+d.updatetime
+FROM t_atte_dtl d
+WHERE (((t.custid)::text = (d.custid)::text) AND ((t.attedate)::text = (d.attedate)::text) AND (d.state = 3)))) THEN 3
+WHEN (EXISTS ( SELECT d.atteno,
+d.custid,
+d.attedate,
+d.timeid,
+d.state,
+d.status,
+d.remark,
+d.oldstate,
+d.operid,
+d.updatetime
+FROM t_atte_dtl d
+WHERE (((t.custid)::text = (d.custid)::text) AND ((t.attedate)::text = (d.attedate)::text) AND (d.state = 2)))) THEN 2
+ELSE 1
+END AS state
+FROM t_atte_dtl t
+GROUP BY t.custid, t.attedate
+ORDER BY t.attedate DESC
+)
+SELECT a.custid,
+       a.attedate,
+       a.state,
+       c.custname,
+       c.custtypeid,
+       c.deptcode
+FROM (a
+  LEFT JOIN t_customer c ON (((a.custid)::text = (c.custid)::text)));
 
-INSERT INTO "tb_function"  VALUES (47, NULL, 1, NULL, '', '/atte/dtl/index', '考勤流水', NULL, 36, NULL);
-INSERT INTO "tb_function"  VALUES (45, NULL, 1, NULL, '', '/atte/timedtl/index', '考勤状态维护', NULL, 36, NULL);
-INSERT INTO "tb_function"  VALUES (37, NULL, 1, NULL, '', '/atte/rule/index', '考勤规则管理', NULL, 36, NULL);
-INSERT INTO "tb_function"  VALUES (36, NULL, 0, NULL, 'layui-icon-set', '#', '人员考勤', 36, -1, NULL);
-INSERT INTO "tb_function"  VALUES (42, NULL, 1, NULL, '', '/atte/class/index', '手动排班', NULL, 36, NULL);
-INSERT INTO "tb_function"  VALUES (48, NULL, 1, NULL, '', '#', '审核人管理', NULL, 36, NULL);
+INSERT INTO "tb_function" ("id", "createtime", "isleaf", "lastsaved", "menuicon", "menuurl", "name", "ordernum", "parentid", "grade") VALUES ('47', NULL, '1', NULL, '', '/atte/dtl/index', '考勤流水', NULL, '36', NULL);
+INSERT INTO "tb_function" ("id", "createtime", "isleaf", "lastsaved", "menuicon", "menuurl", "name", "ordernum", "parentid", "grade") VALUES ('45', NULL, '1', NULL, '', '/atte/timedtl/index', '考勤状态维护', NULL, '36', NULL);
+INSERT INTO "tb_function" ("id", "createtime", "isleaf", "lastsaved", "menuicon", "menuurl", "name", "ordernum", "parentid", "grade") VALUES ('37', NULL, '1', NULL, '', '/atte/rule/index', '考勤规则管理', NULL, '36', NULL);
+INSERT INTO "tb_function" ("id", "createtime", "isleaf", "lastsaved", "menuicon", "menuurl", "name", "ordernum", "parentid", "grade") VALUES ('49', NULL, '1', NULL, '', '/atte/police/index', '考勤报表', NULL, '36', NULL);
+INSERT INTO "tb_function" ("id", "createtime", "isleaf", "lastsaved", "menuicon", "menuurl", "name", "ordernum", "parentid", "grade") VALUES ('36', NULL, '0', NULL, 'layui-icon-set', '#', '人员考勤', '36', '-1', NULL);
+INSERT INTO "tb_function" ("id", "createtime", "isleaf", "lastsaved", "menuicon", "menuurl", "name", "ordernum", "parentid", "grade") VALUES ('42', NULL, '1', NULL, '', '/atte/class/index', '手动排班', NULL, '36', NULL);
+INSERT INTO "tb_function" ("id", "createtime", "isleaf", "lastsaved", "menuicon", "menuurl", "name", "ordernum", "parentid", "grade") VALUES ('48', NULL, '1', NULL, '', '/atte/review/index', '审核人管理', NULL, '36', NULL);
 
diff --git a/src/main/resources/static/libs/CLodop/CLodop_Setup_for_Win32NT_https_3.093Extend.exe b/src/main/resources/static/libs/CLodop/CLodop_Setup_for_Win32NT_https_3.093Extend.exe
new file mode 100644
index 0000000..9988d28
--- /dev/null
+++ b/src/main/resources/static/libs/CLodop/CLodop_Setup_for_Win32NT_https_3.093Extend.exe
Binary files differ
diff --git a/src/main/resources/static/libs/CLodop/LodopFuncs.js b/src/main/resources/static/libs/CLodop/LodopFuncs.js
new file mode 100644
index 0000000..86d840a
--- /dev/null
+++ b/src/main/resources/static/libs/CLodop/LodopFuncs.js
@@ -0,0 +1,144 @@
+var CreatedOKLodop7766 = null, CLodopIsLocal;
+
+//====判断是否需要 Web打印服务CLodop:===
+//===(不支持插件的浏览器版本需要用它)===
+function needCLodop() {
+    try {        
+        return true;
+    } catch (err) {
+        return true;
+    }
+}
+
+//====页面引用CLodop云打印必须的JS文件,用双端口(8000和18000)避免其中某个被占用:====
+if (needCLodop()) {
+    // https
+    var src1 = "https://localhost:8443/CLodopfuncs.js?priority=1";
+    var src2 = "https://localhost:8444/CLodopfuncs.js?priority=0";
+
+    //http
+    // var src1 = "http://localhost:8000/CLodopfuncs.js?priority=1";
+    // var src2 ="http://localhost:18000/CLodopfuncs.js?priority=0";
+
+    var head = document.head || document.getElementsByTagName("head")[0] || document.documentElement;
+    var oscript = document.createElement("script");
+    oscript.src = src1;
+    head.insertBefore(oscript, head.firstChild);
+    oscript = document.createElement("script");
+    oscript.src = src2;
+    head.insertBefore(oscript, head.firstChild);
+    CLodopIsLocal = !!((src1 + src2).match(/\/\/localho|\/\/127.0.0./i));
+}
+
+//====获取LODOP对象的主过程:====
+function getLodop(oOBJECT, oEMBED) {
+    // debugger
+    var baseUrl = window.location.pathname;
+    var strHtmInstall = "<br><font color='#FF00FF'>打印控件未安装!点击这里<a href='"+baseUrl+"static/libs/CLodop/install_lodop32.exe' target='_self'>执行安装</a>,安装后请刷新页面或重新进入。</font>";
+    var strHtmUpdate = "<br><font color='#FF00FF'>打印控件需要升级!点击这里<a href='"+baseUrl+"static/libs/CLodop/install_lodop32.exe' target='_self'>执行升级</a>,升级后请重新进入。</font>";
+    var strHtm64_Install = "<br><font color='#FF00FF'>打印控件未安装!点击这里<a href='"+baseUrl+"static/libs/CLodop/install_lodop64.exe' target='_self'>执行安装</a>,安装后请刷新页面或重新进入。</font>";
+    var strHtm64_Update = "<br><font color='#FF00FF'>打印控件需要升级!点击这里<a href='"+baseUrl+"static/libs/CLodop/install_lodop64.exe' target='_self'>执行升级</a>,升级后请重新进入。</font>";
+    var strHtmFireFox = "<br><font color='#FF00FF'>(注意:如曾安装过Lodop旧版附件npActiveXPLugin,请在【工具】->【附加组件】->【扩展】中先卸它)</font>";
+    var strHtmChrome = "<font color='#FF00FF'>(如果此前正常,仅因浏览器升级或重安装而出问题,需重新执行以上安装)</font>";
+    var strCLodopInstall_1 = "<font color='#FF00FF'>Web打印服务CLodop未安装启动,点击这里<a href='"+baseUrl+"static/libs/CLodop/CLodop_Setup_for_Win32NT_https_3.093Extend.exe' target='_self'>下载执行安装</a>";
+    var strCLodopInstall_2 = "<br>(若此前已安装过,可<a href='CLodop.protocol:setup' target='_self'>点这里直接再次启动</a>)";
+    var strCLodopInstall_3 = ",成功后请刷新本页面。</font>";
+    var strCLodopUpdate = "<font color='#FF00FF'>Web打印服务CLodop需升级!点击这里<a href='"+baseUrl+"static/libs/CLodop/CLodop_Setup_for_Win32NT_https_3.093Extend.exe' target='_self'>执行升级</a>,升级后请刷新页面。</font>";
+    var LODOP;
+    try {
+        var ua = navigator.userAgent;
+        var isIE = !!(ua.match(/MSIE/i)) || !!(ua.match(/Trident/i));
+        if (needCLodop()) {
+            try {
+                LODOP = getCLodop();
+            } catch (err) {}
+            if (!LODOP && document.readyState !== "complete") {
+                // alert("网页还没下载完毕,请稍等一下再操作.");
+                layer.msg("网页还没下载完毕,请稍等一下再操作.",{icon: 0});
+                return;
+            }
+            if (!LODOP) {
+                // document.body.innerHTML = strCLodopInstall_1 + (CLodopIsLocal ? strCLodopInstall_2 : "") + strCLodopInstall_3 + document.body.innerHTML;
+                layer.open({
+                    title: '安装CLodop插件',
+                    area: '500px',
+                    content: strCLodopInstall_1 + (CLodopIsLocal ? strCLodopInstall_2 : "") + strCLodopInstall_3
+                });
+                return;
+            } else {
+                if (CLODOP.CVERSION < "3.0.4.8") {
+                    // document.body.innerHTML = strCLodopUpdate + document.body.innerHTML;
+                    layer.open({
+                        title: '安装CLodop插件',
+                        area: '500px',
+                        content: strCLodopUpdate
+                    });
+                }
+                if (oEMBED && oEMBED.parentNode)
+                    oEMBED.parentNode.removeChild(oEMBED);
+                if (oOBJECT && oOBJECT.parentNode)
+                    oOBJECT.parentNode.removeChild(oOBJECT);
+            }
+        } else {
+            var is64IE = isIE && !!(ua.match(/x64/i));
+            //=====如果页面有Lodop就直接使用,没有则新建:==========
+            if (oOBJECT || oEMBED) {
+                if (isIE)
+                    LODOP = oOBJECT;
+                else
+                    LODOP = oEMBED;
+            } else if (!CreatedOKLodop7766) {
+                LODOP = document.createElement("object");
+                LODOP.setAttribute("width", 0);
+                LODOP.setAttribute("height", 0);
+                LODOP.setAttribute("style", "position:absolute;left:0px;top:-100px;width:0px;height:0px;");
+                if (isIE)
+                    LODOP.setAttribute("classid", "clsid:2105C259-1E0C-4534-8141-A753534CB4CA");
+                else
+                    LODOP.setAttribute("type", "application/x-print-lodop");
+                document.documentElement.appendChild(LODOP);
+                CreatedOKLodop7766 = LODOP;
+            } else
+                LODOP = CreatedOKLodop7766;
+            //=====Lodop插件未安装时提示下载地址:==========
+            if ((!LODOP) || (!LODOP.VERSION)) {
+                var tipmsg = "";
+                if (ua.indexOf('Chrome') >= 0){
+                    // document.body.innerHTML = strHtmChrome + document.body.innerHTML;
+                    tipmsg +=strHtmChrome;
+                }
+
+                if (ua.indexOf('Firefox') >= 0){
+                    // document.body.innerHTML = strHtmFireFox + document.body.innerHTML;
+                    tipmsg += strHtmFireFox;
+                }
+                // document.body.innerHTML = (is64IE ? strHtm64_Install : strHtmInstall) + document.body.innerHTML;
+                tipmsg += (is64IE ? strHtm64_Install : strHtmInstall)
+                layer.open({
+                    title: '安装CLodop插件',
+                    area: '500px',
+                    content: tipmsg
+                });
+                return LODOP;
+            }
+        }
+        if (LODOP.VERSION < "6.2.2.3") {
+            if (!needCLodop()){
+                // document.body.innerHTML = (is64IE ? strHtm64_Update : strHtmUpdate) + document.body.innerHTML;
+                layer.open({
+                    title: '安装CLodop插件',
+                    area: '500px',
+                    content: (is64IE ? strHtm64_Update : strHtmUpdate)
+                });
+            }
+            return LODOP;
+        }
+        //===如下空白位置适合调用统一功能(如注册语句、语言选择等):===
+
+        //=======================================================
+        return LODOP;
+    } catch (err) {
+        // alert("getLodop出错:" + err);
+        layer.msg("getLodop出错:" + err, {icon: 2});
+    }
+}
diff --git a/src/main/resources/static/libs/CLodop/install_lodop32.exe b/src/main/resources/static/libs/CLodop/install_lodop32.exe
new file mode 100644
index 0000000..93cf607
--- /dev/null
+++ b/src/main/resources/static/libs/CLodop/install_lodop32.exe
Binary files differ
diff --git a/src/main/resources/static/libs/CLodop/install_lodop64.exe b/src/main/resources/static/libs/CLodop/install_lodop64.exe
new file mode 100644
index 0000000..a81c111
--- /dev/null
+++ b/src/main/resources/static/libs/CLodop/install_lodop64.exe
Binary files differ
diff --git a/src/main/resources/templates/atte/report/p_index.html b/src/main/resources/templates/atte/report/p_index.html
index 215995e..dd6b6ec 100644
--- a/src/main/resources/templates/atte/report/p_index.html
+++ b/src/main/resources/templates/atte/report/p_index.html
@@ -1,9 +1,9 @@
 <div class="layui-card">
     <div class="layui-card-header">
-        <h2 class="header-title">辅警干警考勤报表</h2>
+        <h2 class="header-title">考勤报表</h2>
         <span class="layui-breadcrumb pull-right">
           <a href="#">人员考勤</a>
-          <a><cite>辅警干警考勤报表</cite></a>
+          <a><cite>考勤报表</cite></a>
         </span>
     </div>
     <div class="layui-card-body" >
@@ -76,6 +76,7 @@
                         </label>
                         <div class="col-md-8 col-sm-12 col-xs-12">
                         <button type="button" class="btn btn-info" @click="query" id="attedtl_qrybtn">查 询</button>
+                        <button type="button" class="btn btn-info" @click="print" id="print_preport">打印</button>
                         </div>
                     </div>
                 </div>
@@ -105,15 +106,13 @@
                     >
                     </el-table-column>
                     <el-table-column
-                            prop="custtypeid"
+                            prop="custtypename"
                             label="人员类别"
-                            :formatter="custtypefor"
                            >
                     </el-table-column>
                     <el-table-column
-                            prop="deptcode"
+                            prop="deptname"
                             label="部门"
-                            :formatter="deptfor"
                     >
                     </el-table-column>
                     <el-table-column
@@ -244,6 +243,10 @@
                 this.currPage=1;
                 attedtl_commonQuery(this,this.currPage,this.pageSize);
             },
+            print:function () {
+                that=this;
+                print(that);
+            },
             resetForm:function(formName) {
                 this.$refs[formName].resetFields();
                 this.dialogFormVisible = false
@@ -252,17 +255,7 @@
                 this.$refs[formName].resetFields();
                 this.dialogFormVisible = false
             },
-            saveState:function (formName) {
 
-                 var _that=this;
-                    attedtl_saveData(_that,formName);
-
-            },
-            editDtl:function (row) {
-                 dtl_getFillData(this,row);
-                 this.dialogFormVisible = true;
-                 this.updatetitle="修改流水状态"
-            },
             custtypefor:function (row) {
                 return custtype_grpname(row.custtypeid);
             },
@@ -313,6 +306,7 @@
                     }
                     _self.deptlist=deptlist;
                     _self.typegrplist=custtypelist;
+                    _self.oper=ret.operator;
                 }
             })
         }
@@ -483,8 +477,29 @@
     function dtl_refreshThisTable(){
         attedtl_commonQuery(polreport_vue,polreport_vue.currPage,polreport_vue.pageSize);
     };
+    var LODOP;
+    function print(that){
+        var startdate=class_Formatdate(that.preportform.startdate);
+        var enddate=class_Formatdate(that.preportform.enddate);
+        var custtypeid=that.preportform.custtypeid;
+        var custname=that.preportform.custname;
+        var cardno=that.preportform.cardno;
+        var opercode=that.oper.opercode;
+        var url = '/atte/print/printpreport?startdate=' + startdate + '&enddate=' + enddate + '&custtypeid=' + custtypeid + '&custname=' + custname+"&cardno="+cardno+"&opercode="+opercode;
 
+        LODOP = getLodop();
+        LODOP.PRINT_INIT("考勤报表");
+        LODOP.SET_PRINT_PAGESIZE(2, 0, 0,"A4");
+        LODOP.ADD_PRINT_URL(30, 20, "95%", "90%", encodeURI(url));
+        LODOP.ADD_PRINT_HTM("95%", "48%", 150, 50, "<font style='font-size:12px'><span tdata='pageNO'>##</span>/<span tdata='pageCount'>&nbsp;&nbsp;##</span></font>");
+        LODOP.SET_PRINT_STYLEA(0, "ItemType", 1);
+        LODOP.SET_PRINT_STYLEA(0, "HOrient", 3);
+        LODOP.SET_PRINT_STYLEA(0, "VOrient", 3);
+        LODOP.SET_SHOW_MODE("NP_NO_RESULT", true);
+        LODOP.SET_PRINT_MODE("FULL_WIDTH_FOR_OVERFLOW",true);
+        LODOP.PREVIEW();
 
+    }
 
 
 
diff --git a/src/main/resources/templates/atte/report/print/p_printindex.html b/src/main/resources/templates/atte/report/print/p_printindex.html
new file mode 100644
index 0000000..d81651b
--- /dev/null
+++ b/src/main/resources/templates/atte/report/print/p_printindex.html
@@ -0,0 +1,107 @@
+<!DOCTYPE html>
+<html xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
+<head>
+    <meta charset="UTF-8">
+    <title>考勤统计表</title>
+
+    <link rel="stylesheet" th:href="@{/static/libs/layui/css/layui.css}"/>
+    <link rel="stylesheet" th:href="@{/static/custom/css/custom.css}"/>
+</head>
+<body>
+<div class="layui-card">
+    <div class="layui-card-header" style="text-align: center;">
+        <h1>考勤统计表</h1>
+    </div>
+    <div class="layui-card-body">
+        <div class="layui-form toolbar">
+            <div style="float: left;padding-left: 3px;font-size:16px" th:text="${'部门:'+deptname}"></div>
+            <div style="float: left;padding-left: 10px;font-size:16px" th:text="${'时间:'+startdate +'至'+ enddate}"></div>
+        </div>
+        <table class="layui-table sw-table sw-print">
+            <thead>
+            <tr>
+                <th  style="text-align: center;">姓名</th>
+                <th  style="text-align: center;">卡号</th>
+                <th  style="text-align: center;">人员类别</th>
+                <th  style="text-align: center;">部门</th>
+                <th  style="text-align: center;">正常(天)</th>
+                <th  style="text-align: center;">迟到早退(天)</th>
+                <th  style="text-align: center;">请假(天)</th>
+                <th  style="text-align: center;">旷工(天)</th>
+                <th  style="text-align: center;">总考勤天数	</th>
+            </tr>
+            </thead>
+            <tbody>
+            <tr th:if="${null==showlist || showlist.size()==0}">
+                <td colspan="13">无数据</td>
+            </tr>
+            <div th:remove="tag" th:if="${null!=showlist && showlist.size()>0}" th:each="data:${showlist}"
+                 >
+
+                <tr >
+                    <td th:text="${data.custname}"></td>
+                    <td th:text="${data.cardno}"></td>
+                    <td th:text="${data.custtypename}"></td>
+                    <td th:text="${data.deptname}"></td>
+                    <td th:text="${data.cnt1}"></td>
+                    <td th:text="${data.cnt2}"></td>
+                    <td th:text="${data.cnt3}"></td>
+                    <td th:text="${data.cnt4}"></td>
+                    <td th:text="${data.cnts}"></td>
+                </tr>
+
+            </div>
+            <div th:if="${null!=sum}">
+                <tr>
+                    <td colspan="4" >合计:</td>
+                    <td th:text="${sum.cnt1}"></td>
+                    <td th:text="${sum.cnt2}"></td>
+                    <td th:text="${sum.cnt3}"></td>
+                    <td th:text="${sum.cnt4}"></td>
+                    <td th:text="${sum.cnts}"></td>
+                </tr>
+            </div>
+            </tbody>
+        </table>
+        <!--<div class="layui-form toolbar">-->
+            <!--<div style="float: left;padding-left: 3px;" th:text="${'制表人:'+opername+' &nbsp;&nbsp; '+ printdatetime}"></div>-->
+        <!--</div>-->
+    </div>
+    <div class="layui-card-body" style="margin-top: 25px;">
+    <div class="col-sm-12">
+        <table width="100%">
+            <tr style="height: 25px;">
+                <td width="12%" style="text-align: right;padding-right: 5px;"></td>
+                <td width="18%"
+                    style="text-align: left;" ></td>
+                <td width="5%">&nbsp;</td>
+                <td width="12%" style="text-align: right;padding-right: 5px;">制表人:</td>
+                <td width="18%"
+                    style="text-align: left;border-bottom: 1px solid #666;" th:text="${opername}"></td>
+                <td width="5%">&nbsp;</td>
+                <td width="12%" style="text-align: right;padding-right: 5px;">制表日期:</td>
+                <td width="18%"
+                    style="text-align: left;border-bottom: 1px solid #666;" th:text="${printdatetime}">
+                </td>
+            </tr>
+            <tr style="height: 25px;"></tr>
+            <tr style="height: 25px;">
+                <td width="12%" style="text-align: right;padding-right: 5px;"></td>
+                <td width="18%"
+                    style="text-align: left;" ></td>
+                <td width="5%">&nbsp;</td>
+                <td width="12%" style="text-align: right;padding-right: 5px;">审核人签字:</td>
+                <td width="18%"
+                    style="text-align: left;border-bottom: 1px solid #666;"></td>
+                <td width="5%">&nbsp;</td>
+                <td width="12%" style="text-align: right;padding-right: 5px;">盖章:</td>
+                <td width="18%"
+                    style="text-align: left;border-bottom: 1px solid #666;">
+                </td>
+            </tr>
+        </table>
+    </div>
+    </div>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html
index 9a19eeb..8b34989 100755
--- a/src/main/resources/templates/index.html
+++ b/src/main/resources/templates/index.html
@@ -28,6 +28,8 @@
     <script type="text/javascript" th:src="@{/static/libs/zTree/js/jquery.ztree.all-3.5.min.js}"></script>

     <script type="text/javascript" th:src="@{/static/libs/custom.js}"></script>

 

+    <script type="text/javascript" th:src="@{/static/libs/CLodop/LodopFuncs.js}"></script>

+

     <script type="text/javascript" th:src="@{/static/res/assets/plugins/bootstrap/js/bootstrap.min.js}"></script>

     <script type="text/javascript" th:src="@{/static/res/assets/plugins/jquery/jquery.form.js}"></script>

     <script type="text/javascript" th:src="@{/static/res/assets/plugins/validator/validator.js}"></script>