Compare commits

...

No commits in common. "main" and "master" have entirely different histories.
main ... master

10 changed files with 22 additions and 474 deletions

33
.gitignore vendored
View File

@ -1,19 +1,26 @@
.iml
/out/
/.idea/
# ---> Java
# Compiled class file
*.class
# Log file
*.log
HELP.md
target/
# BlueJ files
*.ctxt
### IntelliJ IDEA ###
.idea
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
/src/test
/src/rebel.xml
/src/META-INF
### IntelliJ IDEA ###
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
replay_pid*
/log
/build/

2
README.md Normal file
View File

@ -0,0 +1,2 @@
# weaver-jcl-recruit

View File

@ -1,6 +0,0 @@
description = "子模块demo项目"
dependencies {
//
implementation project(':secondev-chapanda-portal')
}

View File

@ -1,41 +0,0 @@
package com.weaver.seconddev.feishu.controller;
import com.weaver.common.authority.annotation.WeaPermission;
import com.weaver.seconddev.feishu.service.EmployeePanelService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
/**
* @author:dxfeng
* @createTime: 2025/07/15
* @version: 1.0
*/
@Slf4j
@RestController
@RequestMapping("/api/secondev/panel/employee")
@WeaPermission(publicPermission = true)
public class EmployeePanelController {
@Autowired
EmployeePanelService employeePanelService;
@GetMapping("/getAttendInfo")
public Object getAttendInfo(@RequestParam("beginDate") String beginDate,
@RequestParam("endDate") String endDate,
@RequestParam("jobNum") String jobNum) {
log.error("beginDate:{},endDate:{},jobNum:{}", beginDate, endDate, jobNum);
Map<String, Object> params = new HashMap<>();
params.put("beginDate", beginDate);
params.put("endDate", endDate);
params.put("jobNum", jobNum);
return employeePanelService.getAttendInfo(params);
}
}

View File

@ -1,41 +0,0 @@
package com.weaver.seconddev.feishu.controller;
import com.weaver.common.authority.annotation.WeaPermission;
import com.weaver.seconddev.feishu.service.EmployeePanelService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
/**
* @author:dxfeng
* @createTime: 2025/07/15
* @version: 1.0
*/
@Slf4j
@RestController
@RequestMapping("/sapi/secondev/panel/employee")
@WeaPermission(publicPermission = true)
public class OutEmployeePanelController {
@Autowired
EmployeePanelService employeePanelService;
@GetMapping("/getAttendInfo")
public Object getAttendInfo(@RequestParam("beginDate") String beginDate,
@RequestParam("endDate") String endDate,
@RequestParam("jobNum") String jobNum) {
log.error("beginDate:{},endDate:{},jobNum:{}", beginDate, endDate, jobNum);
Map<String, Object> params = new HashMap<>();
params.put("beginDate", beginDate);
params.put("endDate", endDate);
params.put("jobNum", jobNum);
return employeePanelService.getAttendInfo(params);
}
}

View File

@ -1,26 +0,0 @@
package com.weaver.seconddev.feishu.entity.po;
import lombok.Data;
/**
* @author:dxfeng
* @createTime: 2025/07/15
* @version: 1.0
*/
@Data
public class EmployeeAttendInfoPo {
/**
* 工号
*/
private String workCode;
/**
* 应出勤天数
*/
private String expectedAttendance;
/**
* 实际出勤
*/
private String actualAttendance;
}

View File

@ -1,25 +0,0 @@
package com.weaver.seconddev.feishu.mapper;
import com.weaver.seconddev.portal.entity.param.BaseParam;
import org.apache.ibatis.annotations.MapKey;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* @author:dxfeng
* @createTime: 2025/07/15
* @version: 1.0
*/
@Mapper
public interface EmployeePanelMapper {
@MapKey("employee")
Map<BigDecimal, Map<String, Object>> statsWorkTimeLength(@Param("param") BaseParam param, @Param(value = "empIds") List<Long> empIds, @Param(value = "beginDate") Date beginDate, @Param(value = "endDate") Date endDate,
@Param(value = "tenantKey") String tenantKey, @Param("extraAbsenteeism") boolean extraAbsenteeism, @Param("hasDetailExtend") boolean hasDetailExtend);
}

View File

@ -1,22 +0,0 @@
package com.weaver.seconddev.feishu.service;
import com.weaver.common.base.entity.result.WeaResult;
import com.weaver.seconddev.feishu.entity.po.EmployeeAttendInfoPo;
import java.util.Map;
/**
* @author:dxfeng
* @createTime: 2025/07/15
* @version: 1.0
*/
public interface EmployeePanelService {
/**
* 获取考勤信息
*
* @param params
* @return
*/
WeaResult<EmployeeAttendInfoPo> getAttendInfo(Map<String, Object> params);
}

