Browse Source

Merge branch 'release-hejq-201846' of ssh://10.10.101.21/source/platform-b2b into dev

hejq 7 years ago
parent
commit
1ce2d79a09
23 changed files with 1422 additions and 328 deletions
  1. 32 1
      db/ddl.sql
  2. 22 47
      src/main/java/com/uas/platform/b2b/controller/SaleApCheckController.java
  3. 16 0
      src/main/java/com/uas/platform/b2b/dao/PurcApCheckDao.java
  4. 18 0
      src/main/java/com/uas/platform/b2b/dao/PurchaseApCheckItemDao.java
  5. 144 91
      src/main/java/com/uas/platform/b2b/filter/SSOInterceptor.java
  6. 115 0
      src/main/java/com/uas/platform/b2b/model/ApCheckTable.java
  7. 40 0
      src/main/java/com/uas/platform/b2b/model/OrderRedDotAll.java
  8. 391 0
      src/main/java/com/uas/platform/b2b/model/PurcApCheck.java
  9. 2 1
      src/main/java/com/uas/platform/b2b/model/PurchaseApCheck.java
  10. 135 1
      src/main/java/com/uas/platform/b2b/model/PurchaseApCheckItem.java
  11. 1 5
      src/main/java/com/uas/platform/b2b/model/SourceForApcheck.java
  12. 9 9
      src/main/java/com/uas/platform/b2b/model/User.java
  13. 19 0
      src/main/java/com/uas/platform/b2b/service/PurchaseApCheckService.java
  14. 206 58
      src/main/java/com/uas/platform/b2b/service/impl/PurchaseApCheckServiceImpl.java
  15. 2 6
      src/main/java/com/uas/platform/b2b/service/impl/UserServiceImpl.java
  16. 1 1
      src/main/java/com/uas/platform/b2b/support/UserCreater.java
  17. 18 22
      src/main/java/com/uas/platform/b2b/v2/service/impl/EnterpriseServiceImpl.java
  18. 3 3
      src/main/java/com/uas/platform/b2b/v2/service/impl/UserServiceImpl.java
  19. 104 51
      src/main/webapp/resources/js/index/app.js
  20. 4 5
      src/main/webapp/resources/tpl/index/approvalFlow/user.html
  21. 54 14
      src/main/webapp/resources/tpl/index/fa/apCheck.html
  22. 53 13
      src/main/webapp/resources/tpl/index/fa/arCheck.html
  23. 33 0
      src/test/java/com/uas/platform/b2b/purc/PurchaseNotify.java

+ 32 - 1
db/ddl.sql

@@ -109,4 +109,35 @@ pd_vdid in (select ve_id from `purc$vendors` where ve_myenuu = 10042875);
 -- author: hejq
 -- content: 供应商客户关系表增加对账总额字段
 alter table `purc$vendors`
-  add column apcheck_count VARCHAR(200) default '' comment '对账总额(已对账和未对账之和)';
+  add column apcheck_count VARCHAR(200) default '' comment '对账总额(已对账和未对账之和)';
+
+-- date: 2018-12-28 17:19
+-- author: hejq
+-- content: 更新发货提醒判断逻辑
+-- 新增函数,返回可发货日期
+CREATE DEFINER=`sa`@`%` FUNCTION `b2b_mysql_test`.`purc_notice_delivery`(v_pn_delivery date,
+                                                                         v_pr_ltinstock int) RETURNS date
+  begin
+
+    if v_pr_ltinstock = -1 then
+      -- 	这里设置减去两个月最后一天再加上26天即指定月份的26号
+      return last_day(v_pn_delivery) + interval (-2) month + interval (26) day;
+    else
+      return v_pn_delivery - interval (v_pr_ltinstock + 1) day;
+    end if;
+  end;
+-- 更新判断方法,根据生成的可发货日期与当前日期比较,大于或等于可以发货,其他状态不能发货
+CREATE DEFINER=`sa`@`%` FUNCTION `b2b_mysql_test`.`PURC_NOTICE_WAIT_TO_SEND`(v_pn_delivery date,
+    v_pr_ltinstock int) RETURNS smallint(6)
+begin
+-- 	可以发货的时间
+declare enable_delivery date;
+
+set enable_delivery := purc_notice_delivery(v_pn_delivery, coalesce(v_pr_ltinstock, 0));
+
+if to_days(current_date()) - to_days(enable_delivery) >= 0 then
+return 0;
+else
+return 1;
+end if;
+end

+ 22 - 47
src/main/java/com/uas/platform/b2b/controller/SaleApCheckController.java

@@ -6,7 +6,6 @@ import com.uas.platform.b2b.model.ErpProdIODetail;
 import com.uas.platform.b2b.model.ErpProdIo;
 import com.uas.platform.b2b.model.OrderType;
 import com.uas.platform.b2b.model.PurchaseApCheck;
-import com.uas.platform.b2b.model.PurchaseApCheckItem;
 import com.uas.platform.b2b.model.Role;
 import com.uas.platform.b2b.model.SearchFilter;
 import com.uas.platform.b2b.model.Vendor;
@@ -20,7 +19,6 @@ import com.uas.platform.b2b.support.JxlsExcelView;
 import com.uas.platform.b2b.support.SPageUtils;
 import com.uas.platform.b2b.support.SystemSession;
 import com.uas.platform.b2b.support.UsageBufferedLogger;
-import com.uas.platform.core.exception.IllegalOperatorException;
 import com.uas.platform.core.logging.BufferedLoggerManager;
 import com.uas.platform.core.model.Constant;
 import com.uas.platform.core.model.PageInfo;
