|
@@ -1,11 +1,42 @@
|
|
|
package nckd.jxccl.hr.ijp.plugin.operate;
|
|
package nckd.jxccl.hr.ijp.plugin.operate;
|
|
|
|
|
|
|
|
|
|
+import kd.bos.context.RequestContext;
|
|
|
|
|
+import kd.bos.dataentity.OperateOption;
|
|
|
import kd.bos.dataentity.entity.DynamicObject;
|
|
import kd.bos.dataentity.entity.DynamicObject;
|
|
|
import kd.bos.dataentity.entity.DynamicObjectCollection;
|
|
import kd.bos.dataentity.entity.DynamicObjectCollection;
|
|
|
|
|
+import kd.bos.entity.EntityMetadataCache;
|
|
|
|
|
+import kd.bos.entity.ExtendedDataEntity;
|
|
|
|
|
+import kd.bos.entity.MainEntityType;
|
|
|
|
|
+import kd.bos.entity.operate.result.OperationResult;
|
|
|
import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
|
|
import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
|
|
|
|
|
+import kd.bos.entity.plugin.AddValidatorsEventArgs;
|
|
|
import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
|
|
import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
|
|
|
|
|
+import kd.bos.entity.validate.AbstractValidator;
|
|
|
|
|
+import kd.bos.orm.query.QCP;
|
|
|
|
|
+import kd.bos.orm.query.QFilter;
|
|
|
|
|
+import kd.bos.servicehelper.BusinessDataServiceHelper;
|
|
|
|
|
+import kd.bos.servicehelper.QueryServiceHelper;
|
|
|
|
|
+import kd.bos.servicehelper.operation.SaveServiceHelper;
|
|
|
import kd.sdk.plugin.Plugin;
|
|
import kd.sdk.plugin.Plugin;
|
|
|
import nckd.jxccl.base.common.constant.FormConstant;
|
|
import nckd.jxccl.base.common.constant.FormConstant;
|
|
|
|
|
+import nckd.jxccl.base.common.enums.ijp.TalentTypeEnum;
|
|
|
|
|
+import nckd.jxccl.base.common.utils.DateUtil;
|
|
|
|
|
+import nckd.jxccl.base.common.utils.QueryFieldBuilder;
|
|
|
|
|
+import nckd.jxccl.base.common.utils.StrFormatter;
|
|
|
|
|
+import nckd.jxccl.base.entity.helper.EntityHelper;
|
|
|
|
|
+import nckd.jxccl.base.hrpi.helper.EmpPosOrgRelHelper;
|
|
|
|
|
+import nckd.jxccl.hr.ijp.common.IntJobPostConstant;
|
|
|
|
|
+import nckd.jxccl.hr.psms.common.PositionStructureConstant;
|
|
|
|
|
+
|
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
|
+import java.util.Arrays;
|
|
|
|
|
+import java.util.Date;
|
|
|
|
|
+import java.util.HashMap;
|
|
|
|
|
+import java.util.HashSet;
|
|
|
|
|
+import java.util.List;
|
|
|
|
|
+import java.util.Map;
|
|
|
|
|
+import java.util.Set;
|
|
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 内部人力资源市场-三类人员记录生成-审批通过
|
|
* 内部人力资源市场-三类人员记录生成-审批通过
|
|
@@ -16,12 +47,151 @@ import nckd.jxccl.base.common.constant.FormConstant;
|
|
|
*/
|
|
*/
|
|
|
public class IntJobPostAuditedOpPlugin extends AbstractOperationServicePlugIn implements Plugin {
|
|
public class IntJobPostAuditedOpPlugin extends AbstractOperationServicePlugIn implements Plugin {
|
|
|
|
|
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void onAddValidators(AddValidatorsEventArgs e) {
|
|
|
|
|
+ e.addValidator(new AbstractValidator(){
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void validate() {
|
|
|
|
|
+ List<Long> personIds = new ArrayList<>();
|
|
|
|
|
+ for (ExtendedDataEntity rowDataEntity : getDataEntities()) {
|
|
|
|
|
+ DynamicObject data = rowDataEntity.getDataEntity();
|
|
|
|
|
+ DynamicObject person = data.getDynamicObject(PositionStructureConstant.NCKD_PERSON);
|
|
|
|
|
+ if(person == null){
|
|
|
|
|
+ this.addFatalErrorMessage(rowDataEntity,"请选择人员");
|
|
|
|
|
+ }else{
|
|
|
|
|
+ long personId = person.getLong(FormConstant.ID_KEY);
|
|
|
|
|
+ personIds.add(personId);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ Map<Long, DynamicObject> empPosOrgRelMap = EmpPosOrgRelHelper.queryEmpPosOrgRelByEmployeesMap(personIds);
|
|
|
|
|
+ for (ExtendedDataEntity rowDataEntity : getDataEntities()) {
|
|
|
|
|
+ DynamicObject data = rowDataEntity.getDataEntity();
|
|
|
|
|
+ DynamicObject person = data.getDynamicObject(PositionStructureConstant.NCKD_PERSON);
|
|
|
|
|
+ if(person != null){
|
|
|
|
|
+ long personId = person.getLong(FormConstant.ID_KEY);
|
|
|
|
|
+ if(empPosOrgRelMap.get(personId) == null){
|
|
|
|
|
+ this.addFatalErrorMessage(rowDataEntity,StrFormatter.format("人员【{}】没有在岗状态的任职经历",person.getString(FormConstant.NAME_KEY)));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
@Override
|
|
@Override
|
|
|
public void beginOperationTransaction(BeginOperationTransactionArgs e) {
|
|
public void beginOperationTransaction(BeginOperationTransactionArgs e) {
|
|
|
|
|
|
|
|
|
|
+ List<Long> personIds = new ArrayList<>();
|
|
|
|
|
+ List<Long> entityIds = new ArrayList<>();
|
|
|
|
|
+ for (DynamicObject dataEntity : e.getDataEntities()) {
|
|
|
|
|
+ DynamicObjectCollection entryEntity = dataEntity.getDynamicObjectCollection(FormConstant.NCKD_ENTRYENTITY);
|
|
|
|
|
+ for (DynamicObject entry : entryEntity) {
|
|
|
|
|
+ boolean isEnter = entry.getBoolean(IntJobPostConstant.NCKD_ISENTER);
|
|
|
|
|
+ if(isEnter){
|
|
|
|
|
+ personIds.add(entry.getLong(IntJobPostConstant.NCKD_PERSON));
|
|
|
|
|
+ }
|
|
|
|
|
+ entityIds.add(entry.getLong(IntJobPostConstant.ID_KEY));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ Map<Long, DynamicObject> empPosOrgRelMap = EmpPosOrgRelHelper.queryEmpPosOrgRelByEmployeesMap(personIds);
|
|
|
|
|
+
|
|
|
|
|
+ // --- A. 处理旧记录 ---
|
|
|
|
|
+ // 1. 查询该员工最近的一条记录(排除当前单据产生的记录,按创建时间倒序取第一条)
|
|
|
|
|
+ long currUserId = RequestContext.get().getCurrUserId();
|
|
|
|
|
+ List<DynamicObject> savedRecords = new ArrayList<>();
|
|
|
|
|
+ //由于轨迹需要关联本次新增的记录,需要等记录保存成功后再set内部人力资源市场记录。 以分录id作为key,记录待新增的轨迹。
|
|
|
|
|
+ Map<Long, DynamicObject> savedLocusMap = new HashMap<>();
|
|
|
|
|
+ List<DynamicObject> savedLocus = new ArrayList<>();
|
|
|
|
|
+ Map<Long, DynamicObject> latestRecordMap = getLatestRecordIdsByPersons(personIds, entityIds);
|
|
|
|
|
+ Map<Long, DynamicObject> latestLocusMap = findLatestLocusByPerson(personIds);
|
|
|
for (DynamicObject dataEntity : e.getDataEntities()) {
|
|
for (DynamicObject dataEntity : e.getDataEntities()) {
|
|
|
- DynamicObjectCollection dynamicObjectCollection = dataEntity.getDynamicObjectCollection(FormConstant.NCKD_ENTRYENTITY);
|
|
|
|
|
|
|
+ Date auditDate = dataEntity.getDate(IntJobPostConstant.AUDIT_DATE_KEY);
|
|
|
|
|
+ long personId = dataEntity.getLong(String.join(".", IntJobPostConstant.NCKD_PERSON, IntJobPostConstant.ID_KEY));
|
|
|
|
|
+ String talentType = dataEntity.getString(IntJobPostConstant.NCKD_TALENTTYPE);
|
|
|
|
|
+ TalentTypeEnum talentTypeEnum = TalentTypeEnum.getByCode(talentType);
|
|
|
|
|
+ DynamicObjectCollection entryEntity = dataEntity.getDynamicObjectCollection(FormConstant.NCKD_ENTRYENTITY);
|
|
|
|
|
+
|
|
|
|
|
+ for (DynamicObject entry : entryEntity) {
|
|
|
|
|
+ long id = entry.getLong(IntJobPostConstant.ID_KEY);
|
|
|
|
|
+ boolean isEnter = entry.getBoolean(IntJobPostConstant.NCKD_ISENTER);
|
|
|
|
|
+ if(isEnter){
|
|
|
|
|
+ DynamicObject latestRecord = latestRecordMap.get(personId);
|
|
|
|
|
+ if(latestRecord != null) {
|
|
|
|
|
+ // 2. 备份旧值
|
|
|
|
|
+ latestRecord.set(IntJobPostConstant.NCKD_OLDTOFOURDATE, latestRecord.get(IntJobPostConstant.NCKD_TOFOURDATE));
|
|
|
|
|
+ latestRecord.set(IntJobPostConstant.NCKD_OLDSTATE, latestRecord.get(IntJobPostConstant.NCKD_STATE));
|
|
|
|
|
+ //退出市场时间
|
|
|
|
|
+ latestRecord.set(IntJobPostConstant.NCKD_TOFOURDATE, auditDate);
|
|
|
|
|
+ //标记上一条为退出市场
|
|
|
|
|
+ latestRecord.set(IntJobPostConstant.NCKD_STATE, "4");
|
|
|
|
|
+ latestRecord.set(IntJobPostConstant.NCKD_ISCURRENTNEWEST, Boolean.FALSE);
|
|
|
|
|
+ latestRecord.set(IntJobPostConstant.NCKD_BACKUP, StrFormatter.format("以【{}】身份新进入市场,退出原市场。",talentTypeEnum.getName()));
|
|
|
|
|
+ savedRecords.add(latestRecord);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // --- B. 插入新记录 ---
|
|
|
|
|
+ DynamicObject newRecord = EntityHelper.newEntity(IntJobPostConstant.INTJOBPOSTRECORD_ENTITYID);
|
|
|
|
|
+ DynamicObject empPosOrgRel = empPosOrgRelMap.get(personId);
|
|
|
|
|
+ newRecord.set(IntJobPostConstant.HRPI_EMPPOSORGREL, empPosOrgRel);
|
|
|
|
|
+ newRecord.set(IntJobPostConstant.NCKD_ADMINORG,empPosOrgRel.get(IntJobPostConstant.ADMINORG));
|
|
|
|
|
+ newRecord.set(IntJobPostConstant.NCKD_ISCURRENTNEWEST, Boolean.TRUE);
|
|
|
|
|
+ //初始状态:进入市场
|
|
|
|
|
+ newRecord.set(IntJobPostConstant.NCKD_STATE,"1");
|
|
|
|
|
+ newRecord.set(IntJobPostConstant.NCKD_TALENTTYPE,dataEntity.get(IntJobPostConstant.NCKD_TALENTTYPE));
|
|
|
|
|
+ newRecord.set(IntJobPostConstant.NCKD_BEGINDATE,dataEntity.get(IntJobPostConstant.NCKD_BIZDAY));
|
|
|
|
|
+ newRecord.set(IntJobPostConstant.NCKD_YEAR,dataEntity.get(IntJobPostConstant.NCKD_YEAR));
|
|
|
|
|
+ //分录
|
|
|
|
|
+ newRecord.set(IntJobPostConstant.NCKD_INTJOBPOSTENTRY,latestRecord);
|
|
|
|
|
+ newRecord.set(IntJobPostConstant.NCKD_APPRAISALRESULT,entry.get(IntJobPostConstant.NCKD_APPRAISALRESULT));
|
|
|
|
|
+ newRecord.set(IntJobPostConstant.NCKD_BEFORELAST,entry.get(IntJobPostConstant.NCKD_BEFORELAST));
|
|
|
|
|
+ newRecord.set(FormConstant.CREATOR_KEY,currUserId);
|
|
|
|
|
+ if ("A".equals(dataEntity.getString(IntJobPostConstant.NCKD_TALENTTYPE))) {
|
|
|
|
|
+ //优秀员工-预计退出时间
|
|
|
|
|
+ Date date = DateUtil.addYears(auditDate, 1);
|
|
|
|
|
+ newRecord.set(IntJobPostConstant.NCKD_PREDICTTOFOURDATE, date);
|
|
|
|
|
+ }
|
|
|
|
|
+ savedRecords.add(newRecord);
|
|
|
|
|
+
|
|
|
|
|
+ // --- C. 处理轨迹 (Locus) ---
|
|
|
|
|
+ // 1. 查询最近的轨迹
|
|
|
|
|
+ DynamicObject latestLocus = latestLocusMap.get(personId);
|
|
|
|
|
+ if(latestLocus != null){
|
|
|
|
|
+ latestLocus.set(IntJobPostConstant.NCKD_OLDENDDAY, latestLocus.get(IntJobPostConstant.ENDDATE));
|
|
|
|
|
+ latestLocus.set(IntJobPostConstant.ENDDATE, auditDate);
|
|
|
|
|
+ latestLocus.set(IntJobPostConstant.NCKD_ISCURRENTNEWEST, Boolean.FALSE);
|
|
|
|
|
+ savedLocus.add(latestLocus);
|
|
|
|
|
+ }
|
|
|
|
|
+ // 2. 插入新轨迹
|
|
|
|
|
+ DynamicObject newLocus = EntityHelper.newEntity(IntJobPostConstant.INTJOBPOSTLOCUS_ENTITYID);
|
|
|
|
|
+ newLocus.set(IntJobPostConstant.HRPI_EMPPOSORGREL, empPosOrgRel);
|
|
|
|
|
+ newLocus.set(IntJobPostConstant.NCKD_ADMINORG,empPosOrgRel.get(IntJobPostConstant.ADMINORG));
|
|
|
|
|
+ newLocus.set(IntJobPostConstant.NCKD_ISCURRENTNEWEST, Boolean.TRUE);
|
|
|
|
|
+ newLocus.set(IntJobPostConstant.NCKD_INTJOBPOSTRECORD, newRecord);
|
|
|
|
|
+ newLocus.set(IntJobPostConstant.NCKD_STARTDATE, dataEntity.get(IntJobPostConstant.NCKD_BIZDAY));
|
|
|
|
|
+ newLocus.set(IntJobPostConstant.NCKD_TALENTTYPE, dataEntity.get(IntJobPostConstant.NCKD_TALENTTYPE));
|
|
|
|
|
+ newLocus.set(IntJobPostConstant.NCKD_STATE, "1");
|
|
|
|
|
+ newLocus.set(FormConstant.CREATOR_KEY,currUserId);
|
|
|
|
|
+ savedLocusMap.put(id, newLocus);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if(!savedRecords.isEmpty()){
|
|
|
|
|
+ OperationResult operationResult = SaveServiceHelper.saveOperate(IntJobPostConstant.INTJOBPOSTRECORD_ENTITYID, savedRecords.toArray(new DynamicObject[0]), OperateOption.create());
|
|
|
|
|
+ if(operationResult.isSuccess()){
|
|
|
|
|
+ //新增实体
|
|
|
|
|
+// OperationResult operationResult = SaveServiceHelper.saveOperate(IntJobPostConstant.INTJOBPOSTLOCUS_ENTITYID, savedRecords.toArray(new DynamicObject[0]), OperateOption.create());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ // --- A. 处理旧记录 ---
|
|
|
|
|
+ // 1. 查询该员工最近的一条记录(排除当前单据产生的记录,按创建时间倒序取第一条)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
//1、阶段1:备份原有记录
|
|
//1、阶段1:备份原有记录
|
|
|
// 条件:单据中要进入市场(CFIsenter=1)的员工 + 他们最新的记录 + 记录来源不是当前单据
|
|
// 条件:单据中要进入市场(CFIsenter=1)的员工 + 他们最新的记录 + 记录来源不是当前单据
|
|
|
//目的:为反审批时恢复数据做准备
|
|
//目的:为反审批时恢复数据做准备
|
|
@@ -37,7 +207,69 @@ public class IntJobPostAuditedOpPlugin extends AbstractOperationServicePlugIn im
|
|
|
//A类员工:有预计退出时间(1年后)
|
|
//A类员工:有预计退出时间(1年后)
|
|
|
//非A类员工:预计退出时间为null
|
|
//非A类员工:预计退出时间为null
|
|
|
|
|
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取每个人员最新一条记录
|
|
|
|
|
+ * @param personIds 人员ID
|
|
|
|
|
+ * @param entityIds 分录ID
|
|
|
|
|
+ * @return: java.util.Map<java.lang.Long, java.util.List < kd.bos.dataentity.entity.DynamicObject>>
|
|
|
|
|
+ * @author W.Y.C
|
|
|
|
|
+ * @date: 2026/01/13 15:56
|
|
|
|
|
+ */
|
|
|
|
|
+ public Map<Long, DynamicObject> getLatestRecordIdsByPersons(List<Long> personIds,List<Long> entityIds) {
|
|
|
|
|
+ QueryFieldBuilder intJobPostRecord = QueryFieldBuilder.create().add(IntJobPostConstant.ID_KEY)
|
|
|
|
|
+ .add(FormConstant.NCKD_EMPPOSORGREL, FormConstant.EMPLOYEE_KEY,FormConstant.ID_KEY)
|
|
|
|
|
+ .add(IntJobPostConstant.NCKD_ISCURRENTNEWEST)
|
|
|
|
|
+ .orderDesc(IntJobPostConstant.CREATE_TIME_KEY);
|
|
|
|
|
+ QFilter filter = new QFilter(String.join(".",FormConstant.NCKD_EMPPOSORGREL, FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY), QCP.in, personIds)
|
|
|
|
|
+ .and(IntJobPostConstant.NCKD_INTJOBPOSTENTRY,QCP.not_in,entityIds);
|
|
|
|
|
+ DynamicObjectCollection records = QueryServiceHelper.query(IntJobPostConstant.INTJOBPOSTRECORD_ENTITYID, intJobPostRecord.buildSelect(), new QFilter[]{filter});
|
|
|
|
|
+ Set<Long> uniquePersonIds = new HashSet<>();
|
|
|
|
|
+ List<Long> result = new ArrayList<>();
|
|
|
|
|
+ for (DynamicObject record : records) {
|
|
|
|
|
+ Long personId = record.getLong(String.join(".",FormConstant.NCKD_EMPPOSORGREL, FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY));
|
|
|
|
|
+ if (uniquePersonIds.add(personId)) { // 如果是新的personId,添加到结果中
|
|
|
|
|
+ result.add(record.getLong(IntJobPostConstant.ID_KEY));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ MainEntityType intJobPostRecordEntityType = EntityMetadataCache.getDataEntityType(IntJobPostConstant.INTJOBPOSTRECORD_ENTITYID);
|
|
|
|
|
+ DynamicObject[] load = BusinessDataServiceHelper.load(result.toArray(new Long[0]), intJobPostRecordEntityType);
|
|
|
|
|
+ return Arrays.stream(load)
|
|
|
|
|
+ .collect(Collectors.toMap(
|
|
|
|
|
+ obj -> obj.getLong(String.join(".", FormConstant.NCKD_EMPPOSORGREL, FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY)),
|
|
|
|
|
+ obj -> obj
|
|
|
|
|
+ ));
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 查询最近的轨迹
|
|
|
|
|
+ * @param personIds 人员ID
|
|
|
|
|
+ * @return: java.util.Map<java.lang.Long, java.util.List < kd.bos.dataentity.entity.DynamicObject>>
|
|
|
|
|
+ * @author W.Y.C
|
|
|
|
|
+ * @date: 2026/01/13 15:56
|
|
|
|
|
+ */
|
|
|
|
|
+ public Map<Long, DynamicObject> findLatestLocusByPerson(List<Long> personIds) {
|
|
|
|
|
+ QueryFieldBuilder intJobPostLocus = QueryFieldBuilder.create().add(IntJobPostConstant.ID_KEY)
|
|
|
|
|
+ .add(FormConstant.NCKD_EMPPOSORGREL, FormConstant.EMPLOYEE_KEY,FormConstant.ID_KEY)
|
|
|
|
|
+ .add(IntJobPostConstant.NCKD_ISCURRENTNEWEST)
|
|
|
|
|
+ .orderDesc(IntJobPostConstant.CREATE_TIME_KEY);
|
|
|
|
|
+ QFilter filter = new QFilter(String.join(".",FormConstant.NCKD_EMPPOSORGREL, FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY), QCP.in, personIds);
|
|
|
|
|
+ DynamicObjectCollection records = QueryServiceHelper.query(IntJobPostConstant.INTJOBPOSTLOCUS_ENTITYID, intJobPostLocus.buildSelect(), new QFilter[]{filter});
|
|
|
|
|
+ Set<Long> uniquePersonIds = new HashSet<>();
|
|
|
|
|
+ List<Long> result = new ArrayList<>();
|
|
|
|
|
+ for (DynamicObject record : records) {
|
|
|
|
|
+ Long personId = record.getLong(String.join(".",FormConstant.NCKD_EMPPOSORGREL, FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY));
|
|
|
|
|
+ if (uniquePersonIds.add(personId)) { // 如果是新的personId,添加到结果中
|
|
|
|
|
+ result.add(record.getLong(IntJobPostConstant.ID_KEY));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ MainEntityType intJobPostLocusEntityType = EntityMetadataCache.getDataEntityType(IntJobPostConstant.INTJOBPOSTLOCUS_ENTITYID);
|
|
|
|
|
+ DynamicObject[] load = BusinessDataServiceHelper.load(result.toArray(new Long[0]), intJobPostLocusEntityType);
|
|
|
|
|
+ return Arrays.stream(load)
|
|
|
|
|
+ .collect(Collectors.toMap(
|
|
|
|
|
+ obj -> obj.getLong(String.join(".",FormConstant.NCKD_EMPPOSORGREL, FormConstant.EMPLOYEE_KEY, FormConstant.ID_KEY)),
|
|
|
|
|
+ obj -> obj
|
|
|
|
|
+ ));
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|