2022-03-31 15:41:55 +08:00
package com.engine.salary.service.impl ;
2022-11-07 15:11:24 +08:00
import com.cloudstore.dev.api.util.Util_DataCache ;
2022-05-31 16:41:11 +08:00
import com.engine.common.util.ServiceUtil ;
2022-03-31 15:41:55 +08:00
import com.engine.core.impl.Service ;
import com.engine.salary.biz.* ;
import com.engine.salary.common.LocalDateRange ;
import com.engine.salary.constant.SalaryDefaultTenantConstant ;
import com.engine.salary.constant.SalaryItemConstant ;
import com.engine.salary.entity.salaryarchive.bo.SalaryArchiveBO ;
import com.engine.salary.entity.salaryarchive.dto.SalaryArchiveDataDTO ;
import com.engine.salary.entity.salaryarchive.dto.SalaryArchiveListDTO ;
import com.engine.salary.entity.salaryarchive.param.* ;
import com.engine.salary.entity.salaryarchive.po.SalaryArchiveDimissionPO ;
import com.engine.salary.entity.salaryarchive.po.SalaryArchiveItemPO ;
import com.engine.salary.entity.salaryarchive.po.SalaryArchivePO ;
import com.engine.salary.entity.salaryarchive.po.SalaryArchiveTaxAgentPO ;
import com.engine.salary.entity.salaryitem.po.SalaryItemPO ;
2022-06-01 15:18:10 +08:00
import com.engine.salary.entity.taxagent.dto.TaxAgentEmployeeDTO ;
2022-07-06 10:13:06 +08:00
import com.engine.salary.entity.taxagent.dto.TaxAgentManageRangeEmployeeDTO ;
2022-10-10 09:47:09 +08:00
import com.engine.salary.entity.taxagent.po.TaxAgentEmpChangePO ;
2022-05-31 16:41:11 +08:00
import com.engine.salary.entity.taxagent.po.TaxAgentPO ;
2022-04-01 14:13:04 +08:00
import com.engine.salary.enums.UserStatusEnum ;
2022-10-09 10:55:35 +08:00
import com.engine.salary.enums.salaryarchive.* ;
2022-10-10 09:47:09 +08:00
import com.engine.salary.enums.taxagent.TaxAgentEmpChangeModuleEnum ;
2022-03-31 15:41:55 +08:00
import com.engine.salary.exception.SalaryRunTimeException ;
2022-07-18 18:08:59 +08:00
import com.engine.salary.mapper.archive.SalaryArchiveItemMapper ;
2022-05-31 21:48:00 +08:00
import com.engine.salary.mapper.archive.SalaryArchiveMapper ;
2022-10-10 09:47:09 +08:00
import com.engine.salary.service.* ;
2023-06-16 14:40:36 +08:00
import com.engine.salary.sys.constant.SalarySysConstant ;
import com.engine.salary.sys.entity.po.SalarySysConfPO ;
2022-09-19 18:21:34 +08:00
import com.engine.salary.sys.entity.vo.OrderRuleVO ;
2022-11-07 15:11:24 +08:00
import com.engine.salary.sys.enums.OpenEnum ;
2023-06-16 14:40:36 +08:00
import com.engine.salary.sys.enums.SalaryAcctEmployeeRuleEnum ;
2022-09-19 13:41:09 +08:00
import com.engine.salary.sys.service.SalarySysConfService ;
import com.engine.salary.sys.service.impl.SalarySysConfServiceImpl ;
2022-03-31 15:41:55 +08:00
import com.engine.salary.util.SalaryDateUtil ;
2022-05-31 21:48:00 +08:00
import com.engine.salary.util.SalaryEntityUtil ;
2022-03-31 15:41:55 +08:00
import com.engine.salary.util.SalaryI18nUtil ;
2022-05-31 21:48:00 +08:00
import com.engine.salary.util.db.MapperProxyFactory ;
2022-03-31 15:41:55 +08:00
import com.engine.salary.util.excel.ExcelParseHelper ;
import com.engine.salary.util.excel.ExcelSupport ;
2023-03-16 13:51:41 +08:00
import com.engine.salary.util.excel.ExcelUtilPlus ;
2022-03-31 15:41:55 +08:00
import com.engine.salary.util.page.PageInfo ;
2022-05-31 21:48:00 +08:00
import com.engine.salary.util.page.SalaryPageUtil ;
2022-09-07 09:45:37 +08:00
import com.engine.salary.util.valid.ValidUtil ;
2022-03-31 15:41:55 +08:00
import com.google.common.collect.Lists ;
import com.google.common.collect.Maps ;
2022-04-20 11:17:25 +08:00
import dm.jdbc.util.IdGenerator ;
2022-07-14 10:36:51 +08:00
import lombok.extern.slf4j.Slf4j ;
2022-03-31 15:41:55 +08:00
import org.apache.commons.collections4.CollectionUtils ;
2022-05-25 11:09:48 +08:00
import org.apache.commons.lang.time.DateUtils ;
2022-03-31 15:41:55 +08:00
import org.apache.commons.lang3.StringUtils ;
2022-07-14 10:36:51 +08:00
import org.apache.commons.lang3.math.NumberUtils ;
2022-03-31 15:41:55 +08:00
import org.apache.poi.ss.usermodel.Sheet ;
import org.apache.poi.util.IOUtils ;
import org.apache.poi.xssf.usermodel.XSSFWorkbook ;
2022-10-14 16:18:55 +08:00
import org.springframework.beans.BeanUtils ;
2022-10-10 09:47:09 +08:00
import org.springframework.transaction.annotation.Transactional ;
2023-08-18 17:56:34 +08:00
import weaver.conn.RecordSet ;
2022-04-01 10:26:28 +08:00
import weaver.file.ImageFileManager ;
2022-07-19 18:40:41 +08:00
import weaver.general.Util ;
2022-05-31 16:41:11 +08:00
import weaver.hrm.User ;
2022-03-31 15:41:55 +08:00
import java.io.InputStream ;
import java.util.* ;
2022-11-07 17:05:50 +08:00
import java.util.concurrent.atomic.AtomicInteger ;
2022-10-14 16:18:55 +08:00
import java.util.regex.Pattern ;
2022-03-31 15:41:55 +08:00
import java.util.stream.Collectors ;
import static com.engine.salary.util.excel.ExcelSupport.EXCEL_TYPE_XLSX ;
/ * *
* 薪资档案
* < p > Copyright : Copyright ( c ) 2022 < / p >
* < p > Company : 泛微软件 < / p >
*
* @author qiantao
* @version 1 . 0
* * /
2022-07-14 10:36:51 +08:00
@Slf4j
2022-03-31 15:41:55 +08:00
public class SalaryArchiveServiceImpl extends Service implements SalaryArchiveService {
2022-05-31 21:48:00 +08:00
private SalaryArchiveBiz salaryArchiveMapper = new SalaryArchiveBiz ( ) ;
2022-03-31 15:41:55 +08:00
private SalaryArchiveItemBiz salaryArchiveItemMapper = new SalaryArchiveItemBiz ( ) ;
private SalaryArchiveTaxAgentBiz salaryArchiveTaxAgentMapper = new SalaryArchiveTaxAgentBiz ( ) ;
private SalaryArchiveDimissionBiz salaryArchiveDimissionMapper = new SalaryArchiveDimissionBiz ( ) ;
private SalaryItemBiz salaryItemMapper = new SalaryItemBiz ( ) ;
2022-05-31 21:05:59 +08:00
private TaxAgentService getTaxAgentService ( User user ) {
return ServiceUtil . getService ( TaxAgentServiceImpl . class , user ) ;
2022-05-31 16:41:11 +08:00
}
2022-03-31 15:41:55 +08:00
2022-05-31 21:48:00 +08:00
private SalaryArchiveMapper getSalaryArchiveMapper ( ) {
return MapperProxyFactory . getProxy ( SalaryArchiveMapper . class ) ;
}
2022-07-18 18:08:59 +08:00
private SalaryArchiveItemMapper getSalaryArchiveItemMapper ( ) {
return MapperProxyFactory . getProxy ( SalaryArchiveItemMapper . class ) ;
}
2022-09-15 17:54:59 +08:00
private SalaryAcctEmployeeService getSalaryAcctEmployeeService ( User user ) {
2022-10-10 09:47:09 +08:00
return ServiceUtil . getService ( SalaryAcctEmployeeServiceImpl . class , user ) ;
2022-09-19 13:41:09 +08:00
}
private SalarySysConfService getSalarySysConfService ( User user ) {
2022-10-10 09:47:09 +08:00
return ServiceUtil . getService ( SalarySysConfServiceImpl . class , user ) ;
2022-09-15 17:54:59 +08:00
}
2022-09-21 11:52:06 +08:00
private SalaryEmployeeService getSalaryEmployeeService ( User user ) {
2022-10-10 09:47:09 +08:00
return ServiceUtil . getService ( SalaryEmployeeServiceImpl . class , user ) ;
2022-09-21 11:52:06 +08:00
}
2022-10-10 09:47:09 +08:00
private TaxAgentEmpChangeService getTaxAgentEmpChangeService ( User user ) {
return ServiceUtil . getService ( TaxAgentEmpChangeServiceImpl . class , user ) ;
}
private SalaryArchiveItemService getSalaryArchiveItemService ( User user ) {
return ServiceUtil . getService ( SalaryArchiveItemServiceImpl . class , user ) ;
}
2023-02-21 18:05:58 +08:00
public SalarySobService getSalarySobService ( User user ) {
return ServiceUtil . getService ( SalarySobServiceImpl . class , user ) ;
}
2022-03-31 15:41:55 +08:00
@Override
public SalaryArchivePO getById ( Long salaryArchiveId ) {
2022-05-31 21:48:00 +08:00
return salaryArchiveMapper . getById ( salaryArchiveId ) ;
2022-03-31 15:41:55 +08:00
}
2022-07-28 15:42:25 +08:00
@Override
public List < SalaryArchivePO > listSome ( SalaryArchivePO po ) {
2022-11-03 19:32:51 +08:00
Collection < Long > ids = po . getIds ( ) ;
2022-11-07 15:11:24 +08:00
if ( CollectionUtils . isNotEmpty ( ids ) ) {
2022-11-03 19:32:51 +08:00
List < SalaryArchivePO > list = new ArrayList < > ( ) ;
List < List < Long > > partition = Lists . partition ( ( List < Long > ) ids , 1000 ) ;
2022-11-07 15:11:24 +08:00
partition . forEach ( idss - > {
2022-11-03 19:32:51 +08:00
po . setIds ( idss ) ;
list . addAll ( getSalaryArchiveMapper ( ) . listSome ( po ) ) ;
} ) ;
return list ;
}
Collection < Long > employeeIds = po . getEmployeeIds ( ) ;
2022-11-07 15:11:24 +08:00
if ( CollectionUtils . isNotEmpty ( employeeIds ) ) {
2022-11-03 19:32:51 +08:00
List < SalaryArchivePO > list = new ArrayList < > ( ) ;
List < List < Long > > partition = Lists . partition ( ( List < Long > ) employeeIds , 1000 ) ;
2022-11-07 15:11:24 +08:00
partition . forEach ( emps - > {
2022-11-03 19:32:51 +08:00
po . setEmployeeIds ( emps ) ;
list . addAll ( getSalaryArchiveMapper ( ) . listSome ( po ) ) ;
} ) ;
return list ;
}
2022-07-28 15:42:25 +08:00
// 获取薪资档案数据
return getSalaryArchiveMapper ( ) . listSome ( po ) ;
}
2023-03-13 16:04:19 +08:00
@Override
public List < SalaryArchiveListDTO > getSalaryArchiveList ( SalaryArchiveQueryParam queryParam ) {
if ( queryParam . isExtSalaryArchiveList ( ) ) {
return getSalaryArchiveMapper ( ) . listExtSalaryArchive ( queryParam ) ;
}
return getSalaryArchiveMapper ( ) . list ( queryParam ) ;
}
2022-03-31 15:41:55 +08:00
@Override
public PageInfo < SalaryArchiveListDTO > listPage ( SalaryArchiveQueryParam queryParam ) {
2022-05-31 21:48:00 +08:00
long currentEmployeeId = user . getUID ( ) ;
2022-11-07 15:11:24 +08:00
/ * *
* 异步处理档案数据
* /
String handleable = Util . null2String ( Util_DataCache . getObjVal ( " salaryArchiveHandleable " ) ) ;
2023-03-13 16:04:19 +08:00
if ( ( StringUtils . isBlank ( handleable ) | | OpenEnum . OPEN . getValue ( ) . equals ( handleable ) ) & & ! queryParam . isExtSalaryArchiveList ( ) ) {
2022-11-07 15:11:24 +08:00
new Thread ( ) {
public void run ( ) {
Util_DataCache . setObjVal ( " salaryArchiveHandleable " , " 0 " ) ;
// 1.历史数据处理
handleHistory ( currentEmployeeId ) ;
// 2.待停薪自动处理
handleSuspendData ( currentEmployeeId ) ;
// 3.增量数据处理
2022-12-07 20:15:52 +08:00
// handleChangeData(currentEmployeeId);
2022-11-07 15:11:24 +08:00
Util_DataCache . setObjVal ( " salaryArchiveHandleable " , " 1 " ) ;
}
} . start ( ) ;
}
2022-10-10 09:47:09 +08:00
2022-07-14 14:32:59 +08:00
2022-05-31 21:48:00 +08:00
Boolean needAuth = getTaxAgentService ( user ) . isNeedAuth ( currentEmployeeId ) ;
2022-07-26 18:01:39 +08:00
2022-09-19 13:41:09 +08:00
//排序配置
2022-09-19 18:21:34 +08:00
OrderRuleVO orderRule = getSalarySysConfService ( user ) . orderRule ( ) ;
queryParam . setOrderRule ( orderRule ) ;
2023-03-13 16:04:19 +08:00
List < SalaryArchiveListDTO > list = getSalaryArchiveList ( queryParam ) ;
2023-02-21 18:05:58 +08:00
list = list . stream ( )
//过滤档案状态
. filter ( dto - > {
if ( StringUtils . isNotBlank ( queryParam . getArchiveStatus ( ) ) ) {
return StringUtils . equals ( queryParam . getArchiveStatus ( ) , dto . getArchiveStatus ( ) ) ;
}
return true ;
} )
. collect ( Collectors . toList ( ) ) ;
2022-09-19 13:41:09 +08:00
2022-06-01 17:45:49 +08:00
if ( needAuth ) {
2022-06-01 19:14:05 +08:00
Boolean adminEnable = getTaxAgentService ( user ) . isAdminEnable ( currentEmployeeId ) ;
//不是管理员看不到数据,返回空
2022-06-01 20:46:51 +08:00
if ( ! adminEnable ) {
2022-06-01 19:14:05 +08:00
PageInfo < SalaryArchiveListDTO > pageInfo = SalaryPageUtil . buildPage ( queryParam . getCurrent ( ) , queryParam . getPageSize ( ) , SalaryArchiveListDTO . class ) ;
return pageInfo ;
}
2022-08-31 15:06:49 +08:00
// 获取作为管理员的所有个税扣缴义务人列表
2022-07-21 17:28:47 +08:00
Collection < TaxAgentPO > taxAgentPOS = getTaxAgentService ( user ) . listAllTaxAgentsAsAdmin ( currentEmployeeId ) ;
Set < Long > taxAgentIds = SalaryEntityUtil . properties ( taxAgentPOS , TaxAgentPO : : getId ) ;
2023-02-21 18:05:58 +08:00
list = list . stream ( ) . filter ( dto - > taxAgentIds . contains ( dto . getTaxAgentId ( ) ) ) . collect ( Collectors . toList ( ) ) ;
2022-05-31 21:48:00 +08:00
}
2023-02-21 18:05:58 +08:00
PageInfo < SalaryArchiveListDTO > pageInfo = SalaryPageUtil . buildPage ( queryParam . getCurrent ( ) , queryParam . getPageSize ( ) , SalaryArchiveListDTO . class ) ;
pageInfo . setTotal ( list . size ( ) ) ;
pageInfo . setList ( SalaryPageUtil . subList ( queryParam . getCurrent ( ) , queryParam . getPageSize ( ) , list ) ) ;
return pageInfo ;
2022-03-31 15:41:55 +08:00
}
2022-10-10 09:47:09 +08:00
/ * *
* 1 、 员工的人事状态属性从在职变成非在职 , 且在 【 发薪员工 】 里 , 则自动进入 【 待停薪 】 ;
* 2 、 若维护了最后发薪日大于当前日期 , 会自动清除该员工的待办数据 ;
* 3 、 个税扣缴义务人发生调整的发薪员工自动进入 【 待停薪 】 ;
* < p >
* 1 . 【 发薪员工 】 中 , 员工的人事状态属性从在职变成非在职 , 则自动进入 【 待停薪 】 ;
* 2 . 【 定薪员工 】 中 , 如果维护了最后发薪日且大于今天的 , 自动清除待停薪 , 如果小于等于今天的则自动进入待停薪
*
* @param currentEmployeeId
* /
@Transactional ( rollbackFor = Exception . class )
public void handleSuspendData ( Long currentEmployeeId ) {
List < String > personnelStatuss = new ArrayList < String > ( ) { {
2022-10-13 14:57:52 +08:00
add ( " 4 " ) ;
2022-10-10 09:47:09 +08:00
add ( " 5 " ) ;
add ( " 6 " ) ;
} } ;
// 1.定薪员工非在职
if ( CollectionUtils . isNotEmpty ( personnelStatuss ) ) {
2023-03-13 16:04:19 +08:00
SalaryArchiveQueryParam queryParam = SalaryArchiveQueryParam . builder ( )
2022-10-10 09:47:09 +08:00
// 离职
. personnelStatuss ( personnelStatuss )
// 定薪列表
. runStatusList ( Collections . singletonList ( SalaryArchiveStatusEnum . FIXED . getValue ( ) ) )
2023-03-13 16:04:19 +08:00
. build ( ) ;
List < SalaryArchiveListDTO > noNormalList = getSalaryArchiveList ( queryParam ) ;
2022-10-10 09:47:09 +08:00
if ( CollectionUtils . isNotEmpty ( noNormalList ) ) {
List < Long > idList = noNormalList . stream ( ) . map ( SalaryArchiveListDTO : : getId ) . collect ( Collectors . toList ( ) ) ;
List < List < Long > > partition = Lists . partition ( idList , 999 ) ;
partition . forEach ( part - >
getSalaryArchiveMapper ( ) . updateRunStatusByIdsAndPayEndDate ( SalaryArchivePO . builder ( ) . ids ( part ) . runStatus ( SalaryArchiveStatusEnum . SUSPEND . getValue ( ) ) . build ( ) )
) ;
}
}
Date today = new Date ( ) ;
// 2.定薪员工维护了最后发薪日,且大于今天的,自动清除待停薪
getSalaryArchiveMapper ( ) . updateFixed ( SalaryArchivePO . builder ( ) . payEndDate ( today ) . build ( ) ) ;
// 3.定薪员工维护了最后发薪日,且小于等于今天的,自动进入待停薪
getSalaryArchiveMapper ( ) . updateSuspend ( SalaryArchivePO . builder ( ) . payEndDate ( today ) . build ( ) ) ;
}
/ * *
* 处理增量数据
*
* @param currentEmployeeId
* /
public void handleChangeData ( Long currentEmployeeId ) {
2023-06-15 10:44:31 +08:00
2022-10-10 09:47:09 +08:00
// 所有增量人员列表
List < TaxAgentEmpChangePO > taxAgentEmpChangeList = getTaxAgentEmpChangeService ( user ) . listAllByModule ( TaxAgentEmpChangeModuleEnum . SALARY_ARCHIVE ) ;
if ( CollectionUtils . isEmpty ( taxAgentEmpChangeList ) ) {
return ;
}
// 当前可以管辖的人员
2022-12-07 20:15:52 +08:00
Collection < TaxAgentPO > taxAgentList = new ArrayList < > ( ) ;
if ( currentEmployeeId ! = 1L ) {
taxAgentList = getTaxAgentService ( user ) . listAllTaxAgents ( currentEmployeeId ) ;
Collection < TaxAgentPO > finalTaxAgentList = taxAgentList ;
taxAgentEmpChangeList = taxAgentEmpChangeList . stream ( ) . filter ( f - > finalTaxAgentList . stream ( ) . anyMatch ( e - > e . getId ( ) . equals ( f . getTaxAgentId ( ) ) ) ) . collect ( Collectors . toList ( ) ) ;
if ( CollectionUtils . isEmpty ( taxAgentEmpChangeList ) ) {
return ;
}
2022-10-10 09:47:09 +08:00
}
// 所有档案数据
List < SalaryArchivePO > salaryArchiveList = getSalaryArchiveMapper ( ) . listAll ( ) ;
// 获取所有可被引用的薪资项目
List < SalaryItemPO > salaryItems = salaryItemMapper . getCanAdjustSalaryItems ( ) ;
Collection < Long > salaryItemIds = salaryItems . stream ( ) . map ( SalaryItemPO : : getId ) . collect ( Collectors . toList ( ) ) ;
// 获取薪资档案所对应的当前生效的薪资项目数据
List < SalaryArchiveItemPO > salaryArchiveItemList = getCurrentEffectiveItemList ( Lists . newArrayList ( ) , salaryItemIds ) ;
/** 增量处理 start ***/
SalaryArchiveBO . ChangeData changeData = SalaryArchiveBO . buildChangeData ( taxAgentEmpChangeList , salaryArchiveList , salaryArchiveItemList , currentEmployeeId ) ;
// 批量修改薪资档案
if ( CollectionUtils . isNotEmpty ( changeData . getSalaryArchiveUpdateTodoList ( ) ) ) {
salaryArchiveMapper . batchUpdate ( changeData . getSalaryArchiveUpdateTodoList ( ) ) ;
}
// 批量新增薪资档案
if ( CollectionUtils . isNotEmpty ( changeData . getSalaryArchiveAddTodoList ( ) ) ) {
salaryArchiveMapper . batchInsert ( changeData . getSalaryArchiveAddTodoList ( ) ) ;
}
// 落库处理薪资项目
if ( CollectionUtils . isNotEmpty ( changeData . getSalaryArchiveItemAddTodos ( ) ) ) {
salaryArchiveItemMapper . batchInsert ( changeData . getSalaryArchiveItemAddTodos ( ) ) ;
}
// 删除增量数据
if ( CollectionUtils . isNotEmpty ( changeData . getChangeIds ( ) ) ) {
getTaxAgentEmpChangeService ( user ) . deleleByIds ( changeData . getChangeIds ( ) ) ;
}
/** 增量处理 end ***/
2023-03-10 17:15:15 +08:00
2022-10-10 09:47:09 +08:00
}
2023-06-29 10:35:55 +08:00
@Override
public void deleteSalaryArchive ( Collection < Long > salaryArchiveIds ) {
if ( CollectionUtils . isEmpty ( salaryArchiveIds ) ) {
throw new SalaryRunTimeException ( " 薪资档案参数为空! " ) ;
}
SalarySysConfPO canDelete = getSalarySysConfService ( user ) . getOneByCode ( SalarySysConstant . SALARY_ARCHIVE_DELETE ) ;
2023-07-11 10:14:28 +08:00
if ( Objects . isNull ( canDelete ) | | StringUtils . equals ( canDelete . getConfValue ( ) , " 0 " ) ) {
throw new SalaryRunTimeException ( " 不允许删除薪资档案,请先开启删除档案规则配置! " ) ;
}
2023-06-29 10:35:55 +08:00
List < SalaryArchivePO > salaryArchiveList = getSalaryArchiveMapper ( ) . listSome ( SalaryArchivePO . builder ( ) . ids ( salaryArchiveIds ) . build ( ) ) ;
//查询当前登录人员管理的个税扣缴义务人
List < Long > canDeleteTaxAgentIds = getTaxAgentService ( user ) . listAllTaxAgentsAsAdmin ( ( long ) user . getUID ( ) )
. stream ( ) . map ( TaxAgentPO : : getId ) . collect ( Collectors . toList ( ) ) ;
boolean err = salaryArchiveList . stream ( ) . anyMatch ( po - > ! canDeleteTaxAgentIds . contains ( po . getTaxAgentId ( ) ) ) ;
if ( CollectionUtils . isEmpty ( salaryArchiveList ) | | err ) {
throw new SalaryRunTimeException ( " 薪资档案不存在,或没有权限删除该薪资档案! " ) ;
}
Optional < SalaryArchivePO > fixedList = salaryArchiveList . stream ( ) . filter ( archive - > ! StringUtils . equals ( archive . getRunStatus ( ) , SalaryArchiveStatusEnum . PENDING . getValue ( ) )
& & ! StringUtils . equals ( archive . getRunStatus ( ) , SalaryArchiveStatusEnum . STOP_FROM_PENDING . getValue ( ) ) ) . findFirst ( ) ;
if ( fixedList . isPresent ( ) ) {
throw new SalaryRunTimeException ( " 发薪员工、待停薪员工、停薪_来自待停薪, 无法删除薪资档案! " ) ;
}
List < Long > deleteIds = salaryArchiveList . stream ( ) . map ( SalaryArchivePO : : getId ) . collect ( Collectors . toList ( ) ) ;
// 删除薪资档案及档案项目
if ( CollectionUtils . isNotEmpty ( deleteIds ) ) {
getSalaryArchiveMapper ( ) . deleteByIds ( deleteIds ) ;
getSalaryArchiveItemMapper ( ) . deleteBySalaryArchiveId ( deleteIds ) ;
}
2022-10-10 09:47:09 +08:00
}
2022-07-26 18:01:39 +08:00
2022-06-01 20:46:51 +08:00
@Override
public List < SalaryArchiveListDTO > list ( SalaryArchiveQueryParam queryParam ) {
long currentEmployeeId = user . getUID ( ) ;
2022-09-19 18:21:34 +08:00
//排序配置
OrderRuleVO orderRule = getSalarySysConfService ( user ) . orderRule ( ) ;
queryParam . setOrderRule ( orderRule ) ;
2022-06-01 20:46:51 +08:00
Boolean needAuth = getTaxAgentService ( user ) . isNeedAuth ( currentEmployeeId ) ;
if ( needAuth ) {
Boolean adminEnable = getTaxAgentService ( user ) . isAdminEnable ( currentEmployeeId ) ;
//不是管理员看不到数据,返回空
if ( ! adminEnable ) {
return new ArrayList < > ( ) ;
}
//获取管理的人员范围
List < TaxAgentEmployeeDTO > taxAgentEmployeeDTOS = getTaxAgentService ( user ) . listTaxAgentAndEmployee ( currentEmployeeId ) ;
Set < Long > employeeId = SalaryEntityUtil . properties ( taxAgentEmployeeDTOS , TaxAgentEmployeeDTO : : getEmployeeId ) ;
2022-07-25 16:29:20 +08:00
Collection < TaxAgentPO > taxAgentPOS = getTaxAgentService ( user ) . listAllTaxAgentsAsAdmin ( currentEmployeeId ) ;
Set < Long > taxAgentIds = SalaryEntityUtil . properties ( taxAgentPOS , TaxAgentPO : : getId ) ;
2022-06-01 20:46:51 +08:00
//获取所有薪资档案
2023-03-13 16:04:19 +08:00
List < SalaryArchiveListDTO > list = getSalaryArchiveList ( queryParam ) ;
2022-07-26 18:01:39 +08:00
List < SalaryArchiveListDTO > finalAllArchive = list . stream ( ) . filter ( dto - > employeeId . contains ( dto . getEmployeeId ( ) ) & & taxAgentIds . contains ( dto . getTaxAgentId ( ) ) ) . collect ( Collectors . toList ( ) ) ;
2022-07-25 16:29:20 +08:00
2022-06-01 20:46:51 +08:00
return finalAllArchive ;
} else {
2023-03-13 16:04:19 +08:00
return getSalaryArchiveList ( queryParam ) ;
2022-06-01 20:46:51 +08:00
}
}
2022-03-31 15:41:55 +08:00
/ * *
* 获取薪资档案对应的当前生效的薪资项目
*
* @param salaryArchivesIds
* @return
* /
@Override
public List < SalaryArchiveItemPO > getCurrentEffectiveItemList ( Collection < Long > salaryArchivesIds , Collection < Long > salaryItemIds ) {
2022-07-18 18:08:59 +08:00
if ( CollectionUtils . isEmpty ( salaryItemIds ) ) {
2022-07-18 09:38:12 +08:00
return Collections . EMPTY_LIST ;
}
2022-03-31 15:41:55 +08:00
List < SalaryArchiveItemPO > salaryArchiveItems = salaryArchiveItemMapper . getCurrentEffectiveItemList ( SalaryArchiveItemQueryParam . builder ( ) . salaryArchivesIds ( salaryArchivesIds ) . salaryItemIds ( salaryItemIds ) . effectiveTime ( new Date ( ) ) . build ( ) ) ;
2022-07-21 10:51:38 +08:00
return salaryArchiveItems . stream ( ) . collect ( Collectors . collectingAndThen ( Collectors . toCollection ( ( ) - > new TreeSet < > ( Comparator . comparing ( f - > f . getSalaryArchiveId ( ) + " - " + f . getSalaryItemId ( ) ) ) ) , ArrayList : : new ) ) ;
2022-03-31 15:41:55 +08:00
}
/ * *
* 获取薪资档案对应的当前生效的个税扣缴义务人
*
* @param salaryArchivesIds
* @return
* /
@Override
public List < SalaryArchiveTaxAgentPO > getCurrentEffectiveTaxAgentList ( Collection < Long > salaryArchivesIds ) {
2022-07-18 18:08:59 +08:00
if ( CollectionUtils . isEmpty ( salaryArchivesIds ) ) {
2022-07-18 09:38:12 +08:00
return Collections . EMPTY_LIST ;
}
2022-03-31 15:41:55 +08:00
List < SalaryArchiveTaxAgentPO > salaryArchiveTaxAgents = salaryArchiveTaxAgentMapper . listByParam ( SalaryArchiveTaxAgentQueryParam . builder ( ) . salaryArchivesIds ( salaryArchivesIds ) . effectiveTime ( new Date ( ) ) . build ( ) ) ;
2022-07-21 10:51:38 +08:00
return salaryArchiveTaxAgents . stream ( ) . collect ( Collectors . collectingAndThen ( Collectors . toCollection ( ( ) - > new TreeSet < > ( Comparator . comparing ( SalaryArchiveTaxAgentPO : : getSalaryArchiveId ) ) ) , ArrayList : : new ) ) ;
2022-03-31 15:41:55 +08:00
}
/ * *
* 构建薪资档案数据
*
* @param salaryArchives
* @param taxAgentLists
* @param salaryItems
* @param isPage
* @return
* /
@Override
2022-07-21 10:51:38 +08:00
public List < Map < String , Object > > buildSalaryArchiveData ( Collection < SalaryArchiveListDTO > salaryArchives , Collection < TaxAgentPO > taxAgentLists , List < SalaryItemPO > salaryItems , Boolean isPage ) {
2022-03-31 15:41:55 +08:00
// 分页用于表格展示,否则用于导出
Collection < Long > ids = isPage ? salaryArchives . stream ( ) . map ( SalaryArchiveListDTO : : getId ) . collect ( Collectors . toList ( ) ) : CollectionUtils . emptyCollection ( ) ;
List < Long > salaryItemIds = salaryItems . stream ( ) . map ( SalaryItemPO : : getId ) . collect ( Collectors . toList ( ) ) ;
// 1.获取薪资档案所对应的当前生效的薪资项目数据
2023-05-29 16:17:13 +08:00
List < SalaryArchiveItemPO > salaryArchiveItemList = Collections . emptyList ( ) ;
2023-06-27 18:00:39 +08:00
if ( CollectionUtils . isNotEmpty ( ids ) & & CollectionUtils . isNotEmpty ( salaryItemIds ) | | ! isPage ) {
2023-05-29 16:17:13 +08:00
salaryArchiveItemList = getCurrentEffectiveItemList ( ids , salaryItemIds ) ;
}
List < SalaryArchiveItemPO > finalSalaryArchiveItemList = salaryArchiveItemList ;
2022-03-31 15:41:55 +08:00
List < Map < String , Object > > salaryArchiveItemData = salaryArchives . stream ( ) . map ( m - > {
Map < String , Object > map = Maps . newHashMap ( ) ;
map . put ( " salaryArchiveId " , m . getId ( ) ) ;
2022-07-26 18:01:39 +08:00
map . put ( " archiveStatus " , m . getArchiveStatus ( ) ) ;
2023-05-29 16:17:13 +08:00
List < SalaryArchiveItemPO > salaryArchiveItemValuelList = finalSalaryArchiveItemList . stream ( ) . filter ( i - > i . getSalaryArchiveId ( ) . equals ( m . getId ( ) ) ) . collect ( Collectors . toList ( ) ) ;
2022-03-31 15:41:55 +08:00
salaryArchiveItemValuelList . forEach ( i - > {
map . put ( i . getSalaryItemId ( ) + SalaryItemConstant . DYNAMIC_SUFFIX , i . getItemValue ( ) ) ;
} ) ;
return map ;
} ) . collect ( Collectors . toList ( ) ) ;
//2.获取薪资档案所对应的当前生效的个税扣缴义务人列表
2022-07-14 14:32:59 +08:00
// List<SalaryArchiveTaxAgentPO> taxAgentList = getCurrentEffectiveTaxAgentList(ids);
// List<Map<String, Object>> taxAgentData = taxAgentList.stream().map(m -> {
// Map<String, Object> map = Maps.newHashMap();
// map.put("salaryArchiveId", m.getSalaryArchiveId());
// map.put("taxAgentId", m.getTaxAgentId());
// Optional<TaxAgentPO> optional = taxAgentLists.stream().filter(f -> f.getId().equals(m.getTaxAgentId())).findFirst();
// map.put("taxAgentName", optional.isPresent() ? optional.get().getName() : "");
// map.put("taxAgentEffectiveTime", m.getEffectiveTime());
// return map;
// }).collect(Collectors.toList());
Map < Long , TaxAgentPO > longTaxAgentPOMap = SalaryEntityUtil . convert2Map ( taxAgentLists , TaxAgentPO : : getId ) ;
2022-03-31 15:41:55 +08:00
// 3.组装数据
List < Map < String , Object > > listMaps = new ArrayList < > ( ) ;
salaryArchives . forEach ( e - > {
2022-04-01 14:13:04 +08:00
e . setEmployeeStatus ( UserStatusEnum . getDefaultLabelByValue ( Integer . parseInt ( e . getEmployeeStatus ( ) ) ) ) ;
2022-03-31 15:41:55 +08:00
Map < String , Object > map = new LinkedHashMap < > ( ) ;
map . put ( " id " , e . getId ( ) ) ;
map . put ( " username " , e . getUsername ( ) ) ;
map . put ( " employeeId " , e . getEmployeeId ( ) ) ;
2022-07-14 14:32:59 +08:00
// Optional<Map<String, Object>> optionalTaxAgent = taxAgentData.stream().filter(f -> f.get("salaryArchiveId").toString().equals(e.getId().toString())).findFirst();
TaxAgentPO taxAgentPO = longTaxAgentPOMap . get ( e . getTaxAgentId ( ) ) ;
2022-07-18 09:38:12 +08:00
map . put ( " taxAgentName " , Optional . ofNullable ( taxAgentPO ) . map ( TaxAgentPO : : getName ) . orElse ( " " ) ) ;
map . put ( " taxAgentId " , Optional . ofNullable ( taxAgentPO ) . map ( TaxAgentPO : : getId ) . orElse ( 0L ) ) ;
2022-07-14 14:32:59 +08:00
// map.put("taxAgentEffectiveTime", optionalTaxAgent.isPresent() ? optionalTaxAgent.get().get("taxAgentEffectiveTime") : "");
2022-03-31 15:41:55 +08:00
2022-08-09 10:09:55 +08:00
map . put ( " subcompanyName " , e . getSubcompanyName ( ) ) ;
2022-03-31 15:41:55 +08:00
map . put ( " departmentName " , e . getDepartmentName ( ) ) ;
map . put ( " mobile " , e . getMobile ( ) ) ;
2022-09-15 17:54:59 +08:00
map . put ( " workcode " , e . getWorkcode ( ) ) ;
2022-03-31 15:41:55 +08:00
map . put ( " employeeStatus " , e . getEmployeeStatus ( ) ) ;
2022-07-18 18:08:59 +08:00
map . put ( " payStartDate " , SalaryDateUtil . getFormatLocalDate ( e . getPayStartDate ( ) ) ) ;
map . put ( " payEndDate " , SalaryDateUtil . getFormatLocalDate ( e . getPayEndDate ( ) ) ) ;
2022-12-01 14:33:21 +08:00
map . put ( " companystartdate " , e . getCompanystartdate ( ) ) ;
map . put ( " dismissdate " , e . getDismissdate ( ) ) ;
2022-03-31 15:41:55 +08:00
// 薪资项目动态
Optional < Map < String , Object > > optionalItem = salaryArchiveItemData . stream ( ) . filter ( f - > f . get ( " salaryArchiveId " ) . toString ( ) . equals ( e . getId ( ) . toString ( ) ) ) . findFirst ( ) ;
optionalItem . ifPresent ( map : : putAll ) ;
listMaps . add ( map ) ;
} ) ;
return listMaps ;
}
@Override
2022-04-19 15:13:08 +08:00
public XSSFWorkbook exportList ( SalaryArchiveQueryParam queryParam ) {
2022-06-01 19:14:05 +08:00
long employeeId = user . getUID ( ) ;
2022-03-31 15:41:55 +08:00
// 1.工作簿名称
String sheetName = SalaryI18nUtil . getI18nLabel ( 85368 , " 薪资档案 " ) ;
// 获取所有可被引用的薪资项目
List < SalaryItemPO > salaryItems = salaryItemMapper . getCanAdjustSalaryItems ( ) ;
2023-06-14 10:33:26 +08:00
String [ ] header = { SalaryI18nUtil . getI18nLabel ( 85429 , " 姓名 " ) ,
SalaryI18nUtil . getI18nLabel ( 86184 , " 个税扣缴义务人 " ) ,
SalaryI18nUtil . getI18nLabel ( 86185 , " 部门 " ) ,
SalaryI18nUtil . getI18nLabel ( 86176 , " 工号 " ) ,
SalaryI18nUtil . getI18nLabel ( 86186 , " 手机号 " ) ,
2023-08-18 17:56:34 +08:00
SalaryI18nUtil . getI18nLabel ( 0 , " 人员分类 " ) ,
2023-06-14 10:33:26 +08:00
SalaryI18nUtil . getI18nLabel ( 15890 , " 员工状态 " ) ,
SalaryI18nUtil . getI18nLabel ( 91075 , " 起始发薪日期 " ) ,
SalaryI18nUtil . getI18nLabel ( 91075 , " 最后发薪日期 " ) } ;
2022-03-31 15:41:55 +08:00
// 2.表头
List < Object > headerList = new ArrayList < > ( Arrays . asList ( header ) ) ;
for ( SalaryItemPO salaryItem : salaryItems ) {
headerList . add ( salaryItem . getName ( ) ) ;
}
// 获取所有个税扣缴义务人
2022-05-31 16:41:11 +08:00
Collection < TaxAgentPO > taxAgentList = getTaxAgentService ( user ) . listAll ( ) ;
2022-09-28 09:26:26 +08:00
//获取管理的人员范围
List < TaxAgentManageRangeEmployeeDTO > taxAgentEmployeeDTOS = getTaxAgentService ( user ) . listTaxAgentAndEmployeeTree ( employeeId ) ;
Map < Long , List < TaxAgentManageRangeEmployeeDTO . TaxAgentEmployee > > taxAgentEmployeesMap = SalaryEntityUtil . convert2Map ( taxAgentEmployeeDTOS , TaxAgentManageRangeEmployeeDTO : : getTaxAgentId , TaxAgentManageRangeEmployeeDTO : : getEmployeeList ) ;
2022-09-19 18:21:34 +08:00
//排序配置
OrderRuleVO orderRule = getSalarySysConfService ( user ) . orderRule ( ) ;
queryParam . setOrderRule ( orderRule ) ;
2023-03-13 16:04:19 +08:00
Collection < SalaryArchiveListDTO > salaryArchives = getSalaryArchiveList ( queryParam ) ;
2022-06-01 19:14:05 +08:00
2022-06-01 20:46:51 +08:00
//分权
Boolean needAuth = getTaxAgentService ( user ) . isNeedAuth ( employeeId ) ;
if ( needAuth ) {
Boolean adminEnable = getTaxAgentService ( user ) . isAdminEnable ( employeeId ) ;
if ( ! adminEnable ) {
salaryArchives = new ArrayList < > ( ) ;
} else {
2022-07-28 17:20:24 +08:00
2022-08-09 16:45:22 +08:00
Collection < TaxAgentPO > taxAgentPOS = getTaxAgentService ( user ) . listAllTaxAgentsAsAdmin ( ( long ) user . getUID ( ) ) ;
2022-07-28 17:20:24 +08:00
Set < Long > taxAgentIds = SalaryEntityUtil . properties ( taxAgentPOS , TaxAgentPO : : getId ) ;
//获取管理扣缴单位薪资档案
salaryArchives = salaryArchives . stream ( ) . filter ( dto - > taxAgentIds . contains ( dto . getTaxAgentId ( ) ) ) . collect ( Collectors . toList ( ) ) ;
//过滤档案状态
if ( StringUtils . isNotBlank ( queryParam . getArchiveStatus ( ) ) ) {
2022-09-28 09:26:26 +08:00
//过滤档案状态
2022-07-28 17:20:24 +08:00
salaryArchives = salaryArchives . stream ( ) . filter ( dto - > StringUtils . equals ( queryParam . getArchiveStatus ( ) , dto . getArchiveStatus ( ) ) ) . collect ( Collectors . toList ( ) ) ;
}
2022-06-01 20:46:51 +08:00
}
}
2022-06-01 19:14:05 +08:00
2022-03-31 15:41:55 +08:00
List < Map < String , Object > > listMaps = buildSalaryArchiveData ( salaryArchives , taxAgentList , salaryItems , Boolean . FALSE ) ;
2023-08-18 17:56:34 +08:00
// 获取人员分类信息
Map < String , String > ryflInfo = new HashMap < > ( ) ;
getAzRyflInfo ( salaryArchives . stream ( ) . map ( SalaryArchiveListDTO : : getEmployeeId ) . collect ( Collectors . toList ( ) ) )
. forEach ( ( k , v ) - > {
ryflInfo . put ( k . toString ( ) , v ) ;
} ) ;
2022-03-31 15:41:55 +08:00
// 组装数据
List < List < Object > > rows = new ArrayList < > ( ) ;
rows . add ( headerList ) ;
listMaps . forEach ( e - > {
List < Object > row = new ArrayList < > ( ) ;
2022-07-21 17:28:47 +08:00
row . add ( Util . null2String ( e . get ( " username " ) ) ) ;
row . add ( Util . null2String ( e . get ( " taxAgentName " ) ) ) ;
row . add ( Util . null2String ( e . get ( " departmentName " ) ) ) ;
2023-03-01 16:19:09 +08:00
row . add ( Util . null2String ( e . get ( " workcode " ) ) ) ;
2022-07-21 17:28:47 +08:00
row . add ( Util . null2String ( e . get ( " mobile " ) ) ) ;
2023-08-18 17:56:34 +08:00
row . add ( ryflInfo . getOrDefault ( Util . null2String ( e . get ( " employeeId " ) ) , " " ) ) ;
2022-07-21 17:28:47 +08:00
row . add ( Util . null2String ( e . get ( " employeeStatus " ) ) ) ;
row . add ( Util . null2String ( e . get ( " payStartDate " ) ) ) ;
row . add ( Util . null2String ( e . get ( " payEndDate " ) ) ) ;
2022-03-31 15:41:55 +08:00
// 薪资项目数据
for ( SalaryItemPO salaryItem : salaryItems ) {
row . add ( e . containsKey ( salaryItem . getId ( ) + SalaryItemConstant . DYNAMIC_SUFFIX ) ? ( e . get ( salaryItem . getId ( ) + SalaryItemConstant . DYNAMIC_SUFFIX ) = = null ? " " : e . get ( salaryItem . getId ( ) + SalaryItemConstant . DYNAMIC_SUFFIX ) . toString ( ) ) : " " ) ;
}
rows . add ( row ) ;
} ) ;
// 3.表数据
2023-03-16 13:51:41 +08:00
// return ExcelUtil.genWorkbookV2(rows, sheetName);
return ExcelUtilPlus . genWorkbookV2 ( rows , sheetName ) ;
2022-03-31 15:41:55 +08:00
}
2022-10-14 16:18:55 +08:00
@Override
public String savePaySet ( SalaryArchiveSetPaySaveParam saveParam ) {
long currentEmployeeId = user . getUID ( ) ;
if ( saveParam . getStatus ( ) = = null ) {
throw new SalaryRunTimeException ( SalaryI18nUtil . getI18nLabel ( 109201 , " 状态不能为空 " ) ) ;
}
Boolean enableStatus = saveParam . getStatus ( ) . equals ( SalaryArchiveStatusEnum . PENDING )
| | saveParam . getStatus ( ) . equals ( SalaryArchiveStatusEnum . FIXED )
| | saveParam . getStatus ( ) . equals ( SalaryArchiveStatusEnum . SUSPEND ) ;
if ( ! enableStatus ) {
return StringUtils . EMPTY ;
}
if ( saveParam . getSalaryArchiveId ( ) = = null ) {
throw new SalaryRunTimeException ( SalaryI18nUtil . getI18nLabel ( 100425 , " 薪资档案id不能为空 " ) ) ;
}
SalaryArchivePO salaryArchive = getById ( saveParam . getSalaryArchiveId ( ) ) ;
if ( salaryArchive = = null ) {
throw new SalaryRunTimeException ( String . format ( SalaryI18nUtil . getI18nLabel ( 100463 , " 薪资档案不存在 " ) + " [id:%s] " , saveParam . getSalaryArchiveId ( ) ) ) ;
}
SalaryArchivePO oldSalaryArchive = new SalaryArchivePO ( ) ;
BeanUtils . copyProperties ( salaryArchive , oldSalaryArchive ) ;
List < SalaryArchivePO > oldList = Collections . singletonList ( oldSalaryArchive ) ;
// 收入所得项目
2023-08-17 14:55:32 +08:00
// boolean checkIncomeCategory = saveParam.getIncomeCategory() == null || StringUtils.isEmpty(SalaryArchiveBO.getIncomeCategoryByValue(saveParam.getIncomeCategory()));
2022-10-14 16:18:55 +08:00
// if (checkIncomeCategory) {
// throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(122085, "收入所得项目不能为空或不存在"));
// } else {
// salaryArchive.setIncomeCategory(saveParam.getIncomeCategory());
// }
// 薪资账套
// if (CollectionUtils.isEmpty(saveParam.getSalarySobIds())) {
// throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(122217, "薪资账套不能为空"));
// }
// 待定薪
if ( saveParam . getStatus ( ) . equals ( SalaryArchiveStatusEnum . PENDING ) ) {
if ( saveParam . getPayStartDate ( ) = = null ) {
throw new SalaryRunTimeException ( SalaryI18nUtil . getI18nLabel ( 109202 , " 起始发薪日期不能为空 " ) ) ;
}
// 起薪日期:新人入职默认为:入职日期;返聘人员默认为:返聘开始日期;调整个税扣缴义务人:不默认日期
salaryArchive . setPayStartDate ( saveParam . getPayStartDate ( ) ) ;
if ( saveParam . getPayEndDate ( ) ! = null ) {
if ( saveParam . getPayStartDate ( ) . after ( saveParam . getPayEndDate ( ) ) ) {
throw new SalaryRunTimeException ( SalaryI18nUtil . getI18nLabel ( 109214 , " 起始发薪日期不可晚于最后发薪日 " ) ) ;
}
}
salaryArchive . setPayEndDate ( saveParam . getPayEndDate ( ) ) ;
// 处理薪资项目
if ( CollectionUtils . isNotEmpty ( saveParam . getSalaryArchiveItems ( ) ) ) {
// 获取所有可被引用的薪资项目
List < SalaryItemPO > salaryItems = getSalaryArchiveItemService ( user ) . getCanAdjustSalaryItems ( ) ;
Collection < Long > salaryItemIds = salaryItems . stream ( ) . map ( SalaryItemPO : : getId ) . collect ( Collectors . toList ( ) ) ;
// 待处理薪资项目
List < SalaryArchiveItemDetailSaveParam > salaryArchiveItems = saveParam . getSalaryArchiveItems ( ) . stream ( ) . filter ( e - > salaryItemIds . contains ( e . getSalaryItemId ( ) ) ) . collect ( Collectors . toList ( ) ) ;
List < Long > salaryItemExistIds = salaryArchiveItems . stream ( ) . map ( SalaryArchiveItemDetailSaveParam : : getSalaryItemId ) . collect ( Collectors . toList ( ) ) ;
// 获取薪资档案所对应的当前生效的薪资项目数据
List < SalaryArchiveItemPO > salaryArchiveItemCurrentList = getSalaryArchiveItemService ( user ) . getCurrentEffectiveItemList ( Collections . singletonList ( saveParam . getSalaryArchiveId ( ) ) , salaryItemExistIds ) ;
List < SalaryArchiveItemPO > salaryArchiveItemAddTodos = Lists . newArrayList ( ) ;
List < Long > salaryArchiveItemDelTodoIds = Lists . newArrayList ( ) ;
Date now = new Date ( ) ;
salaryArchiveItems . forEach ( f - > {
Optional < SalaryItemPO > optional = salaryItems . stream ( ) . filter ( i - > i . getId ( ) . equals ( f . getSalaryItemId ( ) ) ) . findFirst ( ) ;
if ( optional . isPresent ( ) ) {
SalaryItemPO salaryItemPO = optional . get ( ) ;
boolean isNotNumber = salaryItemPO . getDataType ( ) . equals ( SalaryArchiveFieldTypeEnum . NUMBER . getValue ( ) ) & & StringUtils . isNotEmpty ( f . getAdjustValue ( ) ) & & ! Pattern . matches ( SalaryEntityUtil . NUMBER_REGEX , f . getAdjustValue ( ) ) ;
if ( isNotNumber ) {
throw new SalaryRunTimeException ( salaryItemPO . getName ( ) + " : " + SalaryI18nUtil . getI18nLabel ( 100581 , " 请输入数字 " ) ) ;
}
}
Optional < SalaryArchiveItemPO > optionalSAI = salaryArchiveItemCurrentList . stream ( ) . filter ( c - >
c . getSalaryArchiveId ( ) . equals ( saveParam . getSalaryArchiveId ( ) ) & & c . getSalaryItemId ( ) . equals ( f . getSalaryItemId ( ) )
) . findFirst ( ) ;
if ( StringUtils . isNotEmpty ( f . getAdjustValue ( ) ) ) {
salaryArchiveItemAddTodos . add ( SalaryArchiveItemPO . builder ( )
. id ( IdGenerator . generate ( ) )
. salaryArchiveId ( salaryArchive . getId ( ) )
. employeeId ( salaryArchive . getEmployeeId ( ) )
. effectiveTime ( saveParam . getPayStartDate ( ) )
. adjustReason ( SalaryArchiveItemAdjustReasonEnum . INIT . getValue ( ) )
. salaryItemId ( f . getSalaryItemId ( ) )
. itemValue ( f . getAdjustValue ( ) )
. description ( " " )
. operator ( currentEmployeeId )
. operateTime ( now )
. createTime ( now )
. updateTime ( now )
. creator ( currentEmployeeId )
. deleteType ( NumberUtils . INTEGER_ZERO )
. tenantKey ( SalaryDefaultTenantConstant . DEFAULT_TENANT_KEY )
. build ( ) ) ;
}
optionalSAI . ifPresent ( salaryArchiveItemPO - > salaryArchiveItemDelTodoIds . add ( salaryArchiveItemPO . getId ( ) ) ) ;
} ) ;
// 落库处理薪资档案项目数据
if ( CollectionUtils . isNotEmpty ( salaryArchiveItemAddTodos ) ) {
salaryArchiveItemMapper . batchInsert ( salaryArchiveItemAddTodos ) ;
}
if ( CollectionUtils . isNotEmpty ( salaryArchiveItemDelTodoIds ) ) {
salaryArchiveItemMapper . deleteBatchIds ( salaryArchiveItemDelTodoIds ) ;
}
}
// 定薪
} else if ( saveParam . getStatus ( ) . equals ( SalaryArchiveStatusEnum . FIXED ) ) {
if ( saveParam . getPayStartDate ( ) = = null ) {
throw new SalaryRunTimeException ( SalaryI18nUtil . getI18nLabel ( 109202 , " 起始发薪日期不能为空 " ) ) ;
}
salaryArchive . setPayStartDate ( saveParam . getPayStartDate ( ) ) ;
if ( saveParam . getPayEndDate ( ) ! = null ) {
if ( saveParam . getPayStartDate ( ) . after ( saveParam . getPayEndDate ( ) ) ) {
throw new SalaryRunTimeException ( SalaryI18nUtil . getI18nLabel ( 109214 , " 起始发薪日期不可晚于最后发薪日 " ) ) ;
}
}
salaryArchive . setPayEndDate ( saveParam . getPayEndDate ( ) ) ;
2023-04-17 15:31:56 +08:00
//如果是非系统人员,需要将起始发薪日期初始化
if ( Objects . equals ( salaryArchive . getEmployeeType ( ) , 1 ) ) {
salaryArchive . setRunStatus ( SalaryArchiveStatusEnum . FIXED . getValue ( ) ) ;
}
2022-10-14 16:18:55 +08:00
// 待停薪
} else if ( saveParam . getStatus ( ) . equals ( SalaryArchiveStatusEnum . SUSPEND ) ) {
if ( saveParam . getPayEndDate ( ) = = null ) {
throw new SalaryRunTimeException ( SalaryI18nUtil . getI18nLabel ( 109203 , " 最后发薪日期不能为空 " ) ) ;
}
if ( saveParam . getPayStartDate ( ) . after ( saveParam . getPayEndDate ( ) ) ) {
throw new SalaryRunTimeException ( SalaryI18nUtil . getI18nLabel ( 109214 , " 起始发薪日期不可晚于最后发薪日 " ) ) ;
}
salaryArchive . setPayEndDate ( saveParam . getPayEndDate ( ) ) ;
}
getSalaryArchiveMapper ( ) . update ( salaryArchive ) ;
// List<SalarySobPO> salarySobList = getSalarySobList(currentEmployeeId, currentTenantKey);
// List<Long> salarySobIds = salarySobList.stream().map(SalarySobPO::getId).filter(id -> saveParam.getSalarySobIds().contains(id)).collect(Collectors.toList());
2023-08-17 14:55:32 +08:00
// List<SalaryArchiveSobPO> salaryArchiveSobSaveList = SalaryArchiveBO.buildSalaryArchiveSob(salaryArchive.getId(), salarySobIds, LocalDateTime.now());
2022-10-14 16:18:55 +08:00
// this.salaryArchiveSobService.saveBatchBySalaryArchiveIdsAndSaves(Collections.singletonList(salaryArchive.getId()), salaryArchiveSobSaveList, currentTenantKey);
return StringUtils . EMPTY ;
}
2022-03-31 15:41:55 +08:00
@Override
public List < SalaryArchiveDimissionPO > dimissionSets ( ) {
return salaryArchiveDimissionMapper . dimissionSets ( ) ;
}
@Override
public String saveDimissionSet ( SalaryArchiveDimissionSaveParam saveParam ) {
Date now = new Date ( ) ;
List < SalaryArchiveDimissionPO > dimissionSets = dimissionSets ( ) ;
if ( CollectionUtils . isNotEmpty ( dimissionSets ) ) {
SalaryArchiveDimissionPO po = dimissionSets . get ( 0 ) ;
po . setDimissionTimeInterval ( saveParam . getDimissionTimeInterval ( ) . getValue ( ) ) ;
po . setUpdateTime ( now ) ;
salaryArchiveDimissionMapper . updateById ( po ) ;
} else {
2022-10-10 09:47:09 +08:00
salaryArchiveDimissionMapper . insert ( SalaryArchiveDimissionPO . builder ( ) . dimissionTimeInterval ( saveParam . getDimissionTimeInterval ( ) . getValue ( ) ) . createTime ( now ) . updateTime ( now ) . creator ( ( long ) user . getUID ( ) ) . tenantKey ( SalaryDefaultTenantConstant . DEFAULT_TENANT_KEY ) . build ( ) ) ;
2022-03-31 15:41:55 +08:00
}
return StringUtils . EMPTY ;
}
@Override
2022-08-09 16:45:22 +08:00
public List < SalaryArchiveDataDTO > getSalaryArchiveData ( LocalDateRange localDateRange , Collection < Long > employeeIds , Long taxAgentId ) {
return getSalaryArchiveData ( localDateRange , employeeIds , taxAgentId , Boolean . FALSE ) ;
2022-03-31 15:41:55 +08:00
}
@Override
2022-08-09 16:45:22 +08:00
public List < SalaryArchiveDataDTO > getSalaryArchiveTaxAgentData ( LocalDateRange localDateRange , Collection < Long > employeeIds , Long taxAgentId ) {
return getSalaryArchiveData ( localDateRange , employeeIds , taxAgentId , Boolean . TRUE ) ;
2022-03-31 15:41:55 +08:00
}
/ * *
* 根据日期范围和人员获取薪资档案数据
*
* @param localDateRange
* @param employeeIds
* @param isOnlyTaxAgent
* @return
* /
2022-08-09 16:45:22 +08:00
private List < SalaryArchiveDataDTO > getSalaryArchiveData ( LocalDateRange localDateRange , Collection < Long > employeeIds , Long taxAgentId , boolean isOnlyTaxAgent ) {
2023-06-16 14:40:36 +08:00
// 获取核算人员规则
List < String > statusList = Collections . emptyList ( ) ;
SalarySysConfPO employeeRule = getSalarySysConfService ( user ) . getOneByCode ( SalarySysConstant . SALARY_ACCT_EMPLOYEE_RULE ) ;
if ( Objects . isNull ( employeeRule ) | | StringUtils . equals ( employeeRule . getConfValue ( ) , SalaryAcctEmployeeRuleEnum . BYPAYENDTIME . getValue ( ) ) ) {
// 默认包含停薪列表
statusList = Arrays . asList ( SalaryArchiveStatusEnum . FIXED . getValue ( ) , SalaryArchiveStatusEnum . SUSPEND . getValue ( ) ,
2023-06-19 09:16:49 +08:00
SalaryArchiveStatusEnum . STOP_FROM_SUSPEND . getValue ( ) ) ;
2023-06-16 14:40:36 +08:00
} else {
// 仅包含发薪、待定薪
statusList = Arrays . asList ( SalaryArchiveStatusEnum . FIXED . getValue ( ) , SalaryArchiveStatusEnum . SUSPEND . getValue ( ) ) ;
}
2022-07-18 18:08:59 +08:00
// 获取薪资档案数据
2023-06-16 14:40:36 +08:00
List < SalaryArchivePO > salaryArchiveList = listSome ( SalaryArchivePO . builder ( ) . runStatusList ( statusList ) . employeeIds ( employeeIds ) . taxAgentId ( taxAgentId ) . build ( ) ) ;
2022-07-18 18:08:59 +08:00
List < Long > allEmployeeIds = salaryArchiveList . stream ( ) . map ( SalaryArchivePO : : getEmployeeId ) . distinct ( ) . collect ( Collectors . toList ( ) ) ;
2022-03-31 15:41:55 +08:00
// 获取所有可被引用的薪资项目
List < SalaryItemPO > salaryItems = salaryItemMapper . getCanAdjustSalaryItems ( ) ;
Collection < Long > salaryItemIds = salaryItems . stream ( ) . map ( SalaryItemPO : : getId ) . collect ( Collectors . toList ( ) ) ;
// 获取薪资项目调整数据,isOnlyTaxAgent为true时不需要薪资项目数据
2022-07-21 10:51:38 +08:00
List < SalaryArchiveItemPO > salaryArchiveItemDataList = isOnlyTaxAgent | | CollectionUtils . isEmpty ( salaryItemIds ) ? Lists . newArrayList ( ) : salaryArchiveItemMapper . listByParam ( SalaryArchiveItemQueryParam . builder ( ) . salaryItemIds ( salaryItemIds ) . employeeIds ( employeeIds ) . effectiveTime ( localDateRange . getEndDate ( ) ) . build ( ) ) ;
return SalaryArchiveBO . buildSalaryArchiveData ( salaryArchiveList , salaryArchiveItemDataList , localDateRange , allEmployeeIds , isOnlyTaxAgent ) ;
2022-03-31 15:41:55 +08:00
}
2022-07-13 18:59:30 +08:00
2022-09-07 09:45:37 +08:00
@Override
public void stopSalary ( SalaryArchiveStopParam stopSalaryParam ) {
ValidUtil . doValidator ( stopSalaryParam ) ;
stopSalaryParam . setPayEndDate ( SalaryDateUtil . stringToDate ( stopSalaryParam . getPayEndDateStr ( ) ) ) ;
SalaryArchivePO po = getSalaryArchiveMapper ( ) . getById ( stopSalaryParam . getSalaryArchiveId ( ) ) ;
if ( po = = null ) {
throw new SalaryRunTimeException ( " 未找到薪资档案 " ) ;
}
Date payStartDate = po . getPayStartDate ( ) ;
Date payEndDate = stopSalaryParam . getPayEndDate ( ) ;
2022-10-10 09:47:09 +08:00
if ( payEndDate . before ( payStartDate ) ) {
2022-09-07 09:45:37 +08:00
throw new SalaryRunTimeException ( " 最后缴纳日期应大于起始缴纳日期 " ) ;
}
po . setPayEndDate ( payEndDate ) ;
po . setUpdateTime ( new Date ( ) ) ;
getSalaryArchiveMapper ( ) . update ( po ) ;
}
2022-07-13 18:59:30 +08:00
2022-03-31 15:41:55 +08:00
@Override
public Map < String , Object > preview ( SalaryArchiveImportHandleParam param ) {
//1、参数校验
vaildImportParam ( param ) ;
Map < String , Object > map = new HashMap < > ( ) ;
InputStream fileInputStream = null ;
try {
2022-04-01 10:26:28 +08:00
fileInputStream = ImageFileManager . getInputStreamById ( Integer . parseInt ( param . getImageId ( ) ) ) ;
2022-03-31 15:41:55 +08:00
Sheet sheet = ExcelSupport . parseFile ( fileInputStream , 0 , EXCEL_TYPE_XLSX ) ;
List < String > headers = ExcelSupport . getSheetHeader ( sheet , 0 ) ;
map . put ( " headers " , headers ) ;
map . put ( " list " , ExcelParseHelper . parse2List ( sheet , 1 ) ) ;
return map ;
} finally {
IOUtils . closeQuietly ( fileInputStream ) ;
}
}
private void vaildImportParam ( SalaryArchiveImportHandleParam param ) {
String imageId = param . getImageId ( ) ;
if ( StringUtils . isBlank ( imageId ) ) {
throw new SalaryRunTimeException ( SalaryI18nUtil . getI18nLabel ( 100593 , " 文件id为空 " ) ) ;
}
2022-10-26 13:46:36 +08:00
if ( param . getListType ( ) = = null ) {
throw new SalaryRunTimeException ( SalaryI18nUtil . getI18nLabel ( 109712 , " 列表类型必传 " ) ) ;
} else {
// 定薪列表导入有调薪导入和初始化导入
if ( param . getListType ( ) . equals ( SalaryArchiveListTypeEnum . FIXED . getValue ( ) ) ) {
Optional < SalaryArchiveImportTypeEnum > optional = Arrays . stream ( SalaryArchiveImportTypeEnum . values ( ) )
. filter ( e - > StringUtils . isNotEmpty ( param . getImportType ( ) ) & & e . getValue ( ) . equals ( param . getImportType ( ) ) ) . findFirst ( ) ;
if ( ! optional . isPresent ( ) ) {
throw new SalaryRunTimeException ( SalaryI18nUtil . getI18nLabel ( 100593 , " 导入类型不正确 " ) ) ;
}
}
2022-03-31 15:41:55 +08:00
}
}
private List < SalaryArchiveTaxAgentPO > getEffectiveTaxAgentList ( ) {
2022-05-25 11:09:48 +08:00
Date truncate = DateUtils . truncate ( new Date ( ) , Calendar . DATE ) ;
return salaryArchiveTaxAgentMapper . getEffectiveTaxAgentList ( SalaryArchiveTaxAgentQueryParam . builder ( ) . effectiveTime ( truncate ) . build ( ) ) ;
2022-03-31 15:41:55 +08:00
}
private List < SalaryArchiveTaxAgentPO > getIneffectiveTaxAgentList ( ) {
2022-05-25 11:09:48 +08:00
Date truncate = DateUtils . truncate ( new Date ( ) , Calendar . DATE ) ;
return salaryArchiveTaxAgentMapper . getIneffectiveTaxAgentList ( SalaryArchiveTaxAgentQueryParam . builder ( ) . effectiveTime ( truncate ) . build ( ) ) ;
2022-03-31 15:41:55 +08:00
}
2022-07-14 10:36:51 +08:00
/ * *
* 处理历史数据
* 下回发版可删除
* /
public void handleHistory ( Long currentEmployeeId ) {
// 待定薪没设置过的默认为正常工资薪金所得
// new LambdaUpdateChainWrapper<>(salaryArchiveMapper)
// .eq(SalaryArchivePO::getDeleteType, 0)
// .eq(SalaryArchivePO::getTenantKey, tenantKey)
// .eq(SalaryArchivePO::getRunStatus, SalaryArchiveStatusEnum.PENDING.getValue())
// .isNull(SalaryArchivePO::getIncomeCategory)
// .set(SalaryArchivePO::getIncomeCategory, IncomeCategoryEnum.WAGES_AND_SALARIES.getValue())
// .update();
2022-10-09 10:55:35 +08:00
//历史档案默认为发薪员工
List < SalaryArchivePO > historyData = getSalaryArchiveMapper ( ) . getStatusIsNullData ( ) ;
List < Long > ids = SalaryEntityUtil . properties ( historyData , SalaryArchivePO : : getId , Collectors . toList ( ) ) ;
List < List < Long > > partIds = Lists . partition ( ids , 999 ) ;
for ( List < Long > part : partIds ) {
2022-10-10 09:47:09 +08:00
getSalaryArchiveMapper ( ) . updateStatus ( SalaryArchivePO . builder ( ) . ids ( part ) . runStatus ( SalaryArchiveStatusEnum . FIXED . getValue ( ) ) . build ( ) ) ;
2022-10-09 10:55:35 +08:00
}
//处理个税扣缴义务人为空
List < SalaryArchivePO > salaryArchives = getSalaryArchiveMapper ( ) . getHistoryData ( ) ;
2022-07-14 10:36:51 +08:00
if ( CollectionUtils . isEmpty ( salaryArchives ) ) {
return ;
}
Date today = new Date ( ) ;
List < SalaryArchiveTaxAgentPO > salaryArchiveTaxAgents = getEffectiveTaxAgentList ( ) ;
List < SalaryArchiveItemPO > salaryArchiveItems = salaryArchiveItemMapper . getEffectiveSalaryItems ( SalaryArchiveItemQueryParam . builder ( ) . effectiveTime ( today ) . build ( ) ) ;
List < Long > salaryArchiveDelIds = salaryArchives . stream ( ) . map ( SalaryArchivePO : : getId ) . collect ( Collectors . toList ( ) ) ;
List < Long > salaryArchiveTaxAgentDelIds = salaryArchiveTaxAgents . stream ( ) . map ( SalaryArchiveTaxAgentPO : : getId ) . collect ( Collectors . toList ( ) ) ;
List < Long > salaryArchiveItemDelIds = salaryArchiveItems . stream ( ) . map ( SalaryArchiveItemPO : : getId ) . collect ( Collectors . toList ( ) ) ;
List < SalaryArchivePO > salaryArchiveAddList = Lists . newArrayList ( ) ;
List < SalaryArchiveItemPO > salaryArchiveItemAddList = Lists . newArrayList ( ) ;
Date endDate = today ;
for ( SalaryArchivePO sa : salaryArchives ) {
List < SalaryArchiveTaxAgentPO > saTaxAgents = salaryArchiveTaxAgents . stream ( ) . filter ( t - > t . getSalaryArchiveId ( ) . equals ( sa . getId ( ) ) ) . collect ( Collectors . toList ( ) ) ;
// 去重获取最新生效的个税口角义务人列表
saTaxAgents = saTaxAgents . stream ( ) . collect ( Collectors . collectingAndThen ( Collectors . toCollection ( ( ) - > new TreeSet < > ( Comparator . comparing ( f - > f . getSalaryArchiveId ( ) + " - " + f . getTaxAgentId ( ) ) ) ) , ArrayList : : new ) ) ;
List < SalaryArchiveItemPO > saItemList = salaryArchiveItems . stream ( ) . filter ( i - > i . getSalaryArchiveId ( ) . equals ( sa . getId ( ) ) ) . collect ( Collectors . toList ( ) ) ;
for ( SalaryArchiveTaxAgentPO st : saTaxAgents ) {
Date finalEndDate = endDate ;
2022-07-21 10:51:38 +08:00
List < SalaryArchiveItemPO > saItems = saItemList . stream ( ) . filter ( si - > ! si . getEffectiveTime ( ) . after ( finalEndDate ) ) . collect ( Collectors . collectingAndThen ( Collectors . toCollection ( ( ) - > new TreeSet < > ( Comparator . comparing ( f - > f . getSalaryArchiveId ( ) + " - " + f . getSalaryItemId ( ) ) ) ) , ArrayList : : new ) ) ;
SalaryArchivePO newSA = SalaryArchivePO . builder ( ) . id ( IdGenerator . generate ( ) ) . employeeId ( sa . getEmployeeId ( ) ) . taxAgentId ( st . getTaxAgentId ( ) ) . payStartDate ( st . getEffectiveTime ( ) )
2022-07-14 10:36:51 +08:00
// .runStatus(SalaryArchiveStatusEnum.FIXED.getValue())
// .modifier(0L)
2022-07-21 10:51:38 +08:00
. createTime ( today ) . updateTime ( today ) . creator ( currentEmployeeId ) . deleteType ( NumberUtils . INTEGER_ZERO ) . tenantKey ( SalaryDefaultTenantConstant . DEFAULT_TENANT_KEY ) . build ( ) ;
2022-07-14 10:36:51 +08:00
salaryArchiveAddList . add ( newSA ) ;
saItems . forEach ( sf - > {
2022-10-10 09:47:09 +08:00
salaryArchiveItemAddList . add ( SalaryArchiveItemPO . builder ( ) . salaryArchiveId ( newSA . getId ( ) ) . employeeId ( newSA . getEmployeeId ( ) ) . effectiveTime ( sf . getEffectiveTime ( ) ) . adjustReason ( sf . getAdjustReason ( ) ) . salaryItemId ( sf . getSalaryItemId ( ) ) . itemValue ( sf . getItemValue ( ) ) . description ( sf . getDescription ( ) )
2022-07-14 10:36:51 +08:00
// 不用设置操作人
2022-07-21 10:51:38 +08:00
. operator ( currentEmployeeId ) . operateTime ( today ) . createTime ( today ) . updateTime ( today ) . creator ( currentEmployeeId ) . deleteType ( NumberUtils . INTEGER_ZERO ) . tenantKey ( SalaryDefaultTenantConstant . DEFAULT_TENANT_KEY ) . build ( ) ) ;
2022-07-14 10:36:51 +08:00
} ) ;
2022-07-18 18:08:59 +08:00
// endDate = st.getEffectiveTime();
2022-07-14 10:36:51 +08:00
}
}
// 逻辑删除历史数据
List < List < Long > > partition = Lists . partition ( salaryArchiveDelIds , 999 ) ;
for ( List < Long > part : partition ) {
salaryArchiveMapper . batchDeleteHistoryData ( SalaryArchivePO . builder ( ) . ids ( part ) . build ( ) ) ;
}
List < List < Long > > partitionTA = Lists . partition ( salaryArchiveTaxAgentDelIds , 999 ) ;
for ( List < Long > part : partitionTA ) {
salaryArchiveTaxAgentMapper . batchDeleteHistoryData ( SalaryArchiveTaxAgentPO . builder ( ) . ids ( part ) . build ( ) ) ;
}
List < List < Long > > partitionItem = Lists . partition ( salaryArchiveItemDelIds , 999 ) ;
for ( List < Long > part : partitionItem ) {
salaryArchiveItemMapper . batchDeleteHistoryData ( SalaryArchiveItemPO . builder ( ) . ids ( part ) . build ( ) ) ;
}
// 新增迁移数据
if ( CollectionUtils . isNotEmpty ( salaryArchiveAddList ) ) {
this . salaryArchiveMapper . batchInsert ( salaryArchiveAddList ) ;
}
if ( CollectionUtils . isNotEmpty ( salaryArchiveItemAddList ) ) {
this . salaryArchiveItemMapper . batchInsert ( salaryArchiveItemAddList ) ;
}
log . info ( " 处理历史数据结束=============== " ) ;
}
2022-07-21 09:43:02 +08:00
2022-07-13 18:59:30 +08:00
@Override
public Map < String , Object > selectSalaryArchiveColumns ( SalaryArchiveImportTypeEnum salaryArchiveImportTypeEnum ) {
2022-07-21 09:48:40 +08:00
HashMap < String , Object > map = Maps . newHashMap ( ) ;
2022-07-13 18:59:30 +08:00
//类型为档案初始化
boolean isInit = salaryArchiveImportTypeEnum . getValue ( ) . equals ( SalaryArchiveImportTypeEnum . INIT . getValue ( ) ) ;
//类型为调整个税扣缴义务人
boolean isTaxAgentAdjust = salaryArchiveImportTypeEnum . getValue ( ) . equals ( SalaryArchiveImportTypeEnum . TAXAGENTADJUST . getValue ( ) ) ;
//类型为调薪
boolean isSalaryItemAdjust = salaryArchiveImportTypeEnum . getValue ( ) . equals ( SalaryArchiveImportTypeEnum . SALARYITEMADJUST . getValue ( ) ) ;
//固定列
2022-07-21 09:48:40 +08:00
map . put ( SalaryI18nUtil . getI18nLabel ( 85429 , " 姓名 " ) , " username " ) ;
map . put ( SalaryI18nUtil . getI18nLabel ( 86184 , " 个税扣缴义务人 " ) , " taxAgentName " ) ;
map . put ( SalaryI18nUtil . getI18nLabel ( 85904 , " 生效日期 " ) , " taxAgentEffectiveTime " ) ;
map . put ( SalaryI18nUtil . getI18nLabel ( 86185 , " 部门 " ) , " departmentName " ) ;
map . put ( SalaryI18nUtil . getI18nLabel ( 86186 , " 手机号 " ) , " mobile " ) ;
map . put ( SalaryI18nUtil . getI18nLabel ( 91075 , " 员工状态 " ) , " employeeStatus " ) ;
2022-07-13 18:59:30 +08:00
List < SalaryItemPO > salaryItems = salaryItemMapper . getCanAdjustSalaryItems ( ) ;
if ( isTaxAgentAdjust | | isSalaryItemAdjust ) {
2022-07-21 09:48:40 +08:00
map . put ( SalaryI18nUtil . getI18nLabel ( 85431 , " 调整原因 " ) , " adjustReason " ) ;
2022-07-13 18:59:30 +08:00
}
//动态列
// 获取所有可被引用的薪资项目
if ( isInit | | isSalaryItemAdjust ) {
for ( SalaryItemPO salaryItem : salaryItems ) {
2022-07-21 09:48:40 +08:00
map . put ( salaryItem . getName ( ) , salaryItem . getCode ( ) ) ;
2022-07-13 18:59:30 +08:00
}
}
return map ;
}
2022-10-10 14:58:29 +08:00
@Override
public Map < String , Long > queryTabTotal ( ) {
long currentEmployeeId = user . getUID ( ) ;
// tab页签数量
Map < String , Long > result = new HashMap < > ( ) ;
Boolean needAuth = getTaxAgentService ( user ) . isNeedAuth ( currentEmployeeId ) ;
//获取管理的人员范围
List < TaxAgentManageRangeEmployeeDTO > taxAgentEmployeeDTOS = getTaxAgentService ( user ) . listTaxAgentAndEmployeeTree ( currentEmployeeId ) ;
Map < Long , List < TaxAgentManageRangeEmployeeDTO . TaxAgentEmployee > > taxAgentEmployeesMap = SalaryEntityUtil . convert2Map ( taxAgentEmployeeDTOS , TaxAgentManageRangeEmployeeDTO : : getTaxAgentId , TaxAgentManageRangeEmployeeDTO : : getEmployeeList ) ;
2023-03-15 22:48:01 +08:00
List < SalaryArchivePO > list = new ArrayList < > ( ) ;
2022-10-10 14:58:29 +08:00
if ( needAuth ) {
// 获取作为管理员的所有个税扣缴义务人列表
Collection < TaxAgentPO > taxAgentPOS = getTaxAgentService ( user ) . listAllTaxAgentsAsAdmin ( currentEmployeeId ) ;
Set < Long > taxAgentIds = SalaryEntityUtil . properties ( taxAgentPOS , TaxAgentPO : : getId ) ;
//获取所有薪资档案
List < SalaryArchivePO > archiveListDTOS = getSalaryArchiveMapper ( ) . listAll ( ) ;
list = archiveListDTOS . stream ( ) . filter ( dto - > taxAgentIds . contains ( dto . getTaxAgentId ( ) ) ) . collect ( Collectors . toList ( ) ) ;
Boolean adminEnable = getTaxAgentService ( user ) . isAdminEnable ( currentEmployeeId ) ;
//不是管理员看不到数据,返回空
if ( ! adminEnable ) {
list = new ArrayList < > ( ) ;
}
} else {
list = getSalaryArchiveMapper ( ) . listAll ( ) ;
}
long pendingTotal = 0L ;
long fixedTotal = 0L ;
long suspendTotal = 0L ;
long stopTotal = 0L ;
2023-03-15 22:48:01 +08:00
long extTotal = 0L ;
2022-10-10 14:58:29 +08:00
for ( SalaryArchivePO sa : list ) {
2023-03-15 22:48:01 +08:00
Integer employeeType = sa . getEmployeeType ( ) ;
if ( employeeType = = null | | employeeType = = 0 ) {
if ( sa . getRunStatus ( ) . equals ( SalaryArchiveStatusEnum . PENDING . getValue ( ) ) ) {
pendingTotal + = 1 ;
} else if ( sa . getRunStatus ( ) . equals ( SalaryArchiveStatusEnum . FIXED . getValue ( ) ) | | sa . getRunStatus ( ) . equals ( SalaryArchiveStatusEnum . SUSPEND . getValue ( ) ) ) {
fixedTotal + = 1 ;
if ( sa . getRunStatus ( ) . equals ( SalaryArchiveStatusEnum . SUSPEND . getValue ( ) ) ) {
suspendTotal + = 1 ;
}
} else if ( sa . getRunStatus ( ) . equals ( SalaryArchiveStatusEnum . STOP_FROM_PENDING . getValue ( ) ) | | sa . getRunStatus ( ) . equals ( SalaryArchiveStatusEnum . STOP_FROM_SUSPEND . getValue ( ) ) ) {
stopTotal + = 1 ;
2022-10-10 14:58:29 +08:00
}
2023-03-15 22:48:01 +08:00
} else {
extTotal + = 1 ;
2022-10-10 14:58:29 +08:00
}
}
result . put ( SalaryArchiveListTypeEnum . PENDING . getValue ( ) , pendingTotal ) ;
result . put ( SalaryArchiveListTypeEnum . FIXED . getValue ( ) , fixedTotal ) ;
result . put ( SalaryArchiveListTypeEnum . SUSPEND . getValue ( ) , suspendTotal ) ;
result . put ( SalaryArchiveListTypeEnum . STOP . getValue ( ) , stopTotal ) ;
2023-03-15 22:48:01 +08:00
result . put ( SalaryArchiveListTypeEnum . EXT . getValue ( ) , extTotal ) ;
2022-10-10 14:58:29 +08:00
return result ;
}
2022-10-13 14:57:52 +08:00
2022-10-18 16:44:31 +08:00
@Override
public String deletePendingTodo ( Collection < Long > ids ) {
if ( CollectionUtils . isEmpty ( ids ) ) {
throw new SalaryRunTimeException ( SalaryI18nUtil . getI18nLabel ( 84026 , " 参数错误 " ) ) ;
}
2022-11-03 19:32:51 +08:00
List < SalaryArchivePO > oldList = listSome ( SalaryArchivePO . builder ( )
2022-11-07 15:11:24 +08:00
. ids ( ids )
. runStatus ( SalaryArchiveStatusEnum . PENDING . getValue ( ) )
. build ( ) ) ;
2022-10-18 16:44:31 +08:00
if ( CollectionUtils . isEmpty ( oldList ) ) {
return StringUtils . EMPTY ;
}
// 从待定薪到停薪
getSalaryArchiveMapper ( ) . deletePendingTodo ( ids ) ;
return StringUtils . EMPTY ;
}
2022-10-13 14:57:52 +08:00
@Override
public Map < String , Object > gotoFixed ( Collection < Long > ids ) {
if ( CollectionUtils . isEmpty ( ids ) ) {
throw new SalaryRunTimeException ( SalaryI18nUtil . getI18nLabel ( 145969 , " 没有可以操作的记录 " ) ) ;
}
2022-11-03 19:32:51 +08:00
List < SalaryArchivePO > salaryArchiveList = listSome ( SalaryArchivePO . builder ( ) . ids ( ids ) . runStatus ( SalaryArchiveStatusEnum . PENDING . getValue ( ) ) . build ( ) ) ;
2022-11-03 17:16:37 +08:00
2022-10-13 16:24:59 +08:00
if ( CollectionUtils . isEmpty ( salaryArchiveList ) ) {
throw new SalaryRunTimeException ( SalaryI18nUtil . getI18nLabel ( 145969 , " 档案不存在! " ) ) ;
}
2022-10-13 14:57:52 +08:00
List < SalaryArchivePO > unableList = salaryArchiveList . stream ( ) . filter ( f - > f . getPayStartDate ( ) = = null ) . collect ( Collectors . toList ( ) ) ;
int total = ids . size ( ) ;
int errorCount = unableList . size ( ) ;
// 单个设为定薪的失败提示
if ( total = = 1 & & errorCount > 0 ) {
throw new SalaryRunTimeException ( SalaryI18nUtil . getI18nLabel ( 109197 , " 请先维护起始发薪日期 " ) ) ;
}
// 从待定薪到定薪
2022-11-03 19:32:51 +08:00
List < List < Long > > partition = Lists . partition ( ( List < Long > ) ids , 1000 ) ;
2022-11-03 17:16:37 +08:00
partition . forEach ( getSalaryArchiveMapper ( ) : : gotoFixed ) ;
2022-10-13 14:57:52 +08:00
// 获取所有可被引用的薪资项目
List < Long > salaryItemIds = getSalaryArchiveItemService ( user ) . getCanAdjustSalaryItems ( ) . stream ( ) . map ( SalaryItemPO : : getId ) . collect ( Collectors . toList ( ) ) ;
List < SalaryArchiveItemPO > currentEffectiveItemList = getSalaryArchiveItemService ( user ) . getCurrentEffectiveItemListIngoreValue ( ids , salaryItemIds )
. stream ( )
. peek ( e - > {
Optional < SalaryArchivePO > salaryArchive = salaryArchiveList . stream ( ) . filter ( sa - > sa . getId ( ) . equals ( e . getSalaryArchiveId ( ) ) ) . findFirst ( ) ;
if ( salaryArchive . isPresent ( ) ) {
e . setAdjustReason ( SalaryArchiveItemAdjustReasonEnum . INIT . getValue ( ) ) ;
e . setEffectiveTime ( salaryArchive . get ( ) . getPayStartDate ( ) ) ;
}
} ) . collect ( Collectors . toList ( ) ) ;
// 更新薪资项目的生效日期
2022-11-03 17:16:37 +08:00
List < List < SalaryArchiveItemPO > > partitions = Lists . partition ( currentEffectiveItemList , 100 ) ;
partitions . forEach ( list - > getSalaryArchiveItemMapper ( ) . batchUpdate ( list ) ) ;
2022-10-13 14:57:52 +08:00
Map < String , Object > resultMap = new HashMap < > ( 2 ) ;
String resultMsg = SalaryI18nUtil . getI18nLabel ( 94620 , " 操作成功 " ) ;
String resultType = " success " ;
// 批量设为定薪提示
if ( total > 1 ) {
resultMsg = SalaryI18nUtil . getI18nLabel ( 134807 , " 成功条数 " ) + " : " + ( total - errorCount ) + " ; "
+ SalaryI18nUtil . getI18nLabel ( 134808 , " 失败条数 " ) + " : " + ( errorCount )
+ ( errorCount > 0 ? " , " + SalaryI18nUtil . getI18nLabel ( 109197 , " 请先维护起始发薪日期 " ) : " " ) ;
resultType = errorCount > 0 ? " info " : resultType ;
}
resultMap . put ( " type " , resultType ) ;
resultMap . put ( " msg " , resultMsg ) ;
return resultMap ;
}
@Override
public Map < String , Object > allGotoFixed ( SalaryArchiveQueryParam queryParam ) {
queryParam . setRunStatusList ( Arrays . asList ( SalaryArchiveStatusEnum . PENDING . getValue ( ) ) ) ;
List < Long > salaryArchiveIds = this . list ( queryParam )
. stream ( ) . map ( SalaryArchiveListDTO : : getId ) . collect ( Collectors . toList ( ) ) ;
return this . gotoFixed ( salaryArchiveIds ) ;
}
@Override
public Map < String , Object > gotoStop ( Collection < Long > ids ) {
if ( CollectionUtils . isEmpty ( ids ) ) {
throw new SalaryRunTimeException ( SalaryI18nUtil . getI18nLabel ( 145969 , " 没有可以操作的记录 " ) ) ;
}
2022-11-03 19:32:51 +08:00
List < SalaryArchivePO > oldList = listSome ( SalaryArchivePO . builder ( )
2022-11-07 15:11:24 +08:00
. ids ( ids )
. runStatus ( SalaryArchiveStatusEnum . SUSPEND . getValue ( ) )
. build ( ) ) ;
2022-10-13 14:57:52 +08:00
2022-10-13 16:24:59 +08:00
if ( CollectionUtils . isEmpty ( oldList ) ) {
throw new SalaryRunTimeException ( SalaryI18nUtil . getI18nLabel ( 145969 , " 档案不存在! " ) ) ;
}
2022-10-13 14:57:52 +08:00
List < SalaryArchivePO > unableList = oldList . stream ( ) . filter ( f - > f . getPayEndDate ( ) = = null ) . collect ( Collectors . toList ( ) ) ;
int total = ids . size ( ) ;
int errorCount = unableList . size ( ) ;
// 单个设为定薪的失败提示
if ( total = = 1 & & errorCount > 0 ) {
throw new SalaryRunTimeException ( SalaryI18nUtil . getI18nLabel ( 109196 , " 请先维护最后发薪日期 " ) ) ;
}
// 从待停薪到停薪
getSalaryArchiveMapper ( ) . gotoStop ( ids ) ;
Map < String , Object > resultMap = new HashMap < > ( 2 ) ;
String resultMsg = SalaryI18nUtil . getI18nLabel ( 94620 , " 操作成功 " ) ;
String resultType = " success " ;
// 批量设为定薪提示
if ( total > 1 ) {
resultMsg = SalaryI18nUtil . getI18nLabel ( 134807 , " 成功条数 " ) + " : " + ( total - errorCount ) + " ; "
+ SalaryI18nUtil . getI18nLabel ( 134808 , " 失败条数 " ) + " : " + ( errorCount )
+ ( errorCount > 0 ? " , " + SalaryI18nUtil . getI18nLabel ( 109196 , " 请先维护最后发薪日期 " ) : " " ) ;
resultType = errorCount > 0 ? " info " : resultType ;
}
resultMap . put ( " type " , resultType ) ;
resultMap . put ( " msg " , resultMsg ) ;
return resultMap ;
}
@Override
public Map < String , Object > allGotoStop ( SalaryArchiveQueryParam queryParam ) {
queryParam . setRunStatusList ( Arrays . asList ( SalaryArchiveStatusEnum . SUSPEND . getValue ( ) ) ) ;
List < Long > salaryArchiveIds = this . list ( queryParam )
. stream ( ) . map ( SalaryArchiveListDTO : : getId ) . collect ( Collectors . toList ( ) ) ;
return this . gotoStop ( salaryArchiveIds ) ;
}
2022-10-18 16:44:31 +08:00
@Override
public String deleteSuspendTodo ( Collection < Long > ids ) {
if ( org . springframework . util . CollectionUtils . isEmpty ( ids ) ) {
2022-10-26 13:46:36 +08:00
throw new SalaryRunTimeException ( SalaryI18nUtil . getI18nLabel ( 84026 , " 参数错误 " ) ) ;
2022-10-18 16:44:31 +08:00
}
2023-03-28 10:10:54 +08:00
// List<SalaryArchivePO> oldList = listSome(SalaryArchivePO.builder()
// .ids(ids)
// .runStatus(SalaryArchiveStatusEnum.SUSPEND.getValue())
// .build());
// List<SalaryArchivePO> unableList = oldList.stream().filter(f -> Objects.nonNull(f.getPayEndDate()) && !f.getPayEndDate().after(new Date())).collect(Collectors.toList());
// if (CollectionUtils.isNotEmpty(unableList)) {
// throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(115789, "最后发薪日必须晚于今天"));
// }
//
// // 从待停薪到定薪
// getSalaryArchiveMapper().deleteSuspendTodo(ids);
// return StringUtils.EMPTY;
2022-10-18 16:44:31 +08:00
2023-03-28 10:10:54 +08:00
// 获取所有个税扣缴义务人
Collection < TaxAgentManageRangeEmployeeDTO > taxAgentList = getTaxAgentService ( user ) . listTaxAgentAndEmployeeTree ( Long . valueOf ( user . getUID ( ) ) ) ;
// 获取删除待停薪信息
List < SalaryArchiveListDTO > list = getSalaryArchiveMapper ( ) . list ( SalaryArchiveQueryParam . builder ( ) . ids ( ids ) . build ( ) ) ;
2023-04-17 15:31:56 +08:00
if ( list . size ( ) ! = ids . size ( ) ) {
2023-03-28 10:10:54 +08:00
throw new SalaryRunTimeException ( " 薪资档案不存在,删除失败! " ) ;
}
2023-03-31 10:17:31 +08:00
Set < String > employeeStatus = list . stream ( ) . map ( SalaryArchiveListDTO : : getEmployeeStatus ) . collect ( Collectors . toSet ( ) ) ;
2023-04-17 15:31:56 +08:00
if ( employeeStatus . contains ( " 5 " ) ) {
2023-03-31 10:17:31 +08:00
throw new SalaryRunTimeException ( " 离职人员无法删除待办 " ) ;
}
2023-03-28 10:10:54 +08:00
Map < Long , TaxAgentManageRangeEmployeeDTO > taxAgentMap = SalaryEntityUtil . convert2Map ( taxAgentList , TaxAgentManageRangeEmployeeDTO : : getTaxAgentId ) ;
// 判断删除待停薪代办的人是否在个税扣缴义务人的人员范围中
2023-04-17 15:31:56 +08:00
for ( SalaryArchiveListDTO dto : list ) {
2023-03-28 10:10:54 +08:00
TaxAgentManageRangeEmployeeDTO taxAgentManageRangeEmployeeDTO = taxAgentMap . get ( dto . getTaxAgentId ( ) ) ;
2023-04-17 15:31:56 +08:00
if ( Objects . nonNull ( taxAgentManageRangeEmployeeDTO ) ) {
2023-03-28 10:10:54 +08:00
boolean canDelete = taxAgentManageRangeEmployeeDTO . getEmployeeList ( ) . stream ( )
. map ( TaxAgentManageRangeEmployeeDTO . TaxAgentEmployee : : getEmployeeId )
. anyMatch ( id - > Objects . equals ( id , dto . getEmployeeId ( ) ) ) ;
2023-04-17 15:31:56 +08:00
if ( ! canDelete ) {
2023-03-28 10:10:54 +08:00
throw new SalaryRunTimeException ( " 个税扣缴义务人不存在或不在权限范围内,删除失败! " ) ;
}
2023-04-17 15:31:56 +08:00
} else {
2023-03-28 10:10:54 +08:00
throw new SalaryRunTimeException ( " 个税扣缴义务人不存在或不在权限范围内,删除失败! " ) ;
}
}
// 删除最后发薪日期,设置状态为发薪
2023-04-17 15:31:56 +08:00
if ( CollectionUtils . isNotEmpty ( list ) ) {
2023-03-28 10:10:54 +08:00
getSalaryArchiveMapper ( ) . deleteSuspendTodo ( list . stream ( ) . map ( SalaryArchiveListDTO : : getId ) . collect ( Collectors . toList ( ) ) ) ;
}
2022-10-18 16:44:31 +08:00
return StringUtils . EMPTY ;
}
2022-10-13 14:57:52 +08:00
@Override
public String cancelStop ( Collection < Long > ids ) {
if ( org . springframework . util . CollectionUtils . isEmpty ( ids ) ) {
throw new SalaryRunTimeException ( SalaryI18nUtil . getI18nLabel ( 84026 , " 参数错误 " ) ) ;
}
2022-11-03 19:32:51 +08:00
List < SalaryArchivePO > oldList = listSome (
2022-10-13 14:57:52 +08:00
SalaryArchivePO . builder ( )
. ids ( ids )
. runStatusList ( Arrays . asList ( SalaryArchiveStatusEnum . STOP_FROM_PENDING . getValue ( ) , SalaryArchiveStatusEnum . STOP_FROM_SUSPEND . getValue ( ) ) )
. build ( ) ) ;
2022-10-13 16:24:59 +08:00
if ( CollectionUtils . isEmpty ( oldList ) ) {
throw new SalaryRunTimeException ( SalaryI18nUtil . getI18nLabel ( 145969 , " 档案不存在! " ) ) ;
}
2022-10-13 14:57:52 +08:00
List < TaxAgentEmployeeDTO > taxAgentManageRangeEmployees = getTaxAgentService ( user ) . listTaxAgentAndEmployee ( ( long ) user . getUID ( ) ) ;
List < SalaryArchivePO > oldPendingList = oldList . stream ( ) . filter ( f - > f . getRunStatus ( ) . equals ( SalaryArchiveStatusEnum . STOP_FROM_PENDING . getValue ( ) ) ) . collect ( Collectors . toList ( ) ) ;
boolean isNotExist = oldPendingList . stream ( ) . anyMatch ( te - > taxAgentManageRangeEmployees . stream ( ) . noneMatch ( p - > p . getEmployeeId ( ) ! = null & & p . getEmployeeId ( ) . equals ( te . getEmployeeId ( ) ) & & p . getTaxAgentId ( ) . equals ( te . getTaxAgentId ( ) ) ) ) ;
if ( isNotExist ) {
throw new SalaryRunTimeException ( SalaryI18nUtil . getI18nLabel ( 116196 , " 不在当前个税扣缴义人的人员范围中,不可取消停薪 " ) ) ;
}
// 从停薪到待定薪
getSalaryArchiveMapper ( ) . gotoPendingFromStop ( ids ) ;
// 从停薪到定薪
getSalaryArchiveMapper ( ) . gotoFixedFromStop ( ids ) ;
return StringUtils . EMPTY ;
}
2022-11-07 17:05:50 +08:00
@Override
public Map < String , Object > handleRepeatData ( ) {
Map < String , Object > result = new HashMap < > ( ) ;
//获取所有薪资档案
List < SalaryArchivePO > list = getSalaryArchiveMapper ( ) . listSome ( SalaryArchivePO . builder ( ) . runStatus ( SalaryArchiveStatusEnum . PENDING . getValue ( ) ) . build ( ) ) ;
AtomicInteger num = new AtomicInteger ( ) ;
if ( CollectionUtils . isNotEmpty ( list ) ) {
Map < String , List < SalaryArchivePO > > maps = SalaryEntityUtil . group2Map ( list , k - > k . getTaxAgentId ( ) + " - " + k . getEmployeeId ( ) ) ;
maps . forEach ( ( key , pos ) - > {
if ( pos . size ( ) > 1 ) {
for ( int i = 1 ; i < pos . size ( ) ; i + + ) {
SalaryArchivePO salaryArchivePO = pos . get ( i ) ;
getSalaryArchiveMapper ( ) . delete ( salaryArchivePO ) ;
num . getAndIncrement ( ) ;
}
}
} ) ;
}
result . put ( " 共处理 " , num . get ( ) ) ;
return result ;
}
2023-08-30 10:41:00 +08:00
@Override
public List < SalaryArchivePO > listPayEndDateIsNull ( List < Long > employeeIds ) {
if ( CollectionUtils . isEmpty ( employeeIds ) ) {
return Collections . emptyList ( ) ;
}
return getSalaryArchiveMapper ( ) . listPayEndDateIsNull ( employeeIds ) ;
}
2023-08-18 17:56:34 +08:00
@Override
public Map < Long , String > getAzRyflInfo ( List < Long > employeeIds ) {
Map < Long , String > result = new HashMap < > ( ) ;
if ( CollectionUtils . isEmpty ( employeeIds ) ) {
return result ;
}
String employeeIdStr = " ( " + StringUtils . join ( employeeIds , " , " ) + " ) " ;
RecordSet rs = new RecordSet ( ) ;
// 获取人事中设置的人员分类信息
String sql = " select a.id,b.jobactivityname from cus_fielddata a left join hrmjobactivities b on a.field16=b.id where a.scopeid=3 and a.id in " + employeeIdStr ;
rs . execute ( sql ) ;
while ( rs . next ( ) ) {
String jobactivityname = Util . null2String ( rs . getString ( " jobactivityname " ) ) ;
if ( StringUtils . contains ( jobactivityname , " ~`~`7 " ) ) {
String [ ] split = StringUtils . split ( jobactivityname , " ~` " ) ;
for ( String str : split ) {
if ( StringUtils . startsWith ( str , " 7 " ) ) {
String flName = str . substring ( 2 , str . length ( ) ) ;
result . put ( Long . valueOf ( rs . getInt ( " id " ) ) , flName ) ;
}
}
} else {
result . put ( Long . valueOf ( rs . getInt ( " id " ) ) , jobactivityname ) ;
}
}
return result ;
}
2023-09-04 14:20:42 +08:00
@Override
public List < SalaryArchivePO > listByRunStatus ( List < String > list ) {
return getSalaryArchiveMapper ( ) . listSome ( SalaryArchivePO . builder ( ) . runStatusList ( list ) . build ( ) ) ;
}
2022-03-31 15:41:55 +08:00
}