Commit 28be17376aa39d5b78709e248fc89709ef434822

Authored by 王彪总
1 parent 35590a5b

feat(garden): 新增任务距离排序和智能排序功能

- 实现任务按距离排序和班组进度统计功能
- 添加任务智能排序(距离+个人效率加权)功能
- 新增GPS距离计算工具类和相关数据传输对象
- 添加出行速度配置和智能排序权重配置字典类型
- 实现用户任务效率预计算定时任务
- 优化API签名切面注解使用方式
- 添加微信公众号开放平台回调接口免登录配置
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/app/homepage/vo/TaskDetailsRspVo.java
@@ -17,9 +17,13 @@ public class TaskDetailsRspVo { @@ -17,9 +17,13 @@ public class TaskDetailsRspVo {
17 private String taskName; 17 private String taskName;
18 /*创建时间或完成时间*/ 18 /*创建时间或完成时间*/
19 private LocalDateTime busiDateTime; 19 private LocalDateTime busiDateTime;
20 - /**  
21 - * 紧急程度:1:特急;2:紧急;3:一般  
22 - */ 20 + /*紧急程度:1:特急;2:紧急;3:一般*/
23 private Integer pressingType; 21 private Integer pressingType;
  22 + /*计划编码*/
  23 + private String planNo;
  24 + /*批次号*/
  25 + private String batchNo;
  26 + /*任务类型:inspection/maintain/workorder*/
  27 + private String taskType;
24 28
25 } 29 }
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/app/homepage/vo/TaskDistanceSortRespVO.java
@@ -14,9 +14,6 @@ import java.math.BigDecimal; @@ -14,9 +14,6 @@ import java.math.BigDecimal;
14 @EqualsAndHashCode(callSuper = true) 14 @EqualsAndHashCode(callSuper = true)
15 public class TaskDistanceSortRespVO extends TaskDetailsRspVo { 15 public class TaskDistanceSortRespVO extends TaskDetailsRspVo {
16 16
17 - /** 任务类型:inspection / maintain / workorder */  
18 - private String taskType;  
19 -  
20 /** 任务点经度 */ 17 /** 任务点经度 */
21 private BigDecimal taskLon; 18 private BigDecimal taskLon;
22 19
@@ -47,6 +44,9 @@ public class TaskDistanceSortRespVO extends TaskDetailsRspVo { @@ -47,6 +44,9 @@ public class TaskDistanceSortRespVO extends TaskDetailsRspVo {
47 /** 效率得分(已截断) */ 44 /** 效率得分(已截断) */
48 private Double efficiencyScore; 45 private Double efficiencyScore;
49 46
  47 + /** 员工历史任务完成效率 %,100=班组均值,大于100比班组快,小于100比班组慢 */
  48 + private Integer efficiencyPercent;
  49 +
50 /** 综合得分 */ 50 /** 综合得分 */
51 private Double compositeScore; 51 private Double compositeScore;
52 52
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/homepage/HomepageSummaryServiceImpl.java
@@ -3,6 +3,7 @@ package com.zteits.urbanops.module.garden.service.homepage; @@ -3,6 +3,7 @@ package com.zteits.urbanops.module.garden.service.homepage;
3 import cn.hutool.core.bean.BeanUtil; 3 import cn.hutool.core.bean.BeanUtil;
4 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
5 import com.baomidou.mybatisplus.core.metadata.IPage; 5 import com.baomidou.mybatisplus.core.metadata.IPage;
  6 +import com.alibaba.fastjson.JSON;
6 import com.esotericsoftware.minlog.Log; 7 import com.esotericsoftware.minlog.Log;
7 import com.zteits.urbanops.framework.common.pojo.PageResult; 8 import com.zteits.urbanops.framework.common.pojo.PageResult;
8 import com.zteits.urbanops.framework.common.util.date.DateUtils; 9 import com.zteits.urbanops.framework.common.util.date.DateUtils;
@@ -465,6 +466,7 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{ @@ -465,6 +466,7 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{
465 result.setEstimatedTotalWalkingMinutes(totalWalkMin); 466 result.setEstimatedTotalWalkingMinutes(totalWalkMin);
466 result.setEstimatedTotalTricycleMinutes(totalTriMin); 467 result.setEstimatedTotalTricycleMinutes(totalTriMin);
467 468
  469 + Log.info("返回App参数: " + JSON.toJSONString(result));
468 return result; 470 return result;
469 } 471 }
470 472
@@ -480,10 +482,15 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{ @@ -480,10 +482,15 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{
480 if (mpPage != null && CollectionUtils.isNotEmpty(mpPage.getRecords())) { 482 if (mpPage != null && CollectionUtils.isNotEmpty(mpPage.getRecords())) {
481 int i = 0; 483 int i = 0;
482 for (TaskDetailsRspVo vo : mpPage.getRecords()) { 484 for (TaskDetailsRspVo vo : mpPage.getRecords()) {
  485 + // 跳过工单,仅返回巡查/养护
  486 + if ("workorder".equals(vo.getTaskType())) continue;
483 TaskDistanceSortRespVO sortVo = new TaskDistanceSortRespVO(); 487 TaskDistanceSortRespVO sortVo = new TaskDistanceSortRespVO();
484 sortVo.setTaskName(vo.getTaskName()); 488 sortVo.setTaskName(vo.getTaskName());
485 sortVo.setBusiDateTime(vo.getBusiDateTime()); 489 sortVo.setBusiDateTime(vo.getBusiDateTime());
486 sortVo.setPressingType(vo.getPressingType()); 490 sortVo.setPressingType(vo.getPressingType());
  491 + sortVo.setPlanNo(vo.getPlanNo());
  492 + sortVo.setBatchNo(vo.getBatchNo());
  493 + sortVo.setTaskType(vo.getTaskType());
487 sortVo.setSortOrder(++i); 494 sortVo.setSortOrder(++i);
488 sortVo.setDistance(null); 495 sortVo.setDistance(null);
489 sortVo.setCumulativeDistance(null); 496 sortVo.setCumulativeDistance(null);
@@ -492,6 +499,7 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{ @@ -492,6 +499,7 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{
492 result.add(sortVo); 499 result.add(sortVo);
493 } 500 }
494 } 501 }
  502 + Log.info("返回App参数: " + JSON.toJSONString(result));
495 return result; 503 return result;
496 } 504 }
497 505
@@ -620,8 +628,9 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{ @@ -620,8 +628,9 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{
620 } 628 }
621 int memberCount = teamData.size(); 629 int memberCount = teamData.size();
622 teamProgress.setTeamMemberCount(memberCount); 630 teamProgress.setTeamMemberCount(memberCount);
623 - teamProgress.setTeamAverage(memberCount > 0  
624 - ? Math.round(totalCompleted * 10.0 / memberCount) / 10.0 : 0.0); 631 + double avg = memberCount > 0 ? Math.round(totalCompleted * 10.0 / memberCount) / 10.0 : 0.0;
  632 + if (avg == 0.0 && totalCompleted > 0) avg = 0.1;
  633 + teamProgress.setTeamAverage(avg);
625 teamProgress.setTeamMax(maxCompleted); 634 teamProgress.setTeamMax(maxCompleted);
626 } 635 }
627 } catch (Exception e) { 636 } catch (Exception e) {
@@ -643,7 +652,8 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{ @@ -643,7 +652,8 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{
643 result.setSortedTasks(sortedTasks); 652 result.setSortedTasks(sortedTasks);
644 result.setTeamProgress(teamProgress); 653 result.setTeamProgress(teamProgress);
645 result.setTotalPendingTasks(sortedTasks.size()); 654 result.setTotalPendingTasks(sortedTasks.size());
646 - return result; 655 + Log.info("返回App参数: " + JSON.toJSONString(result));
  656 + return result;
647 } 657 }
648 658
649 List<Long> roleIds = roleApi.getRoleIdsByUserId(userId); 659 List<Long> roleIds = roleApi.getRoleIdsByUserId(userId);
@@ -676,31 +686,34 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{ @@ -676,31 +686,34 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{
676 .queryPendingTaskDetailsWithGps(roleIds, userId, deptId, LocalDateTime.now()); 686 .queryPendingTaskDetailsWithGps(roleIds, userId, deptId, LocalDateTime.now());
677 687
678 // 3. 查询效率矩阵 688 // 3. 查询效率矩阵
679 - Map<String, BigDecimal> effMap = loadEfficiencyMap(userId); 689 + Map<String, UserTaskEfficiencyDO> effMap = loadEfficiencyMap(userId);
680 690
681 // 4. 为每个任务打分 691 // 4. 为每个任务打分
682 List<TaskDistanceSortRespVO> tasksWithGps = new ArrayList<>(); 692 List<TaskDistanceSortRespVO> tasksWithGps = new ArrayList<>();
683 List<TaskDistanceSortRespVO> tasksWithoutGps = new ArrayList<>(); 693 List<TaskDistanceSortRespVO> tasksWithoutGps = new ArrayList<>();
684 if (CollectionUtils.isNotEmpty(allTasks)) { 694 if (CollectionUtils.isNotEmpty(allTasks)) {
685 for (TaskDistanceSortRespVO task : allTasks) { 695 for (TaskDistanceSortRespVO task : allTasks) {
  696 + UserTaskEfficiencyDO effDO = lookupEfficiency(effMap, task.getTaskType(), task.getTaskSubType());
  697 + BigDecimal effRatio = (effDO != null && effDO.getEfficiencyRatio() != null)
  698 + ? effDO.getEfficiencyRatio() : BigDecimal.ONE;
  699 + double effScore = clamp(effRatio.doubleValue(), clampMin, clampMax);
  700 + task.setEfficiencyScore(Math.round(effScore * 100.0) / 100.0);
  701 + task.setEfficiencyPercent((int) Math.round(effRatio.doubleValue() * 100));
  702 + if (effDO != null) {
  703 + task.setUserAvgMinutes(effDO.getAvgMinutes());
  704 + task.setTeamAvgMinutes(effDO.getTeamAvgMinutes());
  705 + }
  706 +
686 if (task.getTaskLat() != null && task.getTaskLon() != null) { 707 if (task.getTaskLat() != null && task.getTaskLon() != null) {
687 double dist = GpsDistanceUtil.haversineDistance( 708 double dist = GpsDistanceUtil.haversineDistance(
688 req.getCurrentLat().doubleValue(), req.getCurrentLon().doubleValue(), 709 req.getCurrentLat().doubleValue(), req.getCurrentLon().doubleValue(),
689 task.getTaskLat().doubleValue(), task.getTaskLon().doubleValue()); 710 task.getTaskLat().doubleValue(), task.getTaskLon().doubleValue());
690 double distScore = Math.max(0, 1 - dist / threshold); 711 double distScore = Math.max(0, 1 - dist / threshold);
691 task.setDistanceScore(Math.round(distScore * 100.0) / 100.0); 712 task.setDistanceScore(Math.round(distScore * 100.0) / 100.0);
692 -  
693 - BigDecimal effRatio = lookupEfficiency(effMap, task.getTaskType(), task.getTaskSubType());  
694 - double effScore = clamp(effRatio.doubleValue(), clampMin, clampMax);  
695 - task.setEfficiencyScore(Math.round(effScore * 100.0) / 100.0);  
696 -  
697 task.setCompositeScore(Math.round((distWeight * distScore + effWeight * effScore) * 100.0) / 100.0); 713 task.setCompositeScore(Math.round((distWeight * distScore + effWeight * effScore) * 100.0) / 100.0);
698 tasksWithGps.add(task); 714 tasksWithGps.add(task);
699 } else { 715 } else {
700 - BigDecimal effRatio = lookupEfficiency(effMap, task.getTaskType(), task.getTaskSubType());  
701 - double effScore = clamp(effRatio.doubleValue(), clampMin, clampMax);  
702 task.setDistanceScore(0.0); 716 task.setDistanceScore(0.0);
703 - task.setEfficiencyScore(Math.round(effScore * 100.0) / 100.0);  
704 task.setCompositeScore(Math.round((effWeight * effScore) * 100.0) / 100.0); 717 task.setCompositeScore(Math.round((effWeight * effScore) * 100.0) / 100.0);
705 tasksWithoutGps.add(task); 718 tasksWithoutGps.add(task);
706 } 719 }
@@ -744,19 +757,19 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{ @@ -744,19 +757,19 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{
744 if (t.getDistance() != null) totalDist += t.getDistance(); 757 if (t.getDistance() != null) totalDist += t.getDistance();
745 } 758 }
746 result.setEstimatedTotalDistance(totalDist); 759 result.setEstimatedTotalDistance(totalDist);
  760 + Log.info("返回App参数: " + JSON.toJSONString(result));
747 return result; 761 return result;
748 } 762 }
749 763
750 /** 764 /**
751 * 加载当前用户当月效率矩阵 765 * 加载当前用户当月效率矩阵
752 */ 766 */
753 - private Map<String, BigDecimal> loadEfficiencyMap(Long userId) {  
754 - Map<String, BigDecimal> map = new LinkedHashMap<>(); 767 + private Map<String, UserTaskEfficiencyDO> loadEfficiencyMap(Long userId) {
  768 + Map<String, UserTaskEfficiencyDO> map = new LinkedHashMap<>();
755 try { 769 try {
756 String statPeriod = java.time.LocalDate.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM")); 770 String statPeriod = java.time.LocalDate.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM"));
757 List<UserTaskEfficiencyDO> list = userTaskEfficiencyMapper.selectByUserIdAndPeriod(userId, statPeriod); 771 List<UserTaskEfficiencyDO> list = userTaskEfficiencyMapper.selectByUserIdAndPeriod(userId, statPeriod);
758 if (CollectionUtils.isEmpty(list)) { 772 if (CollectionUtils.isEmpty(list)) {
759 - // fallback: 查最近一个周期的数据  
760 String latestPeriod = userTaskEfficiencyMapper.selectLatestPeriod(userId); 773 String latestPeriod = userTaskEfficiencyMapper.selectLatestPeriod(userId);
761 if (latestPeriod != null) { 774 if (latestPeriod != null) {
762 list = userTaskEfficiencyMapper.selectByUserIdAndPeriod(userId, latestPeriod); 775 list = userTaskEfficiencyMapper.selectByUserIdAndPeriod(userId, latestPeriod);
@@ -765,7 +778,7 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{ @@ -765,7 +778,7 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{
765 if (CollectionUtils.isNotEmpty(list)) { 778 if (CollectionUtils.isNotEmpty(list)) {
766 for (UserTaskEfficiencyDO e : list) { 779 for (UserTaskEfficiencyDO e : list) {
767 String key = e.getTaskCategory() + "_" + e.getTaskType(); 780 String key = e.getTaskCategory() + "_" + e.getTaskType();
768 - map.put(key, e.getEfficiencyRatio() != null ? e.getEfficiencyRatio() : BigDecimal.ONE); 781 + map.put(key, e);
769 } 782 }
770 } 783 }
771 } catch (Exception e) { 784 } catch (Exception e) {
@@ -774,18 +787,12 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{ @@ -774,18 +787,12 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{
774 return map; 787 return map;
775 } 788 }
776 789
777 - /**  
778 - * 从效率矩阵查找,先精确匹配再 fallback 大类  
779 - */  
780 - private BigDecimal lookupEfficiency(Map<String, BigDecimal> map, String category, String subType) {  
781 - // 精确匹配 790 + private UserTaskEfficiencyDO lookupEfficiency(Map<String, UserTaskEfficiencyDO> map, String category, String subType) {
782 String exactKey = category + "_" + subType; 791 String exactKey = category + "_" + subType;
783 if (map.containsKey(exactKey)) return map.get(exactKey); 792 if (map.containsKey(exactKey)) return map.get(exactKey);
784 - // fallback: 大类汇总  
785 String fallbackKey = category + "_ALL"; 793 String fallbackKey = category + "_ALL";
786 if (map.containsKey(fallbackKey)) return map.get(fallbackKey); 794 if (map.containsKey(fallbackKey)) return map.get(fallbackKey);
787 - // 无数据:中性  
788 - return BigDecimal.ONE; 795 + return null;
789 } 796 }
790 797
791 private double clamp(double val, double min, double max) { 798 private double clamp(double val, double min, double max) {
urbanops-module-garden/src/main/resources/mapper/homepage/HomepageSummaryMapper.xml
@@ -376,26 +376,29 @@ @@ -376,26 +376,29 @@
376 <!--已完成任务详情--> 376 <!--已完成任务详情-->
377 <select id="queryCompletedTaskDetails" resultType="com.zteits.urbanops.module.garden.controller.app.homepage.vo.TaskDetailsRspVo" > 377 <select id="queryCompletedTaskDetails" resultType="com.zteits.urbanops.module.garden.controller.app.homepage.vo.TaskDetailsRspVo" >
378 378
379 - SELECT taskName, busiDateTime, pressingType 379 + SELECT taskName, busiDateTime, pressingType, taskType, planNo, batchNo
380 FROM ( 380 FROM (
381 -- 巡查已办理 381 -- 巡查已办理
382 - SELECT B.plan_name as taskName,A.finish_time as busiDateTime, null as pressingType 382 + SELECT B.plan_name as taskName,A.finish_time as busiDateTime, null as pressingType,
  383 + 'inspection' as taskType, a.plan_no as planNo, a.batch_no as batchNo
383 from garden_inspection_plan_commit a , garden_inspection_plan b 384 from garden_inspection_plan_commit a , garden_inspection_plan b
384 where a.batch_no=b.batch_no 385 where a.batch_no=b.batch_no
385 and user_id = #{userId} 386 and user_id = #{userId}
386 union all 387 union all
387 -- 养护已办理 388 -- 养护已办理
388 - SELECT b.plan_name as taskName,a.finish_time as busiDateTime, null as pressingType 389 + SELECT b.plan_name as taskName,a.finish_time as busiDateTime, null as pressingType,
  390 + 'maintain' as taskType, a.plan_no as planNo, a.batch_no as batchNo
389 from garden_maintain_plan_commit a , garden_maintain_plan b 391 from garden_maintain_plan_commit a , garden_maintain_plan b
390 where a.batch_no=b.batch_no 392 where a.batch_no=b.batch_no
391 and user_id = #{userId} 393 and user_id = #{userId}
392 union all 394 union all
393 -- 工单已办 395 -- 工单已办
394 SELECT 396 SELECT
395 - res.order_name as taskName, res.create_time as busiDateTime, res.pressing_type as pressingType 397 + res.order_name as taskName, res.create_time as busiDateTime, res.pressing_type as pressingType,
  398 + 'workorder' as taskType, res.order_no as planNo, null as batchNo
396 FROM ( 399 FROM (
397 SELECT 400 SELECT
398 - m.order_name,m.create_time, m.pressing_type, 401 + m.order_name,m.create_time, m.pressing_type, m.order_no,
399 ROW_NUMBER() OVER ( 402 ROW_NUMBER() OVER (
400 PARTITION BY m.order_no 403 PARTITION BY m.order_no
401 ORDER BY t.START_TIME_ DESC, t.ID_ DESC 404 ORDER BY t.START_TIME_ DESC, t.ID_ DESC
@@ -617,7 +620,7 @@ @@ -617,7 +620,7 @@
617 620
618 <!-- 查询今日待办任务(含 GPS 坐标) --> 621 <!-- 查询今日待办任务(含 GPS 坐标) -->
619 <select id="queryPendingTaskDetailsWithGps" resultType="com.zteits.urbanops.module.garden.controller.app.homepage.vo.TaskDistanceSortRespVO"> 622 <select id="queryPendingTaskDetailsWithGps" resultType="com.zteits.urbanops.module.garden.controller.app.homepage.vo.TaskDistanceSortRespVO">
620 - SELECT taskName, busiDateTime, pressingType, taskLat, taskLon, taskType, taskSubType 623 + SELECT taskName, busiDateTime, pressingType, taskLat, taskLon, taskType, taskSubType, planNo, batchNo
621 FROM ( 624 FROM (
622 SELECT 625 SELECT
623 a.plan_name AS taskName, 626 a.plan_name AS taskName,
@@ -628,7 +631,9 @@ @@ -628,7 +631,9 @@
628 (CAST(r.starting_longitude AS DECIMAL(18,10)) 631 (CAST(r.starting_longitude AS DECIMAL(18,10))
629 + CAST(r.end_longitude AS DECIMAL(18,10))) / 2 AS taskLon, 632 + CAST(r.end_longitude AS DECIMAL(18,10))) / 2 AS taskLon,
630 'inspection' AS taskType, 633 'inspection' AS taskType,
631 - a.plan_type_id AS taskSubType 634 + a.plan_type_id AS taskSubType,
  635 + c.plan_no AS planNo,
  636 + c.batch_no AS batchNo
632 FROM garden_inspection_plan a 637 FROM garden_inspection_plan a
633 INNER JOIN garden_inspection_plan_role b ON a.batch_no = b.batch_no 638 INNER JOIN garden_inspection_plan_role b ON a.batch_no = b.batch_no
634 INNER JOIN garden_inspection_plan_detail c ON a.batch_no = c.batch_no 639 INNER JOIN garden_inspection_plan_detail c ON a.batch_no = c.batch_no
@@ -655,7 +660,9 @@ @@ -655,7 +660,9 @@
655 (CAST(r.starting_longitude AS DECIMAL(18,10)) 660 (CAST(r.starting_longitude AS DECIMAL(18,10))
656 + CAST(r.end_longitude AS DECIMAL(18,10))) / 2 AS taskLon, 661 + CAST(r.end_longitude AS DECIMAL(18,10))) / 2 AS taskLon,
657 'maintain' AS taskType, 662 'maintain' AS taskType,
658 - a.plan_type_id AS taskSubType 663 + a.plan_type_id AS taskSubType,
  664 + c.plan_no AS planNo,
  665 + c.batch_no AS batchNo
659 FROM garden_maintain_plan a 666 FROM garden_maintain_plan a
660 INNER JOIN garden_maintain_plan_role b ON a.batch_no = b.batch_no 667 INNER JOIN garden_maintain_plan_role b ON a.batch_no = b.batch_no
661 INNER JOIN garden_maintain_plan_detail c ON a.batch_no = c.batch_no 668 INNER JOIN garden_maintain_plan_detail c ON a.batch_no = c.batch_no
@@ -670,23 +677,6 @@ @@ -670,23 +677,6 @@
670 #{roleId} 677 #{roleId}
671 </foreach> 678 </foreach>
672 AND r.starting_latitude IS NOT NULL AND r.starting_latitude != '' 679 AND r.starting_latitude IS NOT NULL AND r.starting_latitude != ''
673 -  
674 - UNION ALL  
675 -  
676 - SELECT  
677 - m.order_name AS taskName,  
678 - m.create_time AS busiDateTime,  
679 - m.pressing_type AS pressingType,  
680 - m.lat AS taskLat,  
681 - m.lon AS taskLon,  
682 - 'workorder' AS taskType,  
683 - m.order_type AS taskSubType  
684 - FROM act_ru_task t  
685 - LEFT JOIN workorder_main_info m  
686 - ON t.PROC_INST_ID_ = m.process_instance_id AND m.deleted = 0  
687 - WHERE t.SUSPENSION_STATE_ = 1  
688 - AND m.order_name IS NOT NULL  
689 - AND t.ASSIGNEE_ = #{userId}  
690 ) t 680 ) t
691 </select> 681 </select>
692 682