View File

@ -1,114 +0,0 @@
package com.weaver.seconddev.feishu.service.impl;
import com.weaver.common.base.entity.result.WeaResult;
import com.weaver.common.hr.util.Util;
import com.weaver.seconddev.feishu.entity.po.EmployeeAttendInfoPo;
import com.weaver.seconddev.feishu.mapper.EmployeePanelMapper;
import com.weaver.seconddev.feishu.service.EmployeePanelService;
import com.weaver.seconddev.portal.entity.param.BaseParam;
import com.weaver.workflow.common.cfg.org.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* @author:dxfeng
* @createTime: 2025/07/15
* @version: 1.0
*/
@Slf4j
@Service
public class EmployeePanelServiceImpl implements EmployeePanelService {
@Autowired
EmployeePanelMapper employeePanelMapper;
@Autowired
UserService userService;
@Override
public WeaResult<EmployeeAttendInfoPo> getAttendInfo(Map<String, Object> params) {
String jobNum = Util.null2String(params.get("jobNum"));
String beginDateStr = Util.null2String(params.get("beginDate"));
String endDateStr = Util.null2String(params.get("endDate"));
BaseParam baseParam = new BaseParam();
List<Long> userIdsByJobNum = userService.getUserIdsByJobNum(jobNum, baseParam.getTenantKey());
if (CollectionUtils.isEmpty(userIdsByJobNum)) {
return WeaResult.fail("未匹配到人员", true);
}
Long employeeId = userIdsByJobNum.get(0);
//
List<Long> empIds = new ArrayList<>();
empIds.add(employeeId);
Date beginDate = parseDate(beginDateStr);
Date endDate = parseDate(endDateStr);
Map<BigDecimal, Map<String, Object>> mapMap = employeePanelMapper.statsWorkTimeLength(baseParam, empIds, beginDate, endDate, baseParam.getTenantKey(), false, false);
Map<String, Object> map = mapMap.get(BigDecimal.valueOf(employeeId));
log.error("map===>{}", map);
EmployeeAttendInfoPo employeeAttendInfoPo = new EmployeeAttendInfoPo();
employeeAttendInfoPo.setExpectedAttendance(formatNumber(map.get("period_length_day").toString()));
employeeAttendInfoPo.setActualAttendance(formatNumber(map.get("work_length_day").toString()));
return WeaResult.success(employeeAttendInfoPo);
}
/**
* 日期类型转换
*
* @param dateStr
* @return
*/
private Date parseDate(String dateStr) {
if (dateStr == null) {
return null;
}
// 定义日期格式
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
// 将字符串解析为LocalDate
LocalDate localDate = LocalDate.parse(dateStr, formatter);
// 将LocalDate转换为java.util.Date
return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
}
/**
* 格式化数字
*
* @param numberStr
* @return
*/
public static String formatNumber(String numberStr) {
if (numberStr == null || numberStr.isEmpty()) {
return numberStr;
}
BigDecimal bd = new BigDecimal(numberStr);
// 向上取整最多保留两位小数
bd = bd.setScale(2, RoundingMode.HALF_UP);
String formatted = bd.stripTrailingZeros().toPlainString();
// 如果结果为整数则去掉小数点
if (formatted.contains(".") && formatted.substring(formatted.indexOf('.') + 1).matches("0+")) {
return formatted.substring(0, formatted.indexOf('.'));
}
return formatted;
}
}

View File