@@ -86,7 +84,7 @@ public class SaleApCheckController {
 	@Autowired
     private OrderRedDotService redDotService;
 
-	private final static UsageBufferedLogger logger = BufferedLoggerManager.getLogger(UsageBufferedLogger.class);
+	private final static UsageBufferedLogger LOGGER = BufferedLoggerManager.getLogger(UsageBufferedLogger.class);
 
 	/**
 	 * 打印权限判断
@@ -107,7 +105,7 @@ public class SaleApCheckController {
 	@RequestMapping(value = "/printCount/{id}", method = RequestMethod.POST)
 	public ResponseEntity<String> printCount(@PathVariable("id") Long id) {
 		purchaseApCheckService.print(id);
-		logger.log("应收对账单", "打印应付对账单", id.toString());
+		LOGGER.log("应收对账单", "打印应付对账单", id.toString());
 		return new ResponseEntity<>(HttpStatus.OK);
 	}
 
@@ -120,7 +118,7 @@ public class SaleApCheckController {
 	@RequestMapping("/operation/cancel")
 	public ModelMap cancelApCheck(Long id) {
 		boolean result = purchaseApCheckService.cancelApcheck(id);
-		logger.log("应收对账单", "作废应收对账单", result ? "成功" : "失败", "", id);
+		LOGGER.log("应收对账单", "作废应收对账单", result ? "成功" : "失败", "", id);
 		return new ModelMap("result", result);
 	}
 
@@ -172,7 +170,7 @@ public class SaleApCheckController {
 				}
 			}
 		}
-        logger.log("应收对账单", "获取客户信息", "获取所有符合条件的客户");
+        LOGGER.log("应收对账单", "获取客户信息", "获取所有符合条件的客户");
         return set;
 	}
 
@@ -210,7 +208,7 @@ public class SaleApCheckController {
      */
     @RequestMapping(value = "/customer", method = RequestMethod.GET)
     public SPage<Vendor> getCustomers(PageParams params, String keyword, String checkDate, String searchFilter) throws InterruptedException {
-        logger.log("应收对账单", "获取客户信息", "获取所有符合条件的客户");
+        LOGGER.log("应收对账单", "获取客户信息", "获取所有符合条件的客户");
         SearchFilter filter = JSONObject.parseObject(searchFilter, SearchFilter.class);
         return purchaseApCheckService.getCustomerInfo(params, keyword, checkDate, filter.getFromDate(), filter.getEndDate());
     }
@@ -223,34 +221,11 @@ public class SaleApCheckController {
 	 */
 	@RequestMapping(value = "/operation/save", method = RequestMethod.POST)
 	public ModelMap saveApCheck(@RequestBody String json) {
-		ModelMap map = new ModelMap();
-		Set<String> alters = new HashSet<>();
 		PurchaseApCheck apCheck = FlexJsonUtils.fromJson(json, PurchaseApCheck.class);
-		if (apCheck != null) {
-			for (PurchaseApCheckItem item : apCheck.getItems()) {
-				List<PurchaseApCheckItem> items = purchaseApCheckService
-						.findBySourceTableAndSourceId(item.getSourceTable(), item.getSourceId());
-				for (PurchaseApCheckItem newitem : items) {
-					if (newitem.getApCheck().getCheckStatus().equals("未对账")) {
-						alters.add(item.getInoutno());
-					}
-				}
-			}
-			if (alters.size() > 0) {
-				map.put("alters", alters);
-				throw new IllegalOperatorException("订单" + alters + "存在未对账的单据,请先进行对账!");
-			} else {
-				apCheck = purchaseApCheckService.save(apCheck);
-				logger.log("应收对账单", "多个单据生成同一张应收对账单", apCheck.getRemark(), null, apCheck.getId());
-				map.put("id", apCheck.getId());
-				return map;
-			}
-		} else {
-			throw new IllegalOperatorException("保存失败!");
-		}
+		return purchaseApCheckService.checkCount(apCheck);
 	}
 
-	/**
+    /**
 	 * 生成应收对账单的同时更新明细行来源表中,物料已转数
      *
 	 * @param json 对账数据
@@ -259,7 +234,7 @@ public class SaleApCheckController {
 	public void updateYCheckQty(@RequestBody String json) {
 		List<HashMap<String, Object>> list = FlexJsonUtils.fromJsonArray(json, HashMap.class);
 		purchaseApCheckService.updateYCheckQty(list);
-        logger.log("应收对账单", "生成应收对账单的同时更新明细行来源表中,物料已转数");
+        LOGGER.log("应收对账单", "生成应收对账单的同时更新明细行来源表中,物料已转数");
     }
 
 	/**
@@ -273,7 +248,7 @@ public class SaleApCheckController {
 	 */
 	@RequestMapping(value = "/{id}/info", method = RequestMethod.GET)
 	public PurchaseApCheck getCreatedPurchaseApCheckById(@PathVariable("id") Long id) {
-		logger.log("应收对账单", "查看单个应收对账单", null, null, id);
+		LOGGER.log("应收对账单", "查看单个应收对账单", null, null, id);
 		return purchaseApCheckService.findById(id);
 	}
 
@@ -284,7 +259,7 @@ public class SaleApCheckController {
 	@RequestMapping(value = "/operation/deleteApCheck", method = RequestMethod.POST)
 	public void deleteApCheck(Long id) {
 		purchaseApCheckService.deleteApCheck(id);
-        logger.log("应收对账单", "删除最新生成未提交的应收对账单", null, null, id);
+        LOGGER.log("应收对账单", "删除最新生成未提交的应收对账单", null, null, id);
     }
 
 	/**
@@ -296,7 +271,7 @@ public class SaleApCheckController {
 	public ModelMap updateApCheckStatus(Long id) {
 		ModelMap map = new ModelMap();
 		map.put("result", purchaseApCheckService.updateApCheckStatus(id));
-        logger.log("应收对账单", "提交生成的应收对账单", null, null, id);
+        LOGGER.log("应收对账单", "提交生成的应收对账单", null, null, id);
         return map;
 	}
 
@@ -309,7 +284,7 @@ public class SaleApCheckController {
 	 */
 	@RequestMapping(value = "/info/search", method = RequestMethod.GET)
 	public SPage<PurchaseApCheck> getPurchaseApChecks(PageParams params, String searchFilter) {
-		logger.log("应收对账单", "作为买家,获取全部应收对账单");
+		LOGGER.log("应收对账单", "作为买家,获取全部应收对账单");
 		SearchFilter filter = JSONObject.parseObject(searchFilter, SearchFilter.class);
 		if (StringUtils.isEmpty(filter.getKeyword())) {
             PageInfo pageInfo = new PageInfo(params);
@@ -336,7 +311,7 @@ public class SaleApCheckController {
 	 */
 	@RequestMapping(value = "/info/search", params = RequestState.TODO, method = RequestMethod.GET)
 	public SPage<PurchaseApCheck> getTodoApChecks(PageParams params, String searchFilter) {
-		logger.log("应收对账单", "获取未对账应收对账单");
+		LOGGER.log("应收对账单", "获取未对账应收对账单");
         SearchFilter filter = JSONObject.parseObject(searchFilter, SearchFilter.class);
         if (StringUtils.isEmpty(filter.getKeyword())) {
             PageInfo pageInfo = new PageInfo(params);
@@ -365,7 +340,7 @@ public class SaleApCheckController {
 	 */
 	@RequestMapping(value = "/info/search", params = RequestState.DONE, method = RequestMethod.GET)
 	public SPage<PurchaseApCheck> getDoneApChecks(PageParams params, String searchFilter) {
-		logger.log("应收对账单", "获取已对账应收对账单");
+		LOGGER.log("应收对账单", "获取已对账应收对账单");
         SearchFilter filter = JSONObject.parseObject(searchFilter, SearchFilter.class);
         if (StringUtils.isEmpty(filter.getKeyword())) {
             PageInfo pageInfo = new PageInfo(params);
@@ -401,7 +376,7 @@ public class SaleApCheckController {
 	 */
 	@RequestMapping(value = "/info/search", params = RequestState.END, method = RequestMethod.GET)
 	public SPage<PurchaseApCheck> getEndApChecks(PageParams params, String searchFilter) {
-		logger.log("应收对账单", "获取不同意,已作废应收对账单");
+		LOGGER.log("应收对账单", "获取不同意,已作废应收对账单");
         SearchFilter filter = JSONObject.parseObject(searchFilter, SearchFilter.class);
         if (StringUtils.isEmpty(filter.getKeyword())) {
             PageInfo pageInfo = new PageInfo(params);
@@ -478,7 +453,7 @@ public class SaleApCheckController {
 		modelAndView.addObject("state", "全部");
 		modelAndView.addObject("data", getPurchaseApChecks(params, searchFilter).getContent());
 		modelAndView.setView(new JxlsExcelView("classpath:jxls-tpl/fa/saleApCheck", "应收对账单列表_全部"));
-		logger.log("应收对账单", "导出Excel列表", "导出全部Excel列表");
+		LOGGER.log("应收对账单", "导出Excel列表", "导出全部Excel列表");
 		return modelAndView;
 	}
 
@@ -498,7 +473,7 @@ public class SaleApCheckController {
 		modelAndView.addObject("state", "已对账");
 		modelAndView.addObject("data", getDoneApChecks(params, searchFilter).getContent());
 		modelAndView.setView(new JxlsExcelView("classpath:jxls-tpl/fa/saleApCheck", "应收对账单列表_已对账"));
-		logger.log("应收对账单", "导出Excel列表", "导出已对账Excel列表");
+		LOGGER.log("应收对账单", "导出Excel列表", "导出已对账Excel列表");
 		return modelAndView;
 	}
 
@@ -518,7 +493,7 @@ public class SaleApCheckController {
 		modelAndView.addObject("state", "未对账");
 		modelAndView.addObject("data", getDoneApChecks(params, searchFilter).getContent());
 		modelAndView.setView(new JxlsExcelView("classpath:jxls-tpl/fa/saleApCheck", "应收对账单列表_未对账"));
-		logger.log("应收对账单", "导出Excel列表", "导出未对账Excel列表");
+		LOGGER.log("应收对账单", "导出Excel列表", "导出未对账Excel列表");
 		return modelAndView;
 	}
 
@@ -538,7 +513,7 @@ public class SaleApCheckController {
 		modelAndView.addObject("state", "已作废");
 		modelAndView.addObject("data", getEndApChecks(params, searchFilter).getContent());
 		modelAndView.setView(new JxlsExcelView("classpath:jxls-tpl/fa/saleApCheck", "应收对账单列表_已作废"));
-		logger.log("应收对账单", "导出Excel列表", "导出已做废Excel列表");
+		LOGGER.log("应收对账单", "导出Excel列表", "导出已做废Excel列表");
 		return modelAndView;
 	}
 
@@ -571,7 +546,7 @@ public class SaleApCheckController {
 		modelAndView.addObject("data", details);
         modelAndView.addObject("title", "客户应收对账单");
 		modelAndView.setView(new JxlsExcelView("classpath:jxls-tpl/fa/faApCheck", "客户应收对账单"));
-		logger.log("客户应收对账单", "导出Excel列表", "导出全部Excel列表");
+		LOGGER.log("客户应收对账单", "导出Excel列表", "导出全部Excel列表");
 		return modelAndView;
 	}
 
@@ -582,7 +557,7 @@ public class SaleApCheckController {
 	 */
 	@RequestMapping(value = "/setRead", method = RequestMethod.POST)
 	public void setReadByOrder(@RequestBody Long... sourceId) {
-        logger.log("消息红点", "设置单据已读", "设置对账单已读: " + sourceId);
+        LOGGER.log("消息红点", "设置单据已读", "设置对账单已读: " + sourceId);
         redDotService.setReadByIds(OrderType.apcheck.name(), sourceId);
 	}
 
@@ -636,7 +611,7 @@ public class SaleApCheckController {
      */
 	@RequestMapping(value = "/getBilled", method = RequestMethod.GET)
 	public Double getBilled(Long id) {
-        logger.log("应付发票", "通过id获取已开票数", "", "", id);
+        LOGGER.log("应付发票", "通过id获取已开票数", "", "", id);
         return purchaseApCheckService.getBilledByItemId(id);
 	}
 }

+ 16 - 0
src/main/java/com/uas/platform/b2b/dao/PurcApCheckDao.java

@@ -0,0 +1,16 @@
+package com.uas.platform.b2b.dao;
+
+import com.uas.platform.b2b.model.PurcApCheck;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.stereotype.Repository;
+
+/**
+ * 应收对账单
+ *
+ * @author hejq
+ * @date 2018-12-27 10:03
+ */
+@Repository
+public interface PurcApCheckDao extends JpaRepository<PurcApCheck, Long>, JpaSpecificationExecutor<PurcApCheck> {
+}

+ 18 - 0
src/main/java/com/uas/platform/b2b/dao/PurchaseApCheckItemDao.java

@@ -7,8 +7,15 @@ import org.springframework.data.jpa.repository.Query;
 import org.springframework.data.repository.query.Param;
 import org.springframework.stereotype.Repository;
 
+import java.util.Collection;
 import java.util.List;
 
+/**
+ * 应收对账单明细
+ *
+ * @author hejq
+ * @date 2018-12-27 9:20
+ */
 @Repository
 public interface PurchaseApCheckItemDao
 		extends JpaSpecificationExecutor<PurchaseApCheckItem>, JpaRepository<PurchaseApCheckItem, Long> {
@@ -22,6 +29,15 @@ public interface PurchaseApCheckItemDao
 	 */
 	List<PurchaseApCheckItem> findBySourceTableAndSourceId(String sourceTable, Long sourceId);
 
+    /**
+     * 通过sourceTable、sourceId判断是否已提交未对账
+     *
+     * @param sourceTable 来源表
+     * @param ids id集合
+     * @return 查询的数据
+     */
+	List<PurchaseApCheckItem> findBySourceTableAndSourceIdIn(String sourceTable, Collection<Long> ids);
+
 	/**
 	 * 通过id获取已开票数
 	 * @param id id
@@ -29,4 +45,6 @@ public interface PurchaseApCheckItemDao
 	 */
 	@Query("select p.billed from PurchaseApCheckItem p where p.id= :id")
 	Double getBilledById(@Param("id") Long id);
+
+	List<PurchaseApCheckItem> findByApCheckId(Long apCheckId);
 }

+ 144 - 91
src/main/java/com/uas/platform/b2b/filter/SSOInterceptor.java

@@ -13,6 +13,7 @@ import com.uas.platform.b2b.service.EnterpriseService;
 import com.uas.platform.b2b.service.RoleService;
 import com.uas.platform.b2b.service.SigninLogService;
 import com.uas.platform.b2b.service.UserService;
+import com.uas.platform.b2b.support.CollectionUtil;
 import com.uas.platform.b2b.support.SecurityConstant;
 import com.uas.platform.b2b.support.SysConf;
 import com.uas.platform.b2b.support.SystemSession;
@@ -56,6 +57,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * 访问拦截
@@ -106,6 +108,10 @@ public class SSOInterceptor extends AbstractSSOInterceptor {
 	private HashMap<String, Collection<ConfigAttribute>> resourceMap;
 	private HashMap<Long, Collection<GrantedAuthority>> authorities;
 
+    private final static String TOKEN_PARAM = "access_token";
+    private final static String TYPE_PARAM = "client_type";
+    private final static String MANAGER = "manage";
+
     /**
      * 从token获取用户信息
      *
@@ -141,9 +147,6 @@ public class SSOInterceptor extends AbstractSSOInterceptor {
 							break;
 						}
 					}
-				} else { // 如果这两个信息都不存在,判断未登录,因为存在个人账号能登录账户中心的情况
-					SystemSession.clear();
-                    authorizedUser = null;
 				}
 			}
 		}
@@ -160,18 +163,25 @@ public class SSOInterceptor extends AbstractSSOInterceptor {
 	@Override
 	protected boolean onAuthenticateFailed(HttpServletRequest request, HttpServletResponse response) {
 		SystemSession.clear();
-		User user = (User) request.getSession().getAttribute("user");
-        if (user == null) {
-			user = getUserByAccessToken(request);
-			if (user != null) {
-				user.setIp(AgentUtils.getIp(request));
-				request.getSession().setAttribute("user", user);
-				setGrantedAuthorities(user);
-			} else {
-				user = autoLogin(request);
-			}
-		}
+        String typeParam = request.getParameter(TYPE_PARAM);
+        User user;
+        if (null != typeParam && MANAGER.equals(typeParam)) {
+            user = getUserByAccessToken(request);
+            if (user != null) {
+                user.setIp(AgentUtils.getIp(request));
+                request.getSession().setAttribute("user", user);
+                setGrantedAuthorities(user);
+                SystemSession.setUser(user);
+                return true;
+            }
+        } else {
+            user = verifyUserInfo(request);
+            if (null == user) {
+                user = autoLogin(request);
+            }
+        }
 		if (user != null) {
+            checkIsPersonal(user);
             // 登录之前判断在当前企业的角色信息
             if (null != user.getEnterprise() && user.getEnterprise().getEnAdminuu().equals(user.getUserUU())) {
                 Enterprise enterprise = user.getEnterprise();
@@ -250,8 +260,7 @@ public class SSOInterceptor extends AbstractSSOInterceptor {
         String referSymbol = "Referer";
         request.getSession().setAttribute(SSOConfig.SSOReferer, request.getHeader(referSymbol));
         SSOHelper.clearLogin(request, response);
-        String redirectUrl = (SSOHelper.getRedirectLoginUrl(request, conf.getB2b()));
-        return redirectUrl;
+        return (SSOHelper.getRedirectLoginUrl(request, conf.getB2b()));
     }
 
     /**
@@ -292,46 +301,96 @@ public class SSOInterceptor extends AbstractSSOInterceptor {
      */
 	@Override
 	protected void onAuthenticateSuccess(HttpServletRequest request, HttpServletResponse response) {
-		User user = (User) request.getSession().getAttribute("user");
-		SSOToken token = SSOHelper.attrToken(request);
-		// cookie变化的情况下,session可能还未变化
-        boolean onAuthenticateFailed = user == null || (user.getUserTel() != null && !token.getUid().equals(user.getUserTel()));
-		if (onAuthenticateFailed) {
-			user = getUserByToken(token);
-			if (user != null) {
-				user.setIp(AgentUtils.getIp(request));
-				request.getSession().setAttribute("user", user);
-				setGrantedAuthorities(user);
-				log(request, user);
-			}
-		} else {
-			// 从其他应用切换了企业的情况
-			if (token.getData() != null) {
-				UserAccount tokenUser = FlexJsonUtils.fromJson(token.getData(), UserAccount.class);
-				if (!StringUtils.isEmpty(tokenUser.getSpaceUU())
-						&& !user.getEnterprise().getUu().equals(tokenUser.getSpaceUU())) {
-					user.setCurrentEnterprise(tokenUser.getSpaceUU());
-				}
-			}
-		}
-		if (user != null) {
-            // 登录之前判断在当前企业的角色信息
-            if (null != user.getEnterprise() && user.getEnterprise().getEnAdminuu().equals(user.getUserUU())) {
-                Enterprise enterprise = user.getEnterprise();
-                user = checkRoleAndReturnUserInfo(user, enterprise);
-                user.setCurrentEnterprise(enterprise.getUu());
+	    // 设置管理平台访问优先级最高
+        String typeParam = request.getParameter(TYPE_PARAM);
+        User user;
+        if (null != typeParam && MANAGER.equals(typeParam)) {
+            user = getUserByAccessToken(request);
+            if (user != null) {
+                user.setIp(AgentUtils.getIp(request));
+                request.getSession().setAttribute("user", user);
+                setGrantedAuthorities(user);
+                SystemSession.setUser(user);
             }
-			SystemSession.setUser(user);
-            setResponseAuthorized(response, user, true);
-			try {
-				accessDecision(request, user);
-			} catch (IOException e) {
-				e.printStackTrace();
-			}
-		}
+        } else {
+            user = verifyUserInfo(request);
+            if (user != null) {
+                // 判断是否个人用户
+                checkIsPersonal(user);
+                // 登录之前判断在当前企业的角色信息
+                if (null != user.getEnterprise() && user.getEnterprise().getEnAdminuu().equals(user.getUserUU())) {
+                    Enterprise enterprise = user.getEnterprise();
+                    user = checkRoleAndReturnUserInfo(user, enterprise);
+                    user.setCurrentEnterprise(enterprise.getUu());
+                }
+                SystemSession.setUser(user);
+                setResponseAuthorized(response, user, true);
+                try {
+                    accessDecision(request, user);
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
 	}
 
-	/**
+    private User verifyUserInfo(HttpServletRequest request) {
+        User user = (User) request.getSession().getAttribute("user");
+        SSOToken token = SSOHelper.attrToken(request);
+        // cookie变化的情况下,session可能还未变化
+        boolean onAuthenticateFailed = user == null || (user.getUserTel() != null && !token.getUid().equals(user.getUserTel()));
+        if (onAuthenticateFailed) {
+            user = getUserByToken(token);
+            if (user != null) {
+                user.setIp(AgentUtils.getIp(request));
+                request.getSession().setAttribute("user", user);
+                setGrantedAuthorities(user);
+                log(request, user);
+            }
+        } else {
+            // 从其他应用切换了企业的情况
+            if (token.getData() != null) {
+                UserAccount tokenUser = FlexJsonUtils.fromJson(token.getData(), UserAccount.class);
+                if (StringUtils.isEmpty(tokenUser.getSpaceUU()) && StringUtils.isEmpty(tokenUser.getBusinessCode())) {
+                    throw new AccessDeniedException("个人用户无法使用B2B商务平台");
+                }
+                Enterprise currentEnterprise = user.getEnterprise();
+                boolean changeSpace = false;
+                if (!StringUtils.isEmpty(tokenUser.getSpaceUU()) && !currentEnterprise.getUu().equals(tokenUser.getSpaceUU())) {
+                    user.setCurrentEnterprise(tokenUser.getSpaceUU());
+                    changeSpace = true;
+                } else if (StringUtils.isEmpty(tokenUser.getSpaceUU()) && !StringUtils.isEmpty(tokenUser.getBusinessCode())
+                    && !currentEnterprise.getEnBussinessCode().equals(tokenUser.getBusinessCode())) {
+                    List<Enterprise> enterpriseList = user.getEnterprises().stream()
+                        .filter(userSpace -> tokenUser.getBusinessCode().equals(userSpace.getEnBussinessCode()))
+                        .collect(Collectors.toList());
+                    if (CollectionUtil.isEmpty(enterpriseList)) {
+                        throw new AccessDeniedException(String.format("未找到关于%s的企业信息,请更换企业或账号", tokenUser.getBusinessCode()));
+                    }
+                    user.setCurrentEnterprise(enterpriseList.get(0));
+                    changeSpace = true;
+                }
+                if (changeSpace) {
+                    SystemSession.clear();
+                }
+            }
+        }
+        return user;
+    }
+
+    /**
+     * 检验是否个人用户
+     *
+     * @param user 用户信息
+     */
+    private void checkIsPersonal(User user) {
+	    boolean personalAccount = null == user.getEnterprise() || (null != user.getEnterprise() && null == user.getEnterprise().getUu());
+	    if (personalAccount) {
+            throw new AccessDeniedException("个人用户无法使用B2B商务平台");
+        }
+    }
+
+    /**
 	 * 权限验证
 	 */
 	private void accessDecision(HttpServletRequest request, User user) throws IOException {
@@ -410,7 +469,7 @@ public class SSOInterceptor extends AbstractSSOInterceptor {
 			String resourceMethod = resourceParam[0];
 			String resourceUrl = resourceParam[1];
 			AntPathRequestMatcher matcher = new AntPathRequestMatcher(resourceUrl);
-			if (null != resourceUrl && request.getMethod().equals(resourceMethod) && matcher.matches(request)) {
+			if (request.getMethod().equals(resourceMethod) && matcher.matches(request)) {
 				return resourceMap.get(resourceKey);
 			}
 		}
@@ -442,50 +501,44 @@ public class SSOInterceptor extends AbstractSSOInterceptor {
 		authorities.put(user.getUserUU(), authSet);
 	}
 
-	private final static String tokenParam = "access_token";
-	private final static String typeParam = "client_type";
-
 	/**
 	 * access_token验证登录
 	 * 
 	 * @param request
 	 */
 	private User getUserByAccessToken(HttpServletRequest request) {
-		String token = request.getParameter(tokenParam);
 		// 发现有采用access_token方式
-		if (token != null) {
-		    // 清除上一次访问的数据
-            SystemSession.clear();
-			Object sUser = request.getSession().getAttribute("user");
-			User user = null;
-			if (sUser != null) {
-				// session里面原先存在user信息,接下来要判断此user是否与token绑定的user信息一致
-				// 一致则跳过,无需再次验证;不一致则替换
-				user = (User) sUser;
-			}
-			String type = request.getParameter(typeParam);
-			String MANAGE_TYPE = "manage";
-			if (MANAGE_TYPE.equals(type)) {
-				if (user != null && UserCreater.isVirtual(user)) {
-					return user;
-				}
-				Map<String, Object> data = accessTokenService.validFormManage(token);
-				// user key
-				String USER_KEY = "user";
-				// bind key
-				String BIND_KEY = "bind";
-				if (data.containsKey(USER_KEY) && data.containsKey(BIND_KEY)) {
-					long enUU = Long.parseLong(data.get("bind").toString());
-					Enterprise enterprise = enterpriseService.findById(enUU);
-					if (enterprise != null) {
-						List<Role> roles = roleService.findByEnterprise(enUU);
-						// 虚拟用户
-						user = UserCreater.createVirtual(String.valueOf(data.get("user")), enterprise, roles);
-						return user;
-					}
-				}
-			}
-		}
+        // 清除上一次访问的数据
+        String token = request.getParameter(TOKEN_PARAM);
+        SystemSession.clear();
+        Object sUser = request.getSession().getAttribute("user");
+        User user = null;
+        if (sUser != null) {
+            // session里面原先存在user信息,接下来要判断此user是否与token绑定的user信息一致
+            // 一致则跳过,无需再次验证;不一致则替换
+            user = (User) sUser;
+        }
+        String type = request.getParameter(TYPE_PARAM);
+        if (MANAGER.equals(type)) {
+            if (user != null && UserCreater.isVirtual(user)) {
+                return user;
+            }
+            Map<String, Object> data = accessTokenService.validFormManage(token);
+            // user key
+            String userKey = "user";
+            // bind key
+            String bindKey = "bind";
+            if (data.containsKey(userKey) && data.containsKey(bindKey)) {
+                long enUU = Long.parseLong(data.get("bind").toString());
+                Enterprise enterprise = enterpriseService.findById(enUU);
+                if (enterprise != null) {
+                    List<Role> roles = roleService.findByEnterprise(enUU);
+                    // 虚拟用户
+                    user = UserCreater.createVirtual(String.valueOf(data.get("user")), enterprise, roles);
+                    return user;
+                }
+            }
+        }
 		return null;
 	}
 

+ 115 - 0
src/main/java/com/uas/platform/b2b/model/ApCheckTable.java

@@ -0,0 +1,115 @@
+package com.uas.platform.b2b.model;
+
+/**
+ * 对账表
+ *
+ * @author hejq
+ * @date 2018-12-26 14:59
+ */
+public class ApCheckTable {
+
+    /**
+     * 客户采购验收单
+     */
+    public static final String SALE_ACCEPT = "purc$acceptitem";
+
+    /**
+     * 客户采购验收单对账数量
+     */
+    public static final String SALE_ACCEPT_QTY = "pai_ycheckqty";
+
+    /**
+     * 客户采购验收单明细id
+     */
+    public static final String SALE_ACCEPT_ID = "pai_id";
+
+    /**
+     * 客户采购验退单
+     */
+    public static final String SALE_RETURN = "purc$returnitem";
+
+    /**
+     * 客户采购验退单对账数量
+     */
+    public static final String SALE_RETURN_QTY = "pri_ycheckqty";
+
+    /**
+     * 客户采购验退单明细id
+     */
+    public static final String SALE_RETURN_ID = "pri_id";
+
+    /**
+     * 不良品入库单
+     */
+    public static final String SALE_BADIN = "purc$badinitem";
+
+    /**
+     * 不良品入库单对账数量
+     */
+    public static final String SALE_BADIN_QTY = "pbi_ycheckqty";
+
+    /**
+     * 不良品入库单id
+     */
+    public static final String SALE_BADIN_ID = "pbi_id";
+
+    /**
+     * 不良品出库单对账数量
+     */
+    public static final String SALE_BADOUT_QTY = "poi_ycheckqty";
+
+    /**
+     * 不良品出库单明细id
+     */
+    public static final String SALE_BADOUT_ID = "poi_id";
+
+    /**
+     * 不良品出库单
+     */
+    public static final String SALE_BADOUT = "purc$badoutitem";
+
+    /**
+     * 货款调账单对账数量
+     */
+    public static final String ADJUSTMENT_QTY = "aa_ycheckqty";
+
+    /**
+     * 货款调账单明细id
+     */
+    public static final String ADJUSTMENT_ID = "aa_id";
+
+    /**
+     * 货款调账单
+     */
+    public static final String ADJUSTMENT = "purc$apbilladjustment";
+
+    /**
+     * 委外验收单对账数量
+     */
+    public static final String MAKE_ACCEPT_QTY = "mai_ycheckqty";
+
+    /**
+     * 委外验收单明细id
+     */
+    public static final String MAKE_ACCEPT_ID = "mai_id";
+
+    /**
+     * 委外验收单
+     */
+    public static final String MAKE_ACCEPT = "make$acceptitem";
+
+    /**
+     * 委外验退单对账数量
+     */
+    public static final String MAKE_RETURN_QTY = "mri_ycheckqty";
+
+    /**
+     * 委外验退单明细id
+     */
+    public static final String MAKE_RETURN_ID = "mri_id";
+
+    /**
+     * 委外验退单
+     */
+    public static final String MAKE_RETURN = "make$returnitem";
+}

+ 40 - 0
src/main/java/com/uas/platform/b2b/model/OrderRedDotAll.java

@@ -146,4 +146,44 @@ public class OrderRedDotAll implements Serializable {
     public void setDate(Date date) {
         this.date = date;
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof OrderRedDotAll)) {
+            return false;
+        }
+
+        OrderRedDotAll redDotAll = (OrderRedDotAll) o;
+
+        if (id != null ? !id.equals(redDotAll.id) : redDotAll.id != null) {
+            return false;
+        }
+        if (orderId != null ? !orderId.equals(redDotAll.orderId) : redDotAll.orderId != null) {
+            return false;
+        }
+        if (orderType != null ? !orderType.equals(redDotAll.orderType) : redDotAll.orderType != null) {
+            return false;
+        }
+        if (enUU != null ? !enUU.equals(redDotAll.enUU) : redDotAll.enUU != null) {
+            return false;
+        }
+        if (vendUU != null ? !vendUU.equals(redDotAll.vendUU) : redDotAll.vendUU != null) {
+            return false;
+        }
+        return date != null ? date.equals(redDotAll.date) : redDotAll.date == null;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = id != null ? id.hashCode() : 0;
+        result = 31 * result + (orderId != null ? orderId.hashCode() : 0);
+        result = 31 * result + (orderType != null ? orderType.hashCode() : 0);
+        result = 31 * result + (enUU != null ? enUU.hashCode() : 0);
+        result = 31 * result + (vendUU != null ? vendUU.hashCode() : 0);
+        result = 31 * result + (date != null ? date.hashCode() : 0);
+        return result;
+    }
 }

+ 391 - 0
src/main/java/com/uas/platform/b2b/model/PurcApCheck.java

@@ -0,0 +1,391 @@
+package com.uas.platform.b2b.model;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+import java.io.*;
+import java.util.Date;
+
+/**
+ * 买家应付(卖家应收)对账单
+ * @author hejq
+ */
+@Entity
+@Table(name = "purc$apcheck")
+public class PurcApCheck implements Serializable {
+
+	/**
+	 * 序列号
+	 */
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * ID
+	 */
+	@Id
+	@GeneratedValue(strategy = GenerationType.AUTO)
+	@Column(name = "pa_id")
+	private Long id;
+
+	/**
+	 * 对账起始日期
+	 */
+	@Column(name = "pa_begindate")
+	private Date beginDate;
+
+	/**
+	 * 对账截止日期
+	 */
+	@Column(name = "pa_enddate")
+	private Date endDate;
+
+	/**
+	 * 录单日期
+	 */
+	@Column(name = "pa_recorddate")
+	private Date recordDate;
+
+	/**
+	 * 录单人
+	 */
+	@Column(name = "pa_recorder")
+	private String recorder;
+
+	/**
+	 * 录单人UU
+	 */
+	@Column(name = "pa_recorderuu")
+	private Long recorderUU;
+
+	/**
+	 * 应收日期
+	 */
+	@Column(name = "pa_apdate")
+	private Date apDate;
+
+	/**
+	 * 对账状态
+	 */
+	@Column(name = "pa_checkstatus")
+	private String checkStatus;
+
+	/**
+	 * 备注
+	 */
+	@Column(name = "pa_remark")
+	private String remark;
+
+	/**
+	 * 提交日期
+	 */
+	@Column(name = "pa_commitdate")
+	private Date commitDate;
+
+	/**
+	 * 作废日期
+	 */
+	@Column(name = "pa_resdate")
+	private Date resDate;
+
+	/**
+	 * 作废人
+	 */
+	@Column(name = "pa_resman")
+	private String resMan;
+
+	/**
+	 * 上传状态
+	 */
+	@Column(name = "pa_status")
+	private Short status;
+
+	/**
+	 * 对账总额
+	 */
+	@Column(name = "pa_checkamount")
+	private Double checkAmount;
+
+	/**
+	 * 币别
+	 */
+	@Column(name = "pa_currency")
+	private String currency;
+
+	/**
+	 * 汇率
+	 */
+	@Column(name = "pa_taxrate")
+	private Double taxrate;
+
+	/**
+	 * 汇率
+	 */
+	@Column(name = "pa_rate")
+	private Double rate;
+
+	/**
+	 * 收款方式
+	 */
+	@Column(name = "pa_payments")
+	private String payments;
+
+	/**
+	 * 客户UU
+	 */
+	@Column(name = "pa_custuu")
+	private Long custUu;
+
+	/**
+	 * 客户名称
+	 */
+	@Column(name = "pa_custname")
+	private String custName;
+
+	/**
+	 * 供应商UU
+	 */
+	@Column(name = "pa_enuu")
+	private Long enUu;
+
+    /**
+     * 供应商名称
+     */
+	@Transient
+    private String vendorName;
+
+	/**
+	 * 单据编号
+	 */
+	@Column(name = "pa_code")
+	private String code;
+
+	/**
+	 * 客户回复原因
+	 */
+	@Column(name = "pa_custreply")
+	private String custreply;
+
+	/**
+	 * 打印次数
+	 */
+	@Column(name = "pa_print")
+	private Short print;
+
+	/**
+	 * 不同意原因
+	 */
+	@Column(name = "pa_reason")
+	private String reason;
+
+    public String getCustreply() {
+		return custreply;
+	}
+
+	public void setCustreply(String custreply) {
+		this.custreply = custreply;
+	}
+
+	public Long getId() {
+		return id;
+	}
+
+	public void setId(Long id) {
+		this.id = id;
+	}
+
+	public Date getBeginDate() {
+		return beginDate;
+	}
+
+	public void setBeginDate(Date beginDate) {
+		this.beginDate = beginDate;
+	}
+
+	public Date getEndDate() {
+		return endDate;
+	}
+
+	public void setEndDate(Date endDate) {
+		this.endDate = endDate;
+	}
+
+	public Date getRecordDate() {
+		return recordDate;
+	}
+
+	public void setRecordDate(Date recordDate) {
+		this.recordDate = recordDate;
+	}
+
+	public String getRecorder() {
+		return recorder;
+	}
+
+	public void setRecorder(String recorder) {
+		this.recorder = recorder;
+	}
+
+	public Date getApDate() {
+		return apDate;
+	}
+
+	public void setApDate(Date apDate) {
+		this.apDate = apDate;
+	}
+
+	public String getCheckStatus() {
+		return checkStatus;
+	}
+
+	public void setCheckStatus(String checkStatus) {
+		this.checkStatus = checkStatus;
+	}
+
+	public String getRemark() {
+		return remark;
+	}
+
+	public void setRemark(String remark) {
+		this.remark = remark;
+	}
+
+	public Date getCommitDate() {
+		return commitDate;
+	}
+
+	public void setCommitDate(Date commitDate) {
+		this.commitDate = commitDate;
+	}
+
+	public Date getResDate() {
+		return resDate;
+	}
+
+	public void setResDate(Date resDate) {
+		this.resDate = resDate;
+	}
+
+	public String getResMan() {
+		return resMan;
+	}
+
+	public void setResMan(String resMan) {
+		this.resMan = resMan;
+	}
+
+	public Short getStatus() {
+		return status;
+	}
+
+	public void setStatus(Short status) {
+		this.status = status;
+	}
+
+	public Double getCheckAmount() {
+		return checkAmount;
+	}
+
+	public void setCheckAmount(Double checkAmount) {
+		this.checkAmount = checkAmount;
+	}
+
+	public String getCurrency() {
+		return currency;
+	}
+
+	public void setCurrency(String currency) {
+		this.currency = currency;
+	}
+
+	public Double getTaxrate() {
+		return taxrate;
+	}
+
+	public void setTaxrate(Double taxrate) {
+		this.taxrate = taxrate;
+	}
+
+	public String getPayments() {
+		return payments;
+	}
+
+	public void setPayments(String payments) {
+		this.payments = payments;
+	}
+
+	public Long getCustUu() {
+		return custUu;
+	}
+
+	public void setCustUu(Long custUu) {
+		this.custUu = custUu;
+	}
+
+	public String getCustName() {
+		return custName;
+	}
+
+	public void setCustName(String custName) {
+		this.custName = custName;
+	}
+
+	public Long getEnUu() {
+		return enUu;
+	}
+
+	public void setEnUu(Long enUu) {
+		this.enUu = enUu;
+	}
+
+    public String getVendorName() {
+        return vendorName;
+    }
+
+    public void setVendorName(String vendorName) {
+        this.vendorName = vendorName;
+    }
+
+    public String getCode() {
+		return code;
+	}
+
+	public void setCode(String code) {
+		this.code = code;
+	}
+
+	public Double getRate() {
+		return rate;
+	}
+
+	public void setRate(Double rate) {
+		this.rate = rate;
+	}
+
+	public Short getPrint() {
+		return print;
+	}
+
+	public void setPrint(Short print) {
+		this.print = print;
+	}
+
+	public Long getRecorderUU() {
+		return recorderUU;
+	}
+
+	public void setRecorderUU(Long recorderUU) {
+		this.recorderUU = recorderUU;
+	}
+
+	public String getReason() {
+		return reason;
+	}
+
+	public void setReason(String reason) {
+		this.reason = reason;
+	}
+}

+ 2 - 1
src/main/java/com/uas/platform/b2b/model/PurchaseApCheck.java

@@ -14,6 +14,7 @@ import javax.persistence.Table;
 import javax.persistence.Transient;
 import java.io.*;
 import java.util.Date;
+import java.util.List;
 import java.util.Set;
 
 /**
@@ -198,7 +199,7 @@ public class PurchaseApCheck implements Serializable {
 	@OrderBy("number")
 	private Set<PurchaseApCheckItem> items;
 
-	public String getCustreply() {
+    public String getCustreply() {
 		return custreply;
 	}
 

+ 135 - 1
src/main/java/com/uas/platform/b2b/model/PurchaseApCheckItem.java

@@ -55,7 +55,6 @@ public class PurchaseApCheckItem implements Serializable {
     @Column(name = "pai_custuseruu")
     private Long custUserUU;
 
-
     /**
 	 * 客户物料ID
 	 */
@@ -473,4 +472,139 @@ public class PurchaseApCheckItem implements Serializable {
 		return purchaseApChecks;
 	}
 
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        PurchaseApCheckItem checkItem = (PurchaseApCheckItem) o;
+
+        if (id != null ? !id.equals(checkItem.id) : checkItem.id != null) {
+            return false;
+        }
+        if (number != null ? !number.equals(checkItem.number) : checkItem.number != null) {
+            return false;
+        }
+        if (custUserUU != null ? !custUserUU.equals(checkItem.custUserUU) : checkItem.custUserUU != null) {
+            return false;
+        }
+        if (prid != null ? !prid.equals(checkItem.prid) : checkItem.prid != null) {
+            return false;
+        }
+        if (orderCode != null ? !orderCode.equals(checkItem.orderCode) : checkItem.orderCode != null) {
+            return false;
+        }
+        if (orderClass != null ? !orderClass.equals(checkItem.orderClass) : checkItem.orderClass != null) {
+            return false;
+        }
+        if (orderDetno != null ? !orderDetno.equals(checkItem.orderDetno) : checkItem.orderDetno != null) {
+            return false;
+        }
+        if (inoutno != null ? !inoutno.equals(checkItem.inoutno) : checkItem.inoutno != null) {
+            return false;
+        }
+        if (inoutnodetno != null ? !inoutnodetno.equals(checkItem.inoutnodetno) : checkItem.inoutnodetno != null) {
+            return false;
+        }
+        if (prodCode != null ? !prodCode.equals(checkItem.prodCode) : checkItem.prodCode != null) {
+            return false;
+        }
+        if (prodTitle != null ? !prodTitle.equals(checkItem.prodTitle) : checkItem.prodTitle != null) {
+            return false;
+        }
+        if (prodSpec != null ? !prodSpec.equals(checkItem.prodSpec) : checkItem.prodSpec != null) {
+            return false;
+        }
+        if (prodUnit != null ? !prodUnit.equals(checkItem.prodUnit) : checkItem.prodUnit != null) {
+            return false;
+        }
+        if (price != null ? !price.equals(checkItem.price) : checkItem.price != null) {
+            return false;
+        }
+        if (taxrate != null ? !taxrate.equals(checkItem.taxrate) : checkItem.taxrate != null) {
+            return false;
+        }
+        if (checkQty != null ? !checkQty.equals(checkItem.checkQty) : checkItem.checkQty != null) {
+            return false;
+        }
+        if (amount != null ? !amount.equals(checkItem.amount) : checkItem.amount != null) {
+            return false;
+        }
+        if (custCheckQty != null ? !custCheckQty.equals(checkItem.custCheckQty) : checkItem.custCheckQty != null) {
+            return false;
+        }
+        if (remark != null ? !remark.equals(checkItem.remark) : checkItem.remark != null) {
+            return false;
+        }
+        if (status != null ? !status.equals(checkItem.status) : checkItem.status != null) {
+            return false;
+        }
+        if (sourceTable != null ? !sourceTable.equals(checkItem.sourceTable) : checkItem.sourceTable != null) {
+            return false;
+        }
+        if (sourceId != null ? !sourceId.equals(checkItem.sourceId) : checkItem.sourceId != null) {
+            return false;
+        }
+        if (sourceDate != null ? !sourceDate.equals(checkItem.sourceDate) : checkItem.sourceDate != null) {
+            return false;
+        }
+        if (oldYCheckQty != null ? !oldYCheckQty.equals(checkItem.oldYCheckQty) : checkItem.oldYCheckQty != null) {
+            return false;
+        }
+        if (receiveCode != null ? !receiveCode.equals(checkItem.receiveCode) : checkItem.receiveCode != null) {
+            return false;
+        }
+        if (receiveName != null ? !receiveName.equals(checkItem.receiveName) : checkItem.receiveName != null) {
+            return false;
+        }
+        if (sendcode != null ? !sendcode.equals(checkItem.sendcode) : checkItem.sendcode != null) {
+            return false;
+        }
+        if (whname != null ? !whname.equals(checkItem.whname) : checkItem.whname != null) {
+            return false;
+        }
+        if (billed != null ? !billed.equals(checkItem.billed) : checkItem.billed != null) {
+            return false;
+        }
+        return apCheck != null ? apCheck.equals(checkItem.apCheck) : checkItem.apCheck == null;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = id != null ? id.hashCode() : 0;
+        result = 31 * result + (number != null ? number.hashCode() : 0);
+        result = 31 * result + (custUserUU != null ? custUserUU.hashCode() : 0);
+        result = 31 * result + (prid != null ? prid.hashCode() : 0);
+        result = 31 * result + (orderCode != null ? orderCode.hashCode() : 0);
+        result = 31 * result + (orderClass != null ? orderClass.hashCode() : 0);
+        result = 31 * result + (orderDetno != null ? orderDetno.hashCode() : 0);
+        result = 31 * result + (inoutno != null ? inoutno.hashCode() : 0);
+        result = 31 * result + (inoutnodetno != null ? inoutnodetno.hashCode() : 0);
+        result = 31 * result + (prodCode != null ? prodCode.hashCode() : 0);
+        result = 31 * result + (prodTitle != null ? prodTitle.hashCode() : 0);
+        result = 31 * result + (prodSpec != null ? prodSpec.hashCode() : 0);
+        result = 31 * result + (prodUnit != null ? prodUnit.hashCode() : 0);
+        result = 31 * result + (price != null ? price.hashCode() : 0);
+        result = 31 * result + (taxrate != null ? taxrate.hashCode() : 0);
+        result = 31 * result + (checkQty != null ? checkQty.hashCode() : 0);
+        result = 31 * result + (amount != null ? amount.hashCode() : 0);
+        result = 31 * result + (custCheckQty != null ? custCheckQty.hashCode() : 0);
+        result = 31 * result + (remark != null ? remark.hashCode() : 0);
+        result = 31 * result + (status != null ? status.hashCode() : 0);
+        result = 31 * result + (sourceTable != null ? sourceTable.hashCode() : 0);
+        result = 31 * result + (sourceId != null ? sourceId.hashCode() : 0);
+        result = 31 * result + (sourceDate != null ? sourceDate.hashCode() : 0);
+        result = 31 * result + (oldYCheckQty != null ? oldYCheckQty.hashCode() : 0);
+        result = 31 * result + (receiveCode != null ? receiveCode.hashCode() : 0);
+        result = 31 * result + (receiveName != null ? receiveName.hashCode() : 0);
+        result = 31 * result + (sendcode != null ? sendcode.hashCode() : 0);
+        result = 31 * result + (whname != null ? whname.hashCode() : 0);
+        result = 31 * result + (billed != null ? billed.hashCode() : 0);
+        result = 31 * result + (apCheck != null ? apCheck.hashCode() : 0);
+        return result;
+    }
 }

+ 1 - 5
src/main/java/com/uas/platform/b2b/model/SourceForApcheck.java

@@ -16,11 +16,7 @@ public class SourceForApcheck {
 		super();
 		this.sourceid = item.getSourceId();
 		this.sourcetable = item.getSourceTable();
-		if (item.getOldYCheckQty() == null) {
-			this.newYCheckQty = item.getCheckQty();
-		} else {
-			this.newYCheckQty = item.getCheckQty() + item.getOldYCheckQty();
-		}
+		this.newYCheckQty = item.getOldYCheckQty() == null ? item.getCheckQty() : item.getCheckQty() + item.getOldYCheckQty();
 
 	}
 

+ 9 - 9
src/main/java/com/uas/platform/b2b/model/User.java

@@ -1,6 +1,7 @@
 package com.uas.platform.b2b.model;
 
 import com.alibaba.fastjson.annotation.JSONField;
+import com.uas.platform.b2b.support.CollectionUtil;
 import com.uas.platform.b2b.support.SystemSession;
 import com.uas.platform.core.model.Constant;
 import com.uas.sso.entity.UserView;
@@ -9,6 +10,7 @@ import org.hibernate.annotations.Cache;
 import org.hibernate.annotations.CacheConcurrencyStrategy;
 import org.hibernate.annotations.NotFound;
 import org.hibernate.annotations.NotFoundAction;
+import org.springframework.security.access.AccessDeniedException;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.StringUtils;
 
@@ -27,7 +29,9 @@ import javax.persistence.Transient;
 import java.io.*;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * B2B用户信息
@@ -282,21 +286,17 @@ public class User implements Serializable {
 
 	public void setCurrentEnterprise(long enUU) {
 		if (this.enterprises != null && this.enterprises.size() > 0) {
-            for (Enterprise enterprise : enterprises) {
-                if (enterprise.getUu() == enUU) {
-                    this.enterprise = enterprise;
-                    break;
-                }
+            List<Enterprise> correctEnterprises = enterprises.stream().filter(enter -> enter.getUu().equals(enUU)).collect(Collectors.toList());
+            if (CollectionUtil.isEmpty(correctEnterprises)) {
+                throw new AccessDeniedException(String.format("未找到关于%d的企业信息,请更换企业或账号", enUU));
             }
-        }
-		if (this.enterprise == null) {
-            setCurrentEnterprise();
+            this.enterprise = correctEnterprises.get(0);
         }
 	}
 
 	public void setCurrentEnterprise(Enterprise enterprise) {
 		if (!CollectionUtils.isEmpty(SystemSession.getUser().getEnterprises())) {
-			Set<Enterprise> enterprises = new HashSet<Enterprise>();
+			Set<Enterprise> enterprises = new HashSet<>();
 			for (Enterprise en : SystemSession.getUser().getEnterprises()) {
 				if (en.equals(enterprise)) {
 					enterprises.add(enterprise);

+ 19 - 0
src/main/java/com/uas/platform/b2b/service/PurchaseApCheckService.java

@@ -12,7 +12,9 @@ import com.uas.platform.core.model.PageInfo;
 import com.uas.platform.core.model.PageParams;
 import com.uas.search.b2b.model.SPage;
 import org.springframework.data.domain.Page;
+import org.springframework.ui.ModelMap;
 
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
@@ -132,6 +134,15 @@ public interface PurchaseApCheckService {
 	 */
     List<PurchaseApCheckItem> findBySourceTableAndSourceId(String sourceTable, Long sourceId);
 
+    /**
+     * 通过sourceTable、sourceId判断是否已提交未对账
+     *
+     * @param sourceTable 来源表
+     * @param ids id集合
+     * @return 查询的数据
+     */
+    List<PurchaseApCheckItem> findBySourceTableAndSourceIdIn(String sourceTable, Collection<Long> ids);
+
 	/**
 	 * 获取明细表中已开票数
 	 * @param id 发票id
@@ -254,4 +265,12 @@ public interface PurchaseApCheckService {
      * @return sql
      */
     String updateApCheckCountSql(Long vendorUU, Long customerUU, Long vendorId);
+
+    /**
+     * 进行对账单对账操作
+     *
+     * @param apCheck 对账单数据
+     * @return 对账结果
+     */
+    ModelMap checkCount(PurchaseApCheck apCheck);
 }

+ 206 - 58
src/main/java/com/uas/platform/b2b/service/impl/PurchaseApCheckServiceImpl.java

@@ -7,17 +7,20 @@ import com.uas.platform.b2b.core.util.ContextUtils;
 import com.uas.platform.b2b.dao.CommonDao;
 import com.uas.platform.b2b.dao.CommunalLogDao;
 import com.uas.platform.b2b.dao.EnterpriseDao;
+import com.uas.platform.b2b.dao.PurcApCheckDao;
 import com.uas.platform.b2b.dao.PurchaseApCheckDao;
 import com.uas.platform.b2b.dao.PurchaseApCheckDoneDao;
 import com.uas.platform.b2b.dao.PurchaseApCheckItemDao;
 import com.uas.platform.b2b.dao.PurchaseApCheckTodoDao;
 import com.uas.platform.b2b.dao.VendorDao;
 import com.uas.platform.b2b.event.PurchaseApCheckReplyReleaseEvent;
+import com.uas.platform.b2b.model.ApCheckTable;
 import com.uas.platform.b2b.model.CommunalLog;
 import com.uas.platform.b2b.model.DateFilter;
 import com.uas.platform.b2b.model.Enterprise;
 import com.uas.platform.b2b.model.OrderRedDotAll;
 import com.uas.platform.b2b.model.OrderType;
+import com.uas.platform.b2b.model.PurcApCheck;
 import com.uas.platform.b2b.model.PurchaseApCheck;
 import com.uas.platform.b2b.model.PurchaseApCheckDone;
 import com.uas.platform.b2b.model.PurchaseApCheckItem;
@@ -36,8 +39,10 @@ import com.uas.platform.b2b.service.UserService;
 import com.uas.platform.b2b.support.CollectionUtil;
 import com.uas.platform.b2b.support.DecimalUtils;
 import com.uas.platform.b2b.support.SystemSession;
+import com.uas.platform.b2b.support.UsageBufferedLogger;
 import com.uas.platform.b2b.task.ApCheckTask;
 import com.uas.platform.core.exception.IllegalOperatorException;
+import com.uas.platform.core.logging.BufferedLoggerManager;
 import com.uas.platform.core.model.Constant;
 import com.uas.platform.core.model.PageInfo;
 import com.uas.platform.core.model.PageParams;
@@ -45,11 +50,13 @@ import com.uas.platform.core.model.Status;
 import com.uas.platform.core.persistence.criteria.PredicateUtils;
 import com.uas.ps.core.util.StringUtils;
 import com.uas.search.b2b.model.SPage;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Page;
 import org.springframework.data.jpa.domain.Specification;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.ui.ModelMap;
 import org.springframework.util.CollectionUtils;
 
 import javax.persistence.criteria.CriteriaBuilder;
@@ -59,6 +66,7 @@ import javax.persistence.criteria.Root;
 import java.sql.SQLException;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -68,6 +76,7 @@ import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * 对账单
@@ -86,9 +95,12 @@ public class PurchaseApCheckServiceImpl implements PurchaseApCheckService {
     private final UserService userService;
     private final VendorDao vendorDao;
     private final CommunalLogDao communalLogDao;
+    private final PurcApCheckDao apCheckDao;
     @Autowired
     private ErpProdIODetailService erpProdIODetailService;
 
+    private final static UsageBufferedLogger LOGGER = BufferedLoggerManager.getLogger(UsageBufferedLogger.class);
+
     /**
      * RMB
      */
@@ -110,7 +122,8 @@ public class PurchaseApCheckServiceImpl implements PurchaseApCheckService {
     public PurchaseApCheckServiceImpl(PurchaseApCheckDao purchaseApCheckDao, PurchaseApCheckTodoDao purchaseApCheckTodoDao,
                                       PurchaseApCheckDoneDao purchaseApCheckDoneDao, PurchaseApCheckItemDao purchaseApCheckItemDao,
                                       CommonDao commonDao, OrderRedDotService redDotService, EnterpriseDao enterpriseDao,
-                                      UserService userService, VendorDao vendorDao, CommunalLogDao communalLogDao) {
+                                      UserService userService, VendorDao vendorDao, CommunalLogDao communalLogDao,
+                                      PurcApCheckDao apCheckDao) {
         this.purchaseApCheckDao = purchaseApCheckDao;
         this.redDotService = redDotService;
         this.purchaseApCheckTodoDao = purchaseApCheckTodoDao;
@@ -121,6 +134,7 @@ public class PurchaseApCheckServiceImpl implements PurchaseApCheckService {
         this.userService = userService;
         this.vendorDao = vendorDao;
         this.communalLogDao = communalLogDao;
+        this.apCheckDao = apCheckDao;
         ExecutorService executorService = Executors.newCachedThreadPool();
         executor = new BoundedExecutor(executorService, 1600);
     }
@@ -328,9 +342,9 @@ public class PurchaseApCheckServiceImpl implements PurchaseApCheckService {
 	}
 
 	@Override
-	@Transactional(rollbackFor = SQLException.class)
+	@Transactional(rollbackFor = Exception.class)
 	public PurchaseApCheck save(PurchaseApCheck purchaseApCheck) {
-		Date date = new Date();
+		Date date = new Date(System.currentTimeMillis());
         purchaseApCheck.setRecordDate(date);
         purchaseApCheck.setCommitDate(date);
         SimpleDateFormat sdf = new SimpleDateFormat("yyMMddhhmmss_sss");
@@ -339,79 +353,138 @@ public class PurchaseApCheckServiceImpl implements PurchaseApCheckService {
 		purchaseApCheck.setRecorder(SystemSession.getUser().getUserName());
 		purchaseApCheck.setRecorderUU(SystemSession.getUser().getUserUU());
         purchaseApCheck.setStatus((short) Status.NOT_UPLOAD.value());
-		Short number = 0;
-		List<PurchaseApCheckItem> items = new ArrayList<PurchaseApCheckItem>();
 		// 保存成功的同时来源单据更新一下
 		List<SourceForApcheck> sources = new ArrayList<>();
+        PurcApCheck apCheck = new PurcApCheck();
+        BeanUtils.copyProperties(purchaseApCheck, apCheck, PurcApCheck.class);
+        apCheck = apCheckDao.save(apCheck);
 		for (PurchaseApCheckItem item : purchaseApCheck.getItems()) {
 			SourceForApcheck source = new SourceForApcheck(item);
 			sources.add(source);
-			item.setNumber(++number);
-			item.setApCheck(purchaseApCheck);
-			items.add(item);
 		}
-		updateSourceInfo(sources);
-        items = purchaseApCheckItemDao.save(items);
+        updateSourceInfo(sources);
+        saveCheckItemsByJdbcTemplate(purchaseApCheck.getItems(), apCheck.getId());
         List<PurchaseApCheck> apChecks = new ArrayList<>();
-        apChecks.add(items.get(0).getApCheck());
+        purchaseApCheck.setId(apCheck.getId());
+        apChecks.add(purchaseApCheck);
         saveUserOrders(apChecks);
-		return purchaseApCheck;
+        return purchaseApCheck;
 	}
 
+    /**
+     * 采用jdbcTemplate批量存储名
+     * @param items 对账明细
+     * @param apCheckId 主表id
+     */
+    private void saveCheckItemsByJdbcTemplate(Set<PurchaseApCheckItem> items, final Long apCheckId) {
+	    if (!CollectionUtils.isEmpty(items)) {
+            final Short[] num = {1};
+	        commonDao.getJdbcTemplate().batchUpdate("insert into purc$apcheckitem(pai_number, pai_custuseruu, pai_prid, pai_ordercode,pai_orderclass, " +
+                "pai_orderdetno, pai_inoutno, pai_inoutnodetno, pai_prodcode, pai_prodtitle, pai_prodspec, pai_produnit, pai_price,pai_taxrate, pai_checkqty, " +
+                "pai_amount, pai_custcheckqty, pai_remark, pai_status, pai_sourcetable, pai_sourceid, pai_source_date, pai_oldycheckqty, pai_receivecode, pai_receivename, " +
+                "pai_sendcode, pai_whname, pai_billed, pai_paid) " +
+                "values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
+                items, items.size(), (pa, i) -> {
+	                pa.setObject(1, num[0]++);
+                    pa.setObject(2, i.getCustUserUU());
+                    pa.setObject(3, i.getPrid());
+                    pa.setObject(4, i.getOrderCode());
+                    pa.setObject(5, i.getOrderClass());
+                    pa.setObject(6, i.getOrderDetno());
+                    pa.setObject(7, i.getInoutno());
+                    pa.setObject(8, i.getInoutnodetno());
+                    pa.setObject(9, i.getProdCode());
+                    pa.setObject(10, i.getProdTitle());
+
+                    pa.setObject(11, i.getProdSpec());
+                    pa.setObject(12, i.getProdUnit());
+                    pa.setObject(13, i.getPrice());
+                    pa.setObject(14, i.getTaxrate());
+                    pa.setObject(15, i.getCheckQty());
+                    pa.setObject(16, i.getAmount());
+                    pa.setObject(17, i.getCustCheckQty());
+                    pa.setObject(18, i.getRemark());
+                    pa.setObject(19, i.getStatus());
+                    pa.setObject(20, i.getSourceTable());
+
+                    pa.setObject(21, i.getSourceId());
+                    pa.setObject(22, i.getSourceDate());
+                    pa.setObject(23, i.getOldYCheckQty());
+                    pa.setObject(24, i.getReceiveCode());
+                    pa.setObject(25, i.getReceiveName());
+                    pa.setObject(26, i.getSendcode());
+                    pa.setObject(27, i.getWhname());
+                    pa.setObject(28, i.getBilled());
+                    pa.setObject(29, apCheckId);
+                });
+        }
+    }
+
     /**
      * 更新来源表数据
      *
-     * @param list 来源库信息
+     * @param sourceApCheckList 来源库信息
      * @return 保存结果
      */
-	public boolean updateSourceInfo(List<SourceForApcheck> list) {
-		if (!CollectionUtils.isEmpty(list)) {
-		    List<String> sqls = new ArrayList<>();
-			for (SourceForApcheck source : list) {
-				if (source.hasInfo()) {
-					String idName = null;
-					String yCheckQtyName = null;
-					if (source.getSourcetable().equals("purc$returnitem")) {
-						idName = "pri_id";
-						yCheckQtyName = "pri_ycheckqty";
-					} else if (source.getSourcetable().equals("purc$acceptitem")) {
-						idName = "pai_id";
-						yCheckQtyName = "pai_ycheckqty";
-					} else if (source.getSourcetable().equals("purc$badinitem")) {
-						idName = "pbi_id";
-						yCheckQtyName = "pbi_ycheckqty";
-					} else if (source.getSourcetable().equals("purc$badoutitem")) {
-						idName = "poi_id";
-						yCheckQtyName = "poi_ycheckqty";
-					} else if (source.getSourcetable().equals("make$acceptitem")) {
-						idName = "mai_id";
-						yCheckQtyName = "mai_ycheckqty";
-					} else if (source.getSourcetable().equals("make$returnitem")) {
-						idName = "mri_id";
-						yCheckQtyName = "mri_ycheckqty";
-					} else if (source.getSourcetable().equals("purc$apbilladjustment")) {
-						idName = "aa_id";
-						yCheckQtyName = "aa_ycheckqty";
-					}
-					String sql = "update " + source.getSourcetable() + " set " + yCheckQtyName + " = "
-							+ source.getNewYCheckQty() + " where " + idName + " = " + source.getSourceid();
-                    sqls.add(sql);
-				}
-			}
-			if (!CollectionUtils.isEmpty(sqls)) {
-			    try {
-			        commonDao.getJdbcTemplate().batchUpdate(sqls.toArray(new String[sqls.size()]));
-                } catch (RuntimeException e) {
-                    System.out.println("生成对账单批量更新来源数据失败: " + e.getMessage());
-                    throw new IllegalOperatorException("保存失败!");
-                }
-                return true;
+	public void updateSourceInfo(List<SourceForApcheck> sourceApCheckList) {
+		if (CollectionUtils.isEmpty(sourceApCheckList)) {
+            throw new IllegalOperatorException("保存失败!");
+        }
+        String saleAcceptSql = setSql(sourceApCheckList, ApCheckTable.SALE_ACCEPT, ApCheckTable.SALE_ACCEPT_QTY, ApCheckTable.SALE_ACCEPT_ID);
+        String saleReturnSql = setSql(sourceApCheckList, ApCheckTable.SALE_RETURN, ApCheckTable.SALE_RETURN_QTY, ApCheckTable.SALE_RETURN_ID);
+        String saleBadInSql = setSql(sourceApCheckList, ApCheckTable.SALE_BADIN, ApCheckTable.SALE_BADIN_QTY, ApCheckTable.SALE_BADIN_ID);
+        String saleBadOutSql = setSql(sourceApCheckList, ApCheckTable.SALE_BADOUT, ApCheckTable.SALE_BADOUT_QTY, ApCheckTable.SALE_BADOUT_ID);
+        String makeAcceptSql = setSql(sourceApCheckList, ApCheckTable.MAKE_ACCEPT, ApCheckTable.MAKE_ACCEPT_QTY, ApCheckTable.MAKE_ACCEPT_ID);
+        String makeReturnSql = setSql(sourceApCheckList, ApCheckTable.MAKE_RETURN, ApCheckTable.MAKE_RETURN_QTY, ApCheckTable.MAKE_RETURN_ID);
+        String adjustmentSql = setSql(sourceApCheckList, ApCheckTable.ADJUSTMENT, ApCheckTable.ADJUSTMENT_QTY, ApCheckTable.ADJUSTMENT_ID);
+        List<String> sqlList = Stream.of(saleAcceptSql, saleReturnSql, saleBadInSql, saleBadOutSql, makeAcceptSql, makeReturnSql, adjustmentSql)
+            .filter(str -> !StringUtils.isEmpty(str)).collect(Collectors.toList());
+        if (!CollectionUtils.isEmpty(sqlList)) {
+            try {
+                commonDao.getJdbcTemplate().batchUpdate(sqlList.toArray(new String[sqlList.size()]));
+            } catch (RuntimeException e) {
+                System.out.println("生成对账单批量更新来源数据失败: " + e.getMessage());
+                throw new IllegalOperatorException("保存失败!");
             }
-		}
-		throw new IllegalOperatorException("保存失败!");
+        }
 	}
 
-	@Override
+    /**
+     * 根据传入的来源表, 数据统计,id字段已经对账数量字段生成更新的sql语句
+     *
+     * @param sourceApCheckList 数据统计
+     * @param tableName 来源表名称
+     * @param qtyColumn 对账数量走的
+     * @param idColumn id字段
+     * @return 更新语句
+     */
+    private String setSql(List<SourceForApcheck> sourceApCheckList, String tableName, String qtyColumn, String idColumn) {
+        List<SourceForApcheck> filterList = sourceApCheckList.stream()
+            .filter(source -> source.hasInfo() && tableName.equals(source.getSourcetable()))
+            .collect(Collectors.toList());
+	    if (CollectionUtils.isEmpty(filterList)) {
+	        return null;
+        }
+	    StringBuffer sql = new StringBuffer("update ").append(tableName)
+            .append(" set ").append(qtyColumn).append(" = case ")
+            .append(idColumn).append(" ");
+        StringBuffer idString = new StringBuffer();
+        filterList.forEach(apCheck -> {
+            sql.append(" when ").append(apCheck.getSourceid()).append(" then ").append(apCheck.getNewYCheckQty());
+            if (idString.length() > 0) {
+                idString.append(",");
+            }
+            idString.append(apCheck.getSourceid());
+        });
+        // 如果id为空,前面又筛选出数据,说明数据源存在问题,不能保存对账,抛出异常提示
+        if (idString.length() == 0) {
+            throw new IllegalOperatorException("更新失败");
+        }
+        sql.append(" end where ").append(idColumn).append(" in (").append(idString).append(")");
+        return sql.toString();
+    }
+
+    @Override
 	public Page<PurchaseApCheck> findAllByPageInfo(final PageInfo pageInfo, final String keyword,
 			SearchFilter searchFilter) {
 		if (searchFilter != null) {
@@ -540,6 +613,18 @@ public class PurchaseApCheckServiceImpl implements PurchaseApCheckService {
 		return purchaseApCheckItemDao.findBySourceTableAndSourceId(sourceTable, sourceId);
 	}
 
+    /**
+     * 通过sourceTable、sourceId判断是否已提交未对账
+     *
+     * @param sourceTable 来源表
+     * @param ids         id集合
+     * @return 查询的数据
+     */
+    @Override
+    public List<PurchaseApCheckItem> findBySourceTableAndSourceIdIn(String sourceTable, Collection<Long> ids) {
+        return purchaseApCheckItemDao.findBySourceTableAndSourceIdIn(sourceTable, ids);
+    }
+
     @Override
     public Double getBilledByItemId(Long id) {
         return purchaseApCheckItemDao.getBilledById(id);
@@ -953,4 +1038,67 @@ public class PurchaseApCheckServiceImpl implements PurchaseApCheckService {
         threadsSignal.await();
         return groupCountByCurrency(totalTrades);
     }
+
+    /**
+     * 进行对账单对账操作
+     *
+     * @param apCheck 对账单数据
+     * @return 对账结果
+     */
+    @Override
+    public ModelMap checkCount(PurchaseApCheck apCheck) {
+        if (apCheck != null) {
+            // 针对当前对账数据进行校验操作
+            enableCheck(apCheck.getItems());
+            apCheck = this.save(apCheck);
+            LOGGER.log("应收对账单", "多个单据生成同一张应收对账单", apCheck.getRemark(), null, apCheck.getId());
+            return new ModelMap("id", apCheck.getId());
+        }
+        LOGGER.log("应收对账单", "生成对账单失败,未选择对账数据");
+        throw new IllegalOperatorException("保存失败!");
+    }
+
+    /**
+     * 按表类型分别统计各个出入库单据的对账情况
+     *
+     * @param checkItemList 对账明细
+     */
+    private void enableCheck(Set<PurchaseApCheckItem> checkItemList) {
+        // 先取出表名
+        Set<String> tableNameSet = checkItemList.stream()
+            .filter(item -> !StringUtils.isEmpty(item.getSourceTable()))
+            .map(PurchaseApCheckItem::getSourceTable)
+            .collect(Collectors.toSet());
+        // 根据去重的表名分类统计各个来源id
+        if (!CollectionUtil.isEmpty(tableNameSet)) {
+            // 禁止提交生成对账单状态
+            String disableStatus = "未对账";
+            Set<String> alters = new HashSet<>();
+            // 分别统计各个单据是否存在未对账单据
+            tableNameSet.forEach(tableName -> {
+                Set<Long> sourceIdSet = getSourceIdSet(checkItemList, tableName);
+                List<PurchaseApCheckItem> itemList = this.findBySourceTableAndSourceIdIn(tableName, sourceIdSet);
+                alters.addAll(itemList.stream().filter(item -> disableStatus.equals(item.getApCheck().getCheckStatus()))
+                    .map(PurchaseApCheckItem::getInoutno)
+                    .collect(Collectors.toSet()));
+            });
+            if (!CollectionUtil.isEmpty(alters)) {
+                throw new IllegalOperatorException("订单" + new ModelMap("alters", alters) + "存在未对账的单据,请先进行对账!");
+            }
+        }
+    }
+
+    /**
+     * 按表名统计来源id
+     *
+     * @param checkItemList 对账明细集合
+     * @param tableName 表名
+     * @return id集合
+     */
+    private Set<Long> getSourceIdSet(Set<PurchaseApCheckItem> checkItemList, String tableName) {
+        return checkItemList.stream()
+            .filter(checkItem -> tableName.equals(checkItem.getSourceTable()))
+            .map(PurchaseApCheckItem::getSourceId)
+            .collect(Collectors.toSet());
+    }
 }

+ 2 - 6
src/main/java/com/uas/platform/b2b/service/impl/UserServiceImpl.java

@@ -791,18 +791,14 @@ public class UserServiceImpl implements UserService {
 		Set<Role> roles = SystemSession.getUser().getRoles();
 		boolean isSys = false;
 		for (Role role : roles) {
-			if (role.getIssys() == 1) {
-				isSys = true;
-				break;
-			}
-			if ("ROLE_SALEMANAGER".equals(role.getName())) {
+			if (role.getIssys() == 1 || "ROLE_SALEMANAGER".equals(role.getName())) {
 				isSys = true;
 				break;
 			}
 		}
 		if (!SystemSession.getUser().isSys() && !isSys) {
 			List<Vendor> vendors = findChooseVendor(SystemSession.getUser().getUserUU());
-			List<Long> distributes = new ArrayList<Long>();
+			List<Long> distributes = new ArrayList<>();
 			filter = new SearchFilter();
 			if (!CollectionUtils.isEmpty(vendors)) {
 				for (Vendor v : vendors) {

+ 1 - 1
src/main/java/com/uas/platform/b2b/support/UserCreater.java

@@ -32,7 +32,7 @@ public class UserCreater {
 		user.setEnterprises(enterprises);
 		user.setCurrentEnterprise();
 
-		user.setRoles(new HashSet<Role>(roles));
+		user.setRoles(new HashSet<>(roles));
 
 		return user;
 	}

+ 18 - 22
src/main/java/com/uas/platform/b2b/v2/service/impl/EnterpriseServiceImpl.java

@@ -49,7 +49,7 @@ public class EnterpriseServiceImpl implements EnterpriseService {
 	@Autowired
     private InvitationRecordDao recordDao;
 
-	private final static CommBufferedLogger logger = BufferedLoggerManager.getLogger(CommBufferedLogger.class);
+	private final static CommBufferedLogger LOGGER = BufferedLoggerManager.getLogger(CommBufferedLogger.class);
 
 	private final static Logger INFO_LOG = Logger.getLogger(EnterpriseServiceImpl.class);
 
@@ -73,11 +73,7 @@ public class EnterpriseServiceImpl implements EnterpriseService {
 		enterprise.setEnArea(detail.getArea());
 		enterprise.setEnBussinessCode(detail.getBusinessCode());
 		enterprise.setEnCorporation(detail.getCorporation());
-		if(null != detail.getRegisterDate()) {
-			enterprise.setEnDate(new Date(detail.getRegisterDate()));
-		} else {
-			enterprise.setEnDate(new Date());
-		}
+        enterprise.setEnDate(null != detail.getRegisterDate() ? new Date(detail.getRegisterDate()) : new Date());
 		enterprise.setEnName(detail.getSpaceName());
 		enterprise.setLogUrl(detail.getLogoImage());
 		enterprise.setProfession(detail.getProfession());
@@ -94,26 +90,26 @@ public class EnterpriseServiceImpl implements EnterpriseService {
         User user = userDao.findOne(enterprise.getEnAdminuu());
         INFO_LOG.info("把管理员添加进企业: user-> " + JSONObject.toJSON(user));
         // 先进行管理员信息查找,如果不存在,等待用户信息先存储
-        synchronized (user) {
-            if (null == user) {
-                try {
-                    Thread.sleep(2000);
-                    user = userDao.findOne(enterprise.getEnAdminuu());
-                    if (null == user) {
-                        user = new User(detail.getAdmin());
-                    }
-                } catch (InterruptedException e) {
-                    e.printStackTrace();
+        if (null == user) {
+            try {
+                Thread.sleep(2000);
+                user = userDao.findOne(enterprise.getEnAdminuu());
+                if (null == user) {
+                    user = new User(detail.getAdmin());
                 }
+            } catch (InterruptedException e) {
+                e.printStackTrace();
             }
         }
-		user.addEnterprise(enterprise);
-		// 将用户设置为管理员,只对用户的当前企业的角色进行修改
+        if (user != null) {
+            user.addEnterprise(enterprise);
+        }
+        // 将用户设置为管理员,只对用户的当前企业的角色进行修改
         setUserRole(user, enterprise);
 		if (isNew) {
 			final Long enUU = enterprise.getUu();
             enterpriseDao.callInitProcedure(enUU);
-            logger.log("企业信息", "企业初始化", "新注册企业初始化资料", enUU);
+            LOGGER.log("企业信息", "企业初始化", "新注册企业初始化资料", enUU);
 		}
 		return enterprise;
 	}
@@ -137,7 +133,7 @@ public class EnterpriseServiceImpl implements EnterpriseService {
     @Override
     public User setUserRole(User user, Enterprise enterprise) {
         // 新用户注册企业时为空
-        Set<Role> existRoles = new HashSet<Role>();
+        Set<Role> existRoles = new HashSet<>();
         // 老用户注册新企业
         if (!CollectionUtils.isEmpty(user.getRoles())) {
             existRoles = user.getRoles();
@@ -209,7 +205,7 @@ public class EnterpriseServiceImpl implements EnterpriseService {
                 record.setVendusertel(enterpriseInfo.getEnTel());
                 record.setVendusername(enterpriseInfo.getContactMan());
                 User admin = userDao.findOne(enterpriseInfo.getEnAdminuu());
-                Date inviteDate = null != null ? new Date(enterpriseInfo.getInviteTime()) : new Date(System.currentTimeMillis());
+                Date inviteDate = new Date(System.currentTimeMillis());
                 record.setDate(inviteDate);
                 record.setVenduu(enterpriseInfo.getUu());
                 record.setSource(enterpriseInfo.getInviteSource() != null ? enterpriseInfo.getInviteSource() : "B2B");
@@ -223,7 +219,7 @@ public class EnterpriseServiceImpl implements EnterpriseService {
                 String inviteInfo = "企业名称: " + enterpriseInfo.getEnName() + ";"
                         + "邀请企业: " + inviteEnterprise.getEnName() + "(" + inviteEnterprise.getUu() + ");"
                         + "邀请人: " + inviteUser.getUserName() + "(" + inviteUser.getUserUU() + ")";
-                logger.log("添加合作伙伴", "企业注册添加合作伙伴", inviteInfo , enterpriseInfo.getUu());
+                LOGGER.log("添加合作伙伴", "企业注册添加合作伙伴", inviteInfo , enterpriseInfo.getUu());
             }
         }
     }

+ 3 - 3
src/main/java/com/uas/platform/b2b/v2/service/impl/UserServiceImpl.java

@@ -43,7 +43,7 @@ public class UserServiceImpl implements UserService {
 
 	private final static Logger LOGGER = Logger.getLogger(UserServiceImpl.class);
 	
-	static final String defaultPassword = "111111";
+	private static final String defaultPassword = "111111";
 
 	@Override
 	public User save(UserView user) {
@@ -116,9 +116,9 @@ public class UserServiceImpl implements UserService {
 		Enterprise enterprise = enterpriseDao.findOne(spaceUU);
 		if (user == null) {
 			user = new User(userView);
-			user.setEnterprises(new HashSet<Enterprise>());
+			user.setEnterprises(new HashSet<>());
 		}
-		if (user == null || enterprise == null) {
+		if (enterprise == null) {
 			return;
 		}
 		List<Role> roles = roleDao.findByEnUUAndDesc(enterprise.getUu(), "普通用户");

+ 104 - 51
src/main/webapp/resources/js/index/app.js

@@ -9612,23 +9612,25 @@ define(['toaster', 'charts', 'ngTable', 'common/services', 'common/directives',
         $scope.setActive = function (state) {
             if ($scope.active != state) {
                 $scope.active = state;
-                if ($scope.tableParams.page() == 1)
-                    $scope.tableParams.reload();
-                else
-                    $scope.tableParams.page(1);
+                // if ($scope.tableParams.page() == 1)
+                //     $scope.tableParams.reload();
+                // else
+                //     $scope.tableParams.page(1);
                 $scope.showNotCheck = false
             }
             $scope.condition.$open = false
             $scope.apCheckCondition.$open = false
-            if (state != 'active') {
-                $scope.changeDateZone(1)
-            }
+            // if (state != 'active') {
+            //     $scope.changeDateZone(1)
+            // }
         };
-        $scope.changeDateZone = function (zone) {
+        $scope.changeDateZone = function (zone, flg) {
+
             $scope.condition.dateZone = zone;
             $scope.dateZoneText = zone == 1 ? '最近一个月' : (zone == 3 ? '最近三个月' : (zone == 6 ? '最近六个月' : '自定义'));
             $scope.condition.$dateZoneOpen = false;
             getDateCondition(zone, $scope.condition);
+            if (flg) return
             $scope.tableParams.page(1);
             $scope.tableParams.reload();
         };
@@ -9654,19 +9656,24 @@ define(['toaster', 'charts', 'ngTable', 'common/services', 'common/directives',
                 pageParams.keyword = $scope.keyword;
                 if ($scope.active === 'all') {
                     pageParams.keyword = $scope.keyword
-                    var _fromDate = $scope.thisMouthOut + '-01 00:00:00'
-                    _fromDate = _fromDate.replace(/-/g,'/')
-                    var _d  = new Date(_fromDate)
-                    _d.setDate(1)
-                    _d.setMonth(_d.getMonth() + 1)
-                    _d.setDate(_d.getDate() - 1)
-                    var _endDate = _d.getFullYear() + '-' + (_d.getMonth() + 1) + '-' + _d.getDate() + ' 00:00:00'
-                    _endDate = _endDate.replace(/-/g, '/')
-                    _endDate = new Date(_endDate).getTime()
-                    // _fromDate = _fromDate.replace(/-/g, '/')
-                    _fromDate = new Date(_fromDate).getTime()
-                    pageParams.searchFilter.fromDate =  _fromDate
-                    pageParams.searchFilter.endDate = _endDate
+                    if (!$scope.condition.$open) {
+                        var _fromDate = $scope.thisMouthOut + '-01 00:00:00'
+                        _fromDate = _fromDate.replace(/-/g, '/')
+                        var _d = new Date(_fromDate)
+                        _d.setDate(1)
+                        _d.setMonth(_d.getMonth() + 1)
+                        _d.setDate(_d.getDate() - 1)
+                        var _endDate = _d.getFullYear() + '-' + (_d.getMonth() + 1) + '-' + _d.getDate() + ' 00:00:00'
+                        _endDate = _endDate.replace(/-/g, '/')
+                        _endDate = new Date(_endDate).getTime()
+                        // _fromDate = _fromDate.replace(/-/g, '/')
+                        _fromDate = new Date(_fromDate).getTime()
+                        pageParams.searchFilter.fromDate = _fromDate
+                        pageParams.searchFilter.endDate = _endDate
+                    } else {
+                        // pageParams.searchFilter.fromDate = _fromDate
+                        // pageParams.searchFilter.endDate = _endDate
+                    }
                     FaApCheck.vendor(BaseService.parseParams(pageParams), function (page) {
                         $scope.loading = false;
                         page.content && page.content.forEach(function(list) {
@@ -9879,6 +9886,7 @@ define(['toaster', 'charts', 'ngTable', 'common/services', 'common/directives',
             $scope.showNotCheck = true
             $scope.vendorUU = item.vendorEnterprise.uu
             $scope.thisMouth = $scope.thisMouthOut
+            $scope.condition.$open = false
             this.searchOrder()
         }
 
@@ -10370,9 +10378,11 @@ define(['toaster', 'charts', 'ngTable', 'common/services', 'common/directives',
 
         $scope.hideshowNotCheck = function() {
             $scope.showNotCheck = false
+            $scope.condition.$open2 = false
         }
 
         $scope.$watch('thisMouthOut', function(newVal, oldVal) {
+            $scope.condition.$open = false
             var _fromDate = new Date()
 
             var _d = new Date(_fromDate)
@@ -10387,6 +10397,14 @@ define(['toaster', 'charts', 'ngTable', 'common/services', 'common/directives',
                 $scope.thisMouthOut = oldVal
                 return
             }
+            if (newVal === null) {
+                newVal = oldVal
+                $scope.thisMouthOut = oldVal
+                return false
+            }
+            if (oldVal === null) {
+                return false
+            }
             if (newVal !== oldVal) {
                 var _newVal = newVal.replace(/-/g,'/')
                 var _d  = new Date(_newVal)
@@ -10417,6 +10435,14 @@ define(['toaster', 'charts', 'ngTable', 'common/services', 'common/directives',
                 $scope.thisMouth = oldVal
                 return
             }
+            if (newVal === null) {
+                newVal = oldVal
+                $scope.thisMouthOut = oldVal
+                return false
+            }
+            if (oldVal === null) {
+                return false
+            }
             if (newVal !== oldVal) {
                 var _newVal = newVal.replace(/-/g,'/')
                 var _d  = new Date(_newVal)
@@ -10518,23 +10544,24 @@ define(['toaster', 'charts', 'ngTable', 'common/services', 'common/directives',
         $scope.setActive = function (state) {
             if ($scope.active != state) {
                 $scope.active = state;
-                if ($scope.tableParams.page() == 1)
-                    $scope.tableParams.reload();
-                else
-                    $scope.tableParams.page(1);
-                $scope.showNotCheck = false
+                // if ($scope.tableParams.page() == 1)
+                //     $scope.tableParams.reload();
+                // else
+                //     $scope.tableParams.page(1);
+                // $scope.showNotCheck = false
             }
             $scope.condition.$open = false
             $scope.apCheckCondition.$open = false
-            if (state != 'active') {
-                $scope.changeDateZone(1)
-            }
+            // if (state != 'active') {
+            //     $scope.changeDateZone(1)
+            // }
         };
-        $scope.changeDateZone = function (zone) {
+        $scope.changeDateZone = function (zone, flg) {
             $scope.condition.dateZone = zone;
             $scope.dateZoneText = zone == 1 ? '最近一个月' : (zone == 3 ? '最近三个月' : (zone == 6 ? '最近六个月' : '自定义'));
             $scope.condition.$dateZoneOpen = false;
             getDateCondition(zone, $scope.condition);
+            if (flg) return
             $scope.tableParams.page(1);
             $scope.tableParams.reload();
         };
@@ -10560,20 +10587,22 @@ define(['toaster', 'charts', 'ngTable', 'common/services', 'common/directives',
                 pageParams.keyword = $scope.keyword;
                 if ($scope.active === 'all') {
                     pageParams.keyword = $scope.keyword
-                    var _fromDate =  $scope.thisMouthOut + '-01 00:00:00'
-                    // var _d = new Date(_fromDate)
-                    _fromDate = _fromDate.replace(/-/g,'/')
-                    var _d  = new Date(_fromDate)
-                    _d.setDate(1)
-                    _d.setMonth(_d.getMonth() + 1)
-                    _d.setDate(_d.getDate() - 1)
-                    var _endDate = _d.getFullYear() + '-' + (_d.getMonth() + 1) + '-' + _d.getDate() + ' 00:00:00'
-                    _endDate = _endDate.replace(/-/g,'/')
-                    _fromDate = _fromDate.replace(/-/g,'/')
-                    _endDate = new Date(_endDate).getTime()
-                    _fromDate = new Date(_fromDate).getTime()
-                    pageParams.searchFilter.fromDate =  _fromDate
-                    pageParams.searchFilter.endDate = _endDate
+                    if (!$scope.condition.$open) {
+                        var _fromDate = $scope.thisMouthOut + '-01 00:00:00'
+                        // var _d = new Date(_fromDate)
+                        _fromDate = _fromDate.replace(/-/g, '/')
+                        var _d = new Date(_fromDate)
+                        _d.setDate(1)
+                        _d.setMonth(_d.getMonth() + 1)
+                        _d.setDate(_d.getDate() - 1)
+                        var _endDate = _d.getFullYear() + '-' + (_d.getMonth() + 1) + '-' + _d.getDate() + ' 00:00:00'
+                        _endDate = _endDate.replace(/-/g, '/')
+                        _fromDate = _fromDate.replace(/-/g, '/')
+                        _endDate = new Date(_endDate).getTime()
+                        _fromDate = new Date(_fromDate).getTime()
+                        pageParams.searchFilter.fromDate = _fromDate
+                        pageParams.searchFilter.endDate = _endDate
+                    }
                     FaApCheck.customer(BaseService.parseParams(pageParams), function (page) {
                         $scope.loading = false;
                         page.content && page.content.forEach(function(list) {
@@ -10787,6 +10816,7 @@ define(['toaster', 'charts', 'ngTable', 'common/services', 'common/directives',
             $scope.suuorname = item.myEnterprise.enName
             $scope.customerUU = item.myEnterprise.uu
             $scope.thisMouth = $scope.thisMouthOut
+            $scope.condition.$open = false
             this.searchOrder()
         }
 
@@ -11207,11 +11237,11 @@ define(['toaster', 'charts', 'ngTable', 'common/services', 'common/directives',
                 $scope.apCheck.endDate = _d.getTime()
             }
 
-            //获取筛选时间的开始时间为对账的开始时间
-            $scope.apCheck.beginDate = $scope.fromDate;
-
-            //获取筛选的截止时间为对账的截止时间
-            $scope.apCheck.endDate = $scope.endDate;
+            // //获取筛选时间的开始时间为对账的开始时间
+            // $scope.apCheck.beginDate = $scope.fromDate;
+            //
+            // //获取筛选的截止时间为对账的截止时间
+            // $scope.apCheck.endDate = $scope.endDate;
 
 
             //保存生成的应收对账单
@@ -11292,9 +11322,11 @@ define(['toaster', 'charts', 'ngTable', 'common/services', 'common/directives',
 
         $scope.hideshowNotCheck = function() {
             $scope.showNotCheck = false
+            $scope.condition.$open2 = false
         }
 
         $scope.$watch('thisMouthOut', function(newVal, oldVal) {
+            $scope.condition.$open = false
             var _fromDate = new Date()
             var _d = new Date(_fromDate)
             // var _d  = new Date(_fromDate.replace(/-/g,'/'))
@@ -11308,6 +11340,14 @@ define(['toaster', 'charts', 'ngTable', 'common/services', 'common/directives',
                 $scope.thisMouthOut = oldVal
                 return
             }
+            if (newVal === null) {
+                newVal = oldVal
+                $scope.thisMouthOut = oldVal
+                return false
+            }
+            if (oldVal === null) {
+                return false
+            }
             if (newVal !== oldVal) {
                 // var _d = new Date(newVal)
                 var _d = newVal + '-01'
@@ -11341,6 +11381,14 @@ define(['toaster', 'charts', 'ngTable', 'common/services', 'common/directives',
                 $scope.thisMouth = oldVal
                 return
             }
+            if (newVal === null) {
+                newVal = oldVal
+                $scope.thisMouthOut = oldVal
+                return false
+            }
+            if (oldVal === null) {
+                return false
+            }
             if (newVal !== oldVal) {
                 var _d = newVal + '-01'
                 _d = _d.replace(/-/g,'/')
@@ -12387,6 +12435,13 @@ define(['toaster', 'charts', 'ngTable', 'common/services', 'common/directives',
 
         };
 
+        $scope.closeNewUser = function () {
+            $scope.newUser.userTel = '';
+            $scope.newUser.userEmail = '';
+            $scope.newUser.userName = '';
+            $scope.adding = true;
+        }
+
 
         /**
          * 添加未注册用户
@@ -12407,8 +12462,6 @@ define(['toaster', 'charts', 'ngTable', 'common/services', 'common/directives',
                 $scope.newUserForm.newUserEmail.$setValidity('available', false);
                 $scope.userTelSuccess = false;
                 $scope.userTelError = false;
-                $scope.userEmailSuccess = false;
-                $scope.userEmailError = false;
             }, function (response) {
             	$scope.submit = false;
             	$scope.loading = false;

+ 4 - 5
src/main/webapp/resources/tpl/index/approvalFlow/user.html

@@ -350,12 +350,11 @@
 					添加用户
 				</a>
 				<ul ng-show="adding != true" class="list-unstyle list-inline operator-menu2">
-					<li><a ng-click="adding = true">添加未注册用户</a></li>
+					<li><a ng-click="closeNewUser()">添加未注册用户</a></li>
 					<li><a ng-click="addExistUser()">添加已注册用户</a></li>
 				</ul>
 			</div>
 			<!-- 添加用户 end -->
-
 		</div>
 	</div>
 	<div class="pane-body" id="order-detail-list">
@@ -382,7 +381,7 @@
 					</tr>
 				</thead>
 				<tbody>
-					<tr ng-show="adding">
+					<tr ng-if="adding">
 						<td class="text-center">
 							<div style="line-height: 30px;">系统生成</div>
 						</td>
@@ -402,7 +401,7 @@
 							ng-class="{'has-error': userTelError, 'has-success': userTelSuccess}">
 							<input ng-model="newUser.userTel"
 							ng-blur="telValid(newUser.userTel)" required name="newUserTel"
-							class="form-control input-sm" ng-pattern="/^1[3|4|5|7|8]\d{9}$/" type="text" placeholder="手机号">
+							class="form-control input-sm" ng-pattern="/^1\d{10}$/" type="text" placeholder="手机号">
 						</td>
 						<td class="text-center"
 							ng-class="{'has-error': userEmailError, 'has-success': userEmailSuccess}">
@@ -420,7 +419,7 @@
 						<!--<td class="text-center" ng-bind="::u.userSex == 'F' ? '女' : '男'"></td>-->
 						<!--<td class="text-center" ng-bind="::u.userIdcode"></td>-->
 						<td class="text-center" ng-bind="::u.userTel"></td>
-						<td class="text-center" ng-bind="::u.userEmail"></td>
+						<td class="text-center" ng-bind="::u.userEmail || '-'"></td>
 						<td class="user-role">
 							<div class="role-item" ng-repeat="role in u.roles"
 								 title="{{role.desc}}">

+ 54 - 14
src/main/webapp/resources/tpl/index/fa/apCheck.html

@@ -164,7 +164,7 @@
     color: #fff;
     border: 1px solid #fff;
     margin-top: 3px;
-    padding: 0 5px;"  ng-click="setActive()">查看对账记录
+    padding: 0 5px;"  ng-click="setActive();changeDateZone(1, true);condition.$open=false;showNotCheck=false">查看对账记录
 				<!--<b class="new-dot" ng-if="unread.cancelled > 0">{{unread.cancelled > 99 ? '99+' : unread.cancelled}}</b>-->
 			</div>
 		</div>
@@ -241,6 +241,7 @@
 						<a ng-click="condition.$open=!condition.$open;changeDateZone(-1)" title="自定义" ng-class="{'active':condition.dateZone=='-1'}" >自定义</a>
 					</div>
 					<div  style="float: left" ng-show="active === 'all'" >
+						<div style="width: 355px;display: inline-block">
 						<label class="control-label">请选择月份:</label>
 						<span ng-click="addMouthOut(-1)" style="display: inline-block;
 							width: 32px;
@@ -270,6 +271,45 @@
 							line-height: 32px;
 							cursor: pointer;
 							vertical-align: middle;"><img src="static/img/vendor/images/arrow-right-d-l.png" width="24"/></span>
+						</div>
+						<a ng-click="condition.$open=!condition.$open;changeDateZone(1)" title="自定义" ng-class="{'active':condition.dateZone=='-1'}" style="margin-left: 10px;display: inline-block;padding: 7px 12px;background: #3f84f6;color: #fff" >自定义</a>
+						<div class="more-list more" ng-class="{'open': condition.$open}" ng-if="active === 'all'">
+							<form class="form-inline">
+								<div class="form-group ">
+									<label>日期:</label>
+									<div class="form-group input-group input-group-xs input-trigger">
+										<input type="text" ng-model="condition.dateFrom"
+											   class="form-control" placeholder="从"
+											   datepicker-popup="yyyy-MM-dd" is-open="condition.$fromOpened"
+											   ng-required="true" max-date = "condition.dateTo"
+											   current-text="今天" clear-text="清除" close-text="关闭"
+											   datepicker-options="{formatDayTitle: 'yyyy年M月', formatMonth: 'M月', showWeeks: false}"
+											   ng-focus="openFilterDatePicker($event, condition, '$fromOpened')">
+										<span class="input-group-btn">
+											<button type="button" class="btn btn-default"
+													ng-click="openFilterDatePicker($event, condition, '$fromOpened')">
+												<i class="fa fa-calendar"></i>
+											</button>
+										</span>
+									</div>
+									<div class="form-group input-group input-group-xs input-trigger">
+										<input type="text" ng-model="condition.dateTo"
+											   class="form-control" placeholder="到"
+											   datepicker-popup="yyyy-MM-dd" is-open="condition.$toOpened"
+											   ng-required="true" min-date = "condition.dateFrom"
+											   current-text="今天" clear-text="清除" close-text="关闭"
+											   datepicker-options="{formatDayTitle: 'yyyy年M月', formatMonth: 'M月', showWeeks: false}"
+											   ng-focus="openFilterDatePicker($event, condition, '$toOpened')">
+										<span class="input-group-btn">
+											<button type="button" class="btn btn-default"
+													ng-click="openFilterDatePicker($event, condition, '$toOpened')">
+												<i class="fa fa-calendar"></i>
+											</button>
+										</span>
+									</div>
+								</div>
+							</form>
+						</div>
 					</div>
 					<div class="col-xs-6" style="float: right;">
 						<div class="search">
@@ -285,7 +325,7 @@
 						</div>
 					</div>
 				</div>
-				<div class="more-list more" ng-class="{'open': condition.$open}">
+				<div class="more-list more" ng-class="{'open': condition.$open}" ng-if="active !== 'all'">
 					<form class="form-inline">
 						<div class="form-group ">
 							<label>日期:</label>
@@ -336,9 +376,9 @@
 				<thead>
 					<tr class="header">
 						<th width="180">客户名称</th>
-						<th width="140">本应收</th>
-						<th width="140">本月未对</th>
-						<th width="140">本月已对</th>
+						<th width="140">本应收</th>
+						<th width="140">本期未对账</th>
+						<th width="140">本期已对账</th>
 						<!--<th width="140">本月已收</th>-->
 						<th width="140">应收总额</th>
 						<th width="80">操作</th>
@@ -519,7 +559,7 @@
 						</label>
 					</div>
 					<div style="text-align: left;margin-top: 20px">
-						<label>本期应收总额:</label>
+						<label>本期应收:</label>
 						<label style="text-align:left;vertical-align: top;">
 							<div ng-if="dataInfo.thisMonthCount.length > 0" ng-repeat="count in dataInfo.thisMonthCount">
 								<span>{{count.currency}}:{{count.amount | number:2}}</span>
@@ -530,7 +570,7 @@
 						</label>
 					</div>
 					<div style="text-align: left;margin-top: 20px">
-						<label>本期间未对总额:</label>
+						<label>本期未对账:</label>
 						<label style="text-align:left;vertical-align: top;">
 							<div ng-if="dataInfo.thisMonthTodoCount.length > 0" ng-repeat="count in dataInfo.thisMonthTodoCount">
 								<span>{{count.currency}}:{{count.amount | number:2}}</span>
@@ -541,7 +581,7 @@
 						</label>
 					</div>
 					<div style="text-align: left;margin-top: 20px">
-						<label>本期间已对总额:</label>
+						<label>本期已对账:</label>
 						<label style="text-align:left;vertical-align: top;">
 							<div ng-if="dataInfo.thisMonthDoneCount.length > 0" ng-repeat="count in dataInfo.thisMonthDoneCount">
 								<span>{{count.currency}}:{{count.amount | number:2}}</span>
@@ -654,19 +694,19 @@
 			</div>
 			<div class="form-group form-group-sm form-group-inline">
 				<div class="col-sm-12 text-right">
-					<a ng-click="condition.$open=!condition.$open" class="text-simple"><span
-							ng-bind="condition.$open ? '收起筛选条件' : '更多筛选条件'"></span><i
+					<a ng-click="condition.$open2=!condition.$open2" class="text-simple"><span
+							ng-bind="condition.$open2 ? '收起筛选条件' : '更多筛选条件'"></span><i
 							class="fa fa-fw"
-							ng-class="{'fa-angle-up': condition.$open, 'fa-angle-down': !condition.$open}"></i></a>
+							ng-class="{'fa-angle-up': condition.$open2, 'fa-angle-down': !condition.$open2}"></i></a>
 					<div class="btn-group btn-group-sm">
 						<a class="btn btn-default" ng-click="searchOrder()" title="筛选"><i class="fa fa-search fa-fw btn-icon-left"></i>筛选</a>
-						<a class="btn btn-default" ng-click="createApCheck(check.$selected)" ng-disabled="!data || data.length==0"><i class="fa fa-check-circle-o fa-fw btn-icon-left"></i>确认</a>
+						<a class="btn btn-default" ng-click="createApCheck(check.$selected)" ng-disabled="!data || data.length==0"><i class="fa fa-check-circle-o fa-fw btn-icon-left"></i>确认对账</a>
 						<a class="btn btn-default" ng-click="exportApcheckList()" title="导出Excel" ng-disabled="!data || data.length==0"><i class="fa fa-file-text fa-fw btn-icon-left"></i>导出</a>
 					</div>
 				</div>
 			</div>
 			<div class="form-group form-group-sm form-group-inline"
-				 ng-show="condition.$open">
+				 ng-show="condition.$open2">
 				<!--<label class="col-sm-2 control-label">应付供应商:</label>-->
 				<!--<div class="col-sm-4">-->
 					<!--<div class="form-group form-group-sm has-feedback">-->
@@ -696,7 +736,7 @@
                 </div>
 			</div>
 			<div class="form-group form-group-sm form-group-inline"
-				 ng-show="condition.$open">
+				 ng-show="condition.$open2">
 				<label class="col-sm-2 control-label">物料名称:</label>
 				<div class="col-sm-4">
 					<div class="form-group form-group-sm has-feedback">

+ 53 - 13
src/main/webapp/resources/tpl/index/fa/arCheck.html

@@ -165,7 +165,7 @@
     color: #fff;
     border: 1px solid #fff;
     margin-top: 3px;
-    padding: 0 5px;"  ng-click="setActive()">查看对账记录
+    padding: 0 5px;"  ng-click="setActive();changeDateZone(1, true);condition.$open=false;showNotCheck=false">查看对账记录
 				<!--<b class="new-dot" ng-if="unread.cancelled > 0">{{unread.cancelled > 99 ? '99+' : unread.cancelled}}</b>-->
 			</div>
 		</div>
@@ -219,6 +219,7 @@
 						<a ng-click="condition.$open=!condition.$open;changeDateZone(-1)" title="自定义" ng-class="{'active':condition.dateZone=='-1'}" >自定义</a>
 					</div>
 					<div  style="float: left" ng-show="active === 'all'" >
+						<div style="width: 355px;display: inline-block">
 						<label class="control-label">请选择月份:</label>
 						<span ng-click="addMouthOut(-1)" style="display: inline-block;
 							width: 32px;
@@ -248,6 +249,45 @@
 							line-height: 32px;
 							cursor: pointer;
 							vertical-align: middle;"><img src="static/img/vendor/images/arrow-right-d-l.png" width="24"/></span>
+						</div>
+						<a ng-click="condition.$open=!condition.$open;changeDateZone(1)" title="自定义" ng-class="{'active':condition.dateZone=='-1'}" style="margin-left: 10px;display: inline-block;padding: 7px 12px;background: #3f84f6;color: #fff" >自定义</a>
+						<div class="more-list more" ng-class="{'open': condition.$open}" ng-if="active === 'all'">
+							<form class="form-inline">
+								<div class="form-group ">
+									<label>日期:</label>
+									<div class="form-group input-group input-group-xs input-trigger">
+										<input type="text" ng-model="condition.dateFrom"
+											   class="form-control" placeholder="从"
+											   datepicker-popup="yyyy-MM-dd" is-open="condition.$fromOpened"
+											   ng-required="true" max-date = "condition.dateTo"
+											   current-text="今天" clear-text="清除" close-text="关闭"
+											   datepicker-options="{formatDayTitle: 'yyyy年M月', formatMonth: 'M月', showWeeks: false}"
+											   ng-focus="openFilterDatePicker($event, condition, '$fromOpened')">
+										<span class="input-group-btn">
+											<button type="button" class="btn btn-default"
+													ng-click="openFilterDatePicker($event, condition, '$fromOpened')">
+												<i class="fa fa-calendar"></i>
+											</button>
+										</span>
+									</div>
+									<div class="form-group input-group input-group-xs input-trigger">
+										<input type="text" ng-model="condition.dateTo"
+											   class="form-control" placeholder="到"
+											   datepicker-popup="yyyy-MM-dd" is-open="condition.$toOpened"
+											   ng-required="true" min-date = "condition.dateFrom"
+											   current-text="今天" clear-text="清除" close-text="关闭"
+											   datepicker-options="{formatDayTitle: 'yyyy年M月', formatMonth: 'M月', showWeeks: false}"
+											   ng-focus="openFilterDatePicker($event, condition, '$toOpened')">
+										<span class="input-group-btn">
+											<button type="button" class="btn btn-default"
+													ng-click="openFilterDatePicker($event, condition, '$toOpened')">
+												<i class="fa fa-calendar"></i>
+											</button>
+										</span>
+									</div>
+								</div>
+							</form>
+						</div>
 					</div>
 					<div class="col-xs-6" style="float: right;">
 						<div class="search">
@@ -263,7 +303,7 @@
 						</div>
 					</div>
 				</div>
-				<div class="more-list more" ng-class="{'open': condition.$open}">
+				<div class="more-list more" ng-class="{'open': condition.$open}"  ng-if="active !== 'all'">
 					<form class="form-inline">
 						<div class="form-group ">
 							<label>日期:</label>
@@ -314,9 +354,9 @@
 				<thead>
 				<tr class="header">
 					<th width="180">应付供应商名称</th>
-					<th width="140">本应付</th>
-					<th width="140">本月未对</th>
-					<th width="140">本月已对</th>
+					<th width="140">本应付</th>
+					<th width="140">本期未对账</th>
+					<th width="140">本期已对账</th>
 					<!--<th width="140">本月已付</th>-->
 					<th width="140">应付总额</th>
 					<th width="80">操作</th>
@@ -444,7 +484,7 @@
 						</label>
 					</div>
 					<div style="text-align: left;margin-top: 20px">
-						<label>本期间应付总额:</label>
+						<label>本期应收:</label>
 						<label style="text-align:left;vertical-align: top;">
 							<div ng-if="dataInfo.thisMonthCount.length > 0" ng-repeat="count in dataInfo.thisMonthCount">
 								<span>{{count.currency}}:{{count.amount | number:2}}</span>
@@ -456,7 +496,7 @@
 					</div>
 
 					<div style="text-align: left;margin-top: 20px">
-						<label>本期间未对总额:</label>
+						<label>本期未对账:</label>
 						<label style="text-align:left;vertical-align: top;">
 							<div ng-if="dataInfo.thisMonthTodoCount.length > 0" ng-repeat="count in dataInfo.thisMonthTodoCount">
 								<span>{{count.currency}}:{{count.amount | number:2}}</span>
@@ -468,7 +508,7 @@
 					</div>
 
 					<div style="text-align: left;margin-top: 20px">
-						<label>本期间已对总额:</label>
+						<label>本期已对账:</label>
 						<label style="text-align:left;vertical-align: top;">
 							<div ng-if="dataInfo.thisMonthDoneCount.length > 0" ng-repeat="count in dataInfo.thisMonthDoneCount">
 								<span>{{count.currency}}:{{count.amount | number:2}}</span>
@@ -582,10 +622,10 @@
 			</div>
 			<div class="form-group form-group-sm form-group-inline">
 				<div class="col-sm-12 text-right">
-					<a ng-click="condition.$open=!condition.$open" class="text-simple"><span
-							ng-bind="condition.$open ? '收起筛选条件' : '更多筛选条件'"></span><i
+					<a ng-click="condition.$open2=!condition.$open2" class="text-simple"><span
+							ng-bind="condition.$open2 ? '收起筛选条件' : '更多筛选条件'"></span><i
 							class="fa fa-fw"
-							ng-class="{'fa-angle-up': condition.$open, 'fa-angle-down': !condition.$open}"></i></a>
+							ng-class="{'fa-angle-up': condition.$open2, 'fa-angle-down': !condition.$open2}"></i></a>
 					<div class="btn-group btn-group-sm">
 						<a class="btn btn-default" ng-click="searchOrder()" title="筛选"><i class="fa fa-search fa-fw btn-icon-left"></i>筛选</a>
                         <a class="btn btn-default" ng-click="exportApcheckList()" title="导出Excel" ng-disabled="!data || data.length==0"><i class="fa fa-file-text fa-fw btn-icon-left"></i>导出</a>
@@ -593,7 +633,7 @@
 				</div>
 			</div>
 			<div class="form-group form-group-sm form-group-inline"
-				 ng-show="condition.$open">
+				 ng-show="condition.$open2">
 				<label class="col-sm-2 control-label">送货工厂:</label>
 				<div class="col-sm-4">
 					<div class="form-group form-group-sm has-feedback">
@@ -614,7 +654,7 @@
 				</div>
 			</div>
 			<div class="form-group form-group-sm form-group-inline"
-				 ng-show="condition.$open">
+				 ng-show="condition.$open2">
 				<label class="col-sm-2 control-label">物料名称:</label>
 				<div class="col-sm-4">
 					<div class="form-group form-group-sm has-feedback">

+ 33 - 0
src/test/java/com/uas/platform/b2b/purc/PurchaseNotify.java

@@ -1,6 +1,8 @@
 package com.uas.platform.b2b.purc;
 
 import com.uas.platform.b2b.BaseJunitTest;
+import com.uas.platform.b2b.core.util.DateFormatUtils;
+import com.uas.platform.b2b.dao.CommonDao;
 import com.uas.platform.b2b.dao.PurchaseNoticeDao;
 import com.uas.platform.b2b.dao.PurchaseOrderItemDao;
 import com.uas.platform.b2b.model.PurchaseNotice;
@@ -29,6 +31,9 @@ public class PurchaseNotify extends BaseJunitTest {
     @Autowired
     private EntityManagerFactory entityManagerFactory;
 
+    @Autowired
+    private CommonDao commonDao;
+
     @PersistenceContext
     protected EntityManager em;
 
@@ -126,4 +131,32 @@ public class PurchaseNotify extends BaseJunitTest {
         return notice;
     }
 
+
+    /**
+     * // 测试用例
+     // -1, 不跨年,25日前
+     sendDate(-1, '2018-12-23')  期望结果: '2018-11-26'
+     // -1,不跨年,26日后
+     sendDate(-1, '2018-12-28')  期望结果: '2018-11-26'
+     // -1, 跨年,25日前
+     sendDate(-1, '2019-01-23')  期望结果: '2018-12-26'
+     // -1,跨年,26日后
+     sendDate(-1, '2019-01-28')  期望结果: '2018-12-26'
+     // >=0, 不跨年,不跨月
+     sendDate(5, '2018-12-23')  期望结果: '2018-12-17'
+     // >=0,不跨年,跨月,有31号
+     sendDate(5, '2018-12-02')  期望结果: '2018-11-26'
+     // >=0,不跨年,跨月,无31号
+     sendDate(5, '2018-11-02')  期望结果: '2018-10-27'
+     // >=0, 跨年,不跨月
+     sendDate(5, '2019-01-23')  期望结果: '2019-01-17'
+     // >=0,跨年,跨月
+     sendDate(5, '2019-01-02')  期望结果: '2018-12-27'
+     */
+    @Test
+    public void getSendDelivery() {
+        StringBuffer sql = new StringBuffer("select purc_notice_delivery('").append("2018-12-23").append("', ").append("-1").append(")");
+        Date delivery = commonDao.queryForObject(sql.toString(), Date.class);
+        System.out.println(delivery);
+    }
 }