@ -1,186 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.weaver.seconddev.feishu.mapper.EmployeePanelMapper">
<sql id="lostAbsenteeismLengthHourSql">
SUM(CASE DAY_TYPE WHEN 'WORK' THEN
CASE WHEN FINAL_SIGN_IN_STATUS='SIGN_IN_ABSENCE' THEN
ABSENCE_LENGTH_MSEC-IFNULL(abs.ABSENTEEISM_LENGTH_MESC,0)-IFNULL(EARLY_OUT_LENGTH_MESC,0) -
IFNULL(SERIOUS_EARLY_LENGTH_MESC, 0)
WHEN SIGN_IN_RECORD IS NOT NULL THEN
CASE FINAL_SIGN_OUT_STATUS WHEN 'SIGN_OUT_ABSENCE' THEN
ABSENCE_LENGTH_MSEC-IFNULL(abs.ABSENTEEISM_LENGTH_MESC,0)-IFNULL(LATE_LENGTH_MESC,0)
-IFNULL(SERIOUS_LATE_LENGTH_MESC,0) ELSE 0 END
ELSE 0 END
ELSE 0 END)*1.00/3600000 AS lost_length_hour
</sql>
<sql id="lostAbsenteeismLengthDaySql">
SUM(CASE DAY_TYPE WHEN 'WORK' THEN
CASE WHEN FINAL_SIGN_IN_STATUS='SIGN_IN_ABSENCE' THEN
ABSENCE_LENGTH_DAY-IFNULL(abs.ABSENTEEISM_LENGTH_DAY,0)-IFNULL(EARLY_OUT_LENGTH_DAY,0)-IFNULL(SERIOUS_EARLY_LENGTH_DAY,0)
WHEN SIGN_IN_RECORD IS NOT NULL THEN
CASE FINAL_SIGN_OUT_STATUS WHEN 'SIGN_OUT_ABSENCE' THEN
ABSENCE_LENGTH_DAY-IFNULL(abs.ABSENTEEISM_LENGTH_DAY,0)-IFNULL(LATE_LENGTH_DAY,0)-IFNULL(SERIOUS_LATE_LENGTH_DAY,0)
ELSE 0 END
ELSE 0 END
ELSE 0 END) AS lost_length_day
</sql>
<sql id="lostLengthHourSql">
SUM(CASE DAY_TYPE WHEN 'WORK' THEN
CASE WHEN FINAL_SIGN_IN_STATUS='SIGN_IN_ABSENCE' THEN
ABSENCE_LENGTH_MSEC-IFNULL(AAD.ABSENTEEISM_LENGTH_MESC,0)-IFNULL(EARLY_OUT_LENGTH_MESC,0) -
IFNULL(SERIOUS_EARLY_LENGTH_MESC, 0)
WHEN SIGN_IN_RECORD IS NOT NULL THEN
CASE FINAL_SIGN_OUT_STATUS WHEN 'SIGN_OUT_ABSENCE' THEN
ABSENCE_LENGTH_MSEC-IFNULL(AAD.ABSENTEEISM_LENGTH_MESC,0)-IFNULL(LATE_LENGTH_MESC,0)
-IFNULL(SERIOUS_LATE_LENGTH_MESC,0) ELSE 0 END
ELSE 0 END
ELSE 0 END)*1.00/3600000 AS lost_length_hour
</sql>
<sql id="lateEarlyCountLengthSql">
sum(case when month_late_length_mesc = 1 then 1 else 0 end) AS month_late_in_count,
sum(case when month_late_length_mesc = 1 then AAD.LATE_LENGTH_MESC else 0 end)*1.00/3600000 AS
month_late_in_hour,
sum(case when month_late_length_mesc = 1 then AAD.LATE_LENGTH_DAY else 0 end) AS month_late_in_day,
sum(case when month_late_length_mesc = 2 then 1 else 0 end) AS month_late_out_count,
sum(case when month_late_length_mesc = 2 then AAD.LATE_LENGTH_MESC else 0 end)*1.00/3600000 AS
month_late_out_hour,
sum(case when month_late_length_mesc = 2 then AAD.LATE_LENGTH_DAY else 0 end) AS month_late_out_day,
sum(case when month_early_length_mesc = 1 then 1 else 0 end) AS month_early_in_count,
sum(case when month_early_length_mesc = 1 then AAD.EARLY_OUT_LENGTH_MESC else 0 end)*1.00/3600000 AS
month_early_in_hour,
sum(case when month_early_length_mesc = 1 then AAD.EARLY_OUT_LENGTH_DAY else 0 end) AS month_early_in_day,
sum(case when month_early_length_mesc = 2 then 1 else 0 end) AS month_early_out_count,
sum(case when month_early_length_mesc = 2 then AAD.EARLY_OUT_LENGTH_MESC else 0 end)*1.00/3600000 AS
month_early_out_hour,
sum(case when month_early_length_mesc = 2 then AAD.EARLY_OUT_LENGTH_DAY else 0 end) AS month_early_out_day
</sql>
<sql id="lostLengthDaySql">
SUM(CASE DAY_TYPE WHEN 'WORK' THEN
CASE WHEN FINAL_SIGN_IN_STATUS='SIGN_IN_ABSENCE' THEN
ABSENCE_LENGTH_DAY-IFNULL(AAD.ABSENTEEISM_LENGTH_DAY,0)-IFNULL(EARLY_OUT_LENGTH_DAY,0)-IFNULL(SERIOUS_EARLY_LENGTH_DAY,0)
WHEN SIGN_IN_RECORD IS NOT NULL THEN
CASE FINAL_SIGN_OUT_STATUS WHEN 'SIGN_OUT_ABSENCE' THEN
ABSENCE_LENGTH_DAY-IFNULL(AAD.ABSENTEEISM_LENGTH_DAY,0)-IFNULL(LATE_LENGTH_DAY,0)-IFNULL(SERIOUS_LATE_LENGTH_DAY,0)
ELSE 0 END
ELSE 0 END
ELSE 0 END) AS lost_length_day
</sql>
<select id="statsWorkTimeLength" resultType="java.util.Map">
SELECT
ASD.employee,
COUNT(CASE WHEN SIGN_IN_RECORD IS NOT NULL THEN 1 END) AS sign_in_num,
COUNT(CASE FINAL_SIGN_IN_STATUS WHEN 'SIGN_IN_LATE' THEN 1 END) AS late_num,
COUNT(CASE WHEN SIGN_OUT_RECORD IS NOT NULL THEN 1 END) AS sign_out_num,
COUNT(CASE FINAL_SIGN_OUT_STATUS WHEN 'SIGN_OUT_EARLY' THEN 1 END) AS early_num,
COUNT(CASE FINAL_SIGN_IN_STATUS WHEN 'SERIOUSLY_LATE' THEN 1 END) AS seriously_late_num,
COUNT(CASE FINAL_SIGN_OUT_STATUS WHEN 'SERIOUSLY_EARLY' THEN 1 END) AS seriously_early_num,
<choose>
<when test="extraAbsenteeism == true">
COUNT(CASE WHEN abs.sign_in_absenteeism_status is not null AND (abs.sign_in_absenteeism_status !=
'SIGN_IN_NORMAL') THEN 1 END) AS absent_num_of_sign_in,
sum(abs.month_absent_countous) AS month_absent_countous,
</when>
<otherwise>
COUNT(CASE FINAL_SIGN_IN_STATUS WHEN 'SIGN_IN_ABSENTEEISM' THEN 1 END) AS absent_num_of_sign_in,
</otherwise>
</choose>
<choose>
<when test="extraAbsenteeism == true">
COUNT(CASE WHEN abs.sign_out_absenteeism_status is not null AND (abs.sign_out_absenteeism_status !=
'SIGN_OUT_NORMAL') AND (SIGN_IN_RECORD IS NOT NULL OR SIGN_OUT_RECORD IS NOT NULL) THEN 1 END) AS
absent_num_of_sign_out,
</when>
<otherwise>
COUNT(CASE WHEN FINAL_SIGN_OUT_STATUS = 'SIGN_OUT_ABSENTEEISM' AND SIGN_IN_RECORD IS NOT NULL THEN 1
END) AS absent_num_of_sign_out,
</otherwise>
</choose>
SUM(CASE DAY_TYPE WHEN 'WORK' THEN PERIOD_LENGTH_MSEC ELSE 0 END)*1.00/3600000 AS period_length_hour,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN PERIOD_LENGTH_DAY ELSE 0 END) AS period_length_day,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN WORK_LENGTH_MSEC ELSE 0 END)*1.00/3600000 AS work_length_hour,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN WORK_LENGTH_DAY ELSE 0 END) AS work_length_day,
SUM(CASE DAY_TYPE WHEN 'HOLIDAY' THEN WORK_LENGTH_MSEC ELSE 0 END)*1.00/3600000 AS holiday_work_length_hour,
SUM(CASE DAY_TYPE WHEN 'HOLIDAY' THEN WORK_LENGTH_DAY ELSE 0 END) AS holiday_work_length_day,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN ACTUAL_WORK_LENGTH_MSEC ELSE 0 END)*1.00/3600000 AS actual_work_length_hour,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN ACTUAL_WORK_LENGTH_DAY ELSE 0 END) AS actual_work_length_day,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN ABSENCE_LENGTH_MSEC ELSE 0 END)*1.00/3600000 AS absence_length_hour,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN ABSENCE_LENGTH_DAY ELSE 0 END) AS absence_length_day,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN LATE_LENGTH_MESC ELSE 0 END)*1.00/3600000 AS late_length_hour,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN LATE_LENGTH_DAY ELSE 0 END) AS late_length_day,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN SERIOUS_LATE_LENGTH_MESC ELSE 0 END)*1.00/3600000 AS
seriously_late_length_hour,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN SERIOUS_LATE_LENGTH_DAY ELSE 0 END) AS seriously_late_length_day,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN EARLY_OUT_LENGTH_MESC ELSE 0 END)*1.00/3600000 AS early_out_length_hour,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN EARLY_OUT_LENGTH_DAY ELSE 0 END) AS early_out_length_day,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN SERIOUS_EARLY_LENGTH_MESC ELSE 0 END)*1.00/3600000 AS
seriously_early_length_hour,
SUM(CASE DAY_TYPE WHEN 'WORK' THEN SERIOUS_EARLY_LENGTH_DAY ELSE 0 END) AS seriously_early_length_day,
<choose>
<when test="extraAbsenteeism == true">
SUM(CASE DAY_TYPE WHEN 'WORK' THEN abs.ABSENTEEISM_LENGTH_MESC ELSE 0 END)*1.00/3600000 AS
absenteeism_length_hour,
</when>
<otherwise>
SUM(CASE DAY_TYPE WHEN 'WORK' THEN AAD.ABSENTEEISM_LENGTH_MESC ELSE 0 END)*1.00/3600000 AS
absenteeism_length_hour,
</otherwise>
</choose>
<choose>
<when test="extraAbsenteeism == true">
SUM(CASE DAY_TYPE WHEN 'WORK' THEN abs.ABSENTEEISM_LENGTH_DAY ELSE 0 END) AS absenteeism_length_day,
</when>
<otherwise>
SUM(CASE DAY_TYPE WHEN 'WORK' THEN AAD.ABSENTEEISM_LENGTH_DAY ELSE 0 END) AS absenteeism_length_day,
</otherwise>
</choose>
<choose>
<when test="extraAbsenteeism == true">
<include refid="lostAbsenteeismLengthHourSql"/>,
<include refid="lostAbsenteeismLengthDaySql"/>,
</when>
<otherwise>
<include refid="lostLengthHourSql"/>,
<include refid="lostLengthDaySql"/>,
</otherwise>
</choose>
<include refid="lateEarlyCountLengthSql"/>,
<if test="hasDetailExtend == true">
SUM(ADE.salary_length_day) as salary_length_day,
SUM(ADE.salary_length_mesc)*1.00/3600000 as salary_length_hour,
SUM(ADE.meal_length_day) as meal_length_day,
SUM(ADE.meal_length_mesc)*1.00/3600000 as meal_length_hour,
SUM(ADE.out_sign_length_day) as out_sign_length_day,
SUM(ADE.out_sign_length_mesc)*1.00/3600000 as out_sign_length_hour,
COUNT(CASE WHEN ADE.osign_in_record is not null THEN 1 END) as osign_in_num,
COUNT(CASE WHEN ADE.osign_out_record is not null THEN 1 END) as osign_out_num,
</if>
COUNT(CASE WHEN FINAL_SIGN_IN_STATUS = 'SIGN_IN_ABSENCE' AND SIGN_OUT_RECORD IS NOT NULL THEN 1 END) AS
un_sign_in_num,
COUNT(CASE WHEN FINAL_SIGN_OUT_STATUS = 'SIGN_OUT_ABSENCE' AND SIGN_IN_RECORD IS NOT NULL THEN 1 END) AS
un_sign_out_num,
COUNT(CASE WHEN FINAL_SIGN_IN_STATUS = 'SIGN_IN_ABSENCE' AND SIGN_OUT_RECORD IS NULL THEN 1 END) AS un_sign_num
FROM ${param.e10_other_business}.ATTEND_STATUS_DETAIL ASD
LEFT JOIN ${param.e10_other_business}.attend_absence_detail AAD ON ASD.ID = AAD.ID and
ASD.delete_type=AAD.delete_type
<if test="extraAbsenteeism == true">
LEFT JOIN ${param.e10_other_business}.attend_absenteeism_detail abs on abs.id = ASD.id and abs.delete_type=0
</if>
<if test="hasDetailExtend == true">
LEFT JOIN ${param.e10_other_business}.attend_status_detail_extend ADE on ADE.id = ASD.id
</if>
WHERE ASD.TENANT_KEY = #{tenantKey} AND ASD.ATTEND_DATE BETWEEN #{beginDate} AND #{endDate} and
ASD.delete_type=0
<if test="empIds != null">
AND ASD.EMPLOYEE IN
<foreach collection="empIds" item="empId" index="index" separator="," open="(" close=")">#{empId}</foreach>
</if>
GROUP BY ASD.EMPLOYEE
</select>
</mapper>