commit 1548ad44cd82576963ce8b26fe3a9e975431ba9b Author: hezq Date: Fri Dec 15 10:15:19 2023 +0800 Signed-off-by: hezq diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..eca7bdb --- /dev/null +++ b/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000..24d35fc --- /dev/null +++ b/.project @@ -0,0 +1,28 @@ + + + com.langtech.plm.performancemanagement + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..9f6ece8 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF new file mode 100644 index 0000000..7afe5d5 --- /dev/null +++ b/META-INF/MANIFEST.MF @@ -0,0 +1,21 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Performancemanagement +Bundle-SymbolicName: com.langtech.plm.performancemanagement;singleton:=true +Bundle-Version: 1.0.0 +Bundle-Activator: com.langtech.plm.performancemanagement.Activator +Bundle-Vendor: LANGTECH +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + com.teamcenter.rac.aifrcp;bundle-version="13000.1.0", + com.teamcenter.rac.tcapps;bundle-version="13000.1.0", + com.teamcenter.rac.ui;bundle-version="13000.1.0", + com.teamcenter.rac.ui.views;bundle-version="13000.1.0", + com.teamcenter.rac.util;bundle-version="13000.1.0", + com.teamcenter.rac.common;bundle-version="13000.1.0", + com.teamcenter.rac.kernel;bundle-version="13000.1.0", + com.teamcenter.rac.external;bundle-version="13000.1.0", + org.apache.poi.39;bundle-version="3.9.0" +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Automatic-Module-Name: com.langtech.plm.performancemanagement +Bundle-ActivationPolicy: lazy diff --git a/bin/com/langtech/plm/performancemanagement/Activator.class b/bin/com/langtech/plm/performancemanagement/Activator.class new file mode 100644 index 0000000..ea46575 Binary files /dev/null and b/bin/com/langtech/plm/performancemanagement/Activator.class differ diff --git a/bin/com/langtech/plm/performancemanagement/handlers/TaskFolderMatchingHandler.class b/bin/com/langtech/plm/performancemanagement/handlers/TaskFolderMatchingHandler.class new file mode 100644 index 0000000..994f3bb Binary files /dev/null and b/bin/com/langtech/plm/performancemanagement/handlers/TaskFolderMatchingHandler.class differ diff --git a/build.properties b/build.properties new file mode 100644 index 0000000..0d3d3a7 --- /dev/null +++ b/build.properties @@ -0,0 +1,6 @@ +source.. = src/ +output.. = bin/ +bin.includes = plugin.xml,\ + META-INF/,\ + .,\ + icons/ diff --git a/icons/sample.png b/icons/sample.png new file mode 100644 index 0000000..02c4b79 Binary files /dev/null and b/icons/sample.png differ diff --git a/icons/sample@2x.png b/icons/sample@2x.png new file mode 100644 index 0000000..c1224d1 Binary files /dev/null and b/icons/sample@2x.png differ diff --git a/plugin.xml b/plugin.xml new file mode 100644 index 0000000..5a25493 --- /dev/null +++ b/plugin.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com/langtech/plm/performancemanagement/Activator.java b/src/com/langtech/plm/performancemanagement/Activator.java new file mode 100644 index 0000000..67636fc --- /dev/null +++ b/src/com/langtech/plm/performancemanagement/Activator.java @@ -0,0 +1,44 @@ +package com.langtech.plm.performancemanagement; + +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class Activator extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "com.langtech.plm.performancemanagement"; //$NON-NLS-1$ + + // The shared instance + private static Activator plugin; + + /** + * The constructor + */ + public Activator() { + } + + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + @Override + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static Activator getDefault() { + return plugin; + } + +} diff --git a/src/com/langtech/plm/performancemanagement/handlers/TaskFolderMatchingHandler.java b/src/com/langtech/plm/performancemanagement/handlers/TaskFolderMatchingHandler.java new file mode 100644 index 0000000..212380b --- /dev/null +++ b/src/com/langtech/plm/performancemanagement/handlers/TaskFolderMatchingHandler.java @@ -0,0 +1,426 @@ +package com.langtech.plm.performancemanagement.handlers; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.poi.xssf.usermodel.XSSFRow; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; + +import com.teamcenter.rac.aif.AbstractAIFApplication; +import com.teamcenter.rac.aifrcp.AIFUtility; +import com.teamcenter.rac.kernel.TCComponent; +import com.teamcenter.rac.kernel.TCComponentDataset; +import com.teamcenter.rac.kernel.TCComponentTcFile; +import com.teamcenter.rac.kernel.TCException; +import com.teamcenter.rac.kernel.TCProperty; +import com.teamcenter.rac.kernel.TCSession; +import com.teamcenter.rac.util.FileUtility; +import com.teamcenter.rac.util.MessageBox; + +/** + * 功能描述:选中项目文件夹,导出绩效报表 数据库表维护任务要求表 + * + * + */ +public class TaskFolderMatchingHandler extends AbstractHandler { + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + AbstractAIFApplication app = AIFUtility.getCurrentApplication(); + TCSession session = (TCSession) app.getSession(); + TCComponent target = null; + target = (TCComponent) app.getTargetComponent(); + // 选中项目类型,否则报错 + String type = target.getType(); + if (type.equals("LD6_CusProdFolder") || type.equals("客户成品文件夹")) { + // TODO 换成数据库方式维护 +// TCComponent[] workRequest = null; +// try { +// workRequest = session.search("常规...", new String[] { "名称", "类型" }, new String[] { "任务要求表", "xxxx" }); +// } catch (Exception e) { +// e.printStackTrace(); +// MessageBox.post("查询异常", "", MessageBox.INFORMATION); +// } +// if (workRequest.length == 0) { +// MessageBox.post("系统中没有任务要求表,请导入后重试", "", MessageBox.INFORMATION); +// } else if (workRequest.length > 1) { +// +// MessageBox.post("系统中存在多个任务要求表", "", MessageBox.INFORMATION); +// } + // 检查报表模板是否存在(首选项ld_billboards_uid) + String ldBillboardsUid = session.getPreferenceService().getStringValue("ld_billboards_uid"); + if (!getMessageboxInfo(ldBillboardsUid, "ld_billboards_uid")) { + return null; + } + TCComponent billboard = null; + try { + billboard = session.stringToComponent(ldBillboardsUid); + } catch (TCException e) { + e.printStackTrace(); + MessageBox.post("请通知管理员检查首选项ld_billboards_uid是否配置", "", MessageBox.INFORMATION); + return null; + } + if (billboard == null) { + MessageBox.post("请通知管理员检查首选项ld_billboards_uid是否配置", "", MessageBox.INFORMATION); + return null; + } + // 获取岗位系数 难度系数 紧张度系数 要求完成时间公式的首选项 + String[] ldPostCoefficient = session.getPreferenceService().getStringValues("ld_postCoefficient"); + String[] ldTaskNature = session.getPreferenceService().getStringValues("ld_taskNature");// 难度系数对应的难度系数? + String[] ldUrgency = session.getPreferenceService().getStringValues("ld_urgency"); + // 超时配置 + String[] ldOvertime = session.getPreferenceService().getStringValues("ld_overtime");// 严重等级:天数区间(整数)[0,0]:扣分系数;一般:(0,1]:1/5;严重:(1,2]:1/3;超严重:(2,3]:1/2 + // 流程信息配置成 任务包名称=流程名称:审核节点名称 + String[] ldProcessReview = session.getPreferenceService().getStringValues("ld_processReview"); + if (!getMessageInfo(ldPostCoefficient, "ld_processReview")) { + return false; + } + if (!getMessageInfo(ldTaskNature, "ld_taskNature")) { + return false; + } + if (!getMessageInfo(ldUrgency, "ld_urgency")) { + return false; + } + if (!getMessageInfo(ldProcessReview, "ld_processReview")) { + return false; + } + if (!getMessageInfo(ldOvertime, "ld_overtime")) { + return false; + } + Map postCoefficientMap = new HashMap();// 岗位,岗位系数 + Map taskNatureMap = new HashMap();// 任务性质,任务系数 + Map urgencyMap = new HashMap();// 紧急程度,紧急程度系数 + Map processReviewMap = new HashMap();// 流程名称,指派的节点名称 + Map severityIntervalMap = new HashMap();// 键:天数区间;值:扣分系数 + for (int i = 0; i < ldPostCoefficient.length; i++) { + String value = ldPostCoefficient[i]; + postCoefficientMap.put(value.split("=")[0], value.split("=")[0]); + } + for (int i = 0; i < ldTaskNature.length; i++) { + String value = ldTaskNature[i]; + taskNatureMap.put(value.split("=")[0], value.split("=")[0]); + } + for (int i = 0; i < ldUrgency.length; i++) { + String value = ldUrgency[i]; + urgencyMap.put(value.split("=")[0], value.split("=")[0]); + } + for (int i = 0; i < ldProcessReview.length; i++) { + String value = ldProcessReview[i]; + processReviewMap.put(value.split("=")[0], value.split("=")[0]); + } + for (int i = 0; i < ldOvertime.length; i++) { + String dayInterval = ldOvertime[i].split(":")[1]; + String severity = ldOvertime[i].split(":")[0]; + String point = ldOvertime[i].split(":")[2]; + severityIntervalMap.put(dayInterval, point); + } + // 下载报表命名引用和任务要求表的命名引用 + String billboardAddress = downLoadFile(billboard); + // TODO 获取工艺结束时间 + String targetName = ""; + try { + targetName = target.getProperty("object_name"); + } catch (TCException e) { + e.printStackTrace(); + } + Date processEndTime = getEndTime(targetName); + if (processEndTime == null) { + MessageBox.post("请检查是否设置或者导入相关客户成品文件夹名称和工艺程序结束时间", "", MessageBox.INFORMATION); + return null; + } + // 获取任务包的流程 组织 + // 先遍历底层结构 + String path = ""; + path = targetName; + String link = "/"; + List taskPathList = new ArrayList(); + Map folderMap = new HashMap();// 键:文件夹层级结构 值:文件夹对象 + getAllFolderPath(target, path, link, taskPathList, folderMap); + // 获取首选项Connor_JXFolder + Map> packageMap = new HashMap>(); + String connorJXFolderPreference = "Connor_JXFolder"; + String[] ConnorJXFolders = session.getPreferenceService().getStringValues(connorJXFolderPreference); + if (getMessageInfo(ConnorJXFolders, connorJXFolderPreference)) { + return false; + } + for (int i = 0; i < ConnorJXFolders.length; i++) { + String[] values = ConnorJXFolders[i].split("="); + String[] folders = values[1].split(";"); + List folderList = Arrays.asList(folders); + packageMap.put(values[0], folderList); + } + // 读取报表信息 + File file = new File(billboardAddress); + XSSFWorkbook workbook = null; + try { + FileInputStream fis = new FileInputStream(file); + workbook = new XSSFWorkbook(fis); + } catch (IOException e) { + e.printStackTrace(); + } + XSSFSheet sheet = workbook.getSheet("新品任务分配表"); + int rowNum = sheet.getLastRowNum(); + for (int i = 1; i < rowNum; i++) { + XSSFRow row = sheet.getRow(i); + String cellBValue = row.getCell(1).getStringCellValue().trim();// 任务包名 + List folderList = packageMap.get(cellBValue); + if (folderList != null && folderList.size() > 0) { + String folderPath = folderList.get(0); + TCComponent folder = folderMap.get(folderPath); + String[] properties = new String[] { "object_desc", "任务性质", "难易程度", "紧急程度", "额定业务工时(小时)", + "fnd0AllWorkflows" }; + TCProperty[] tcproperties = null; + try { + tcproperties = folder.getTCProperties(properties); + } catch (TCException e) { + e.printStackTrace(); + } + // 新品任务要求描述 + String objectDesc = tcproperties[0].getStringValue(); + String taskNature = tcproperties[1].getDisplayValue(); + String difficulty = tcproperties[2].getDisplayValue(); + String urgency = tcproperties[3].getDisplayValue(); + String ratedBusinessHours = tcproperties[4].getStringValue(); + String taskNatureCoefficient = taskNatureMap.get(difficulty); + String urgencyCoefficient = urgencyMap.get(urgency); + String postCoefficient = "";// 待定 + // 获取流程信息 + String processReview = processReviewMap.get(cellBValue); + String processName = processReview.split(":")[0]; + String reviewName = processReview.split(":")[1]; + String assignee = "";// 被指派者fnd0Assignee,如果流程任务没有经过转发,被指派者即流程接受者;等同于责任方 + String assigner = "";// 指派者fnd0Assigner,如果流程任务没有经过转发,这个属性没有值,可以取被指派者 + String assigneeGroup = "";// 被指派者的组 + String status = "";// 流程状态 + String startData = "";// 流程开始时间 + String endDateValue = "";// 流程结束时间 + String actualHours = "";// 实际业务工时 + String deductPoints = "";// 超时扣分 + TCComponent[] workflows = tcproperties[5].getReferenceValueArray(); + for (int j = 0; j < workflows.length; j++) { + TCComponent workflow = workflows[j]; + try { + String[] workflowProperties = new String[] { "object_name", "fnd0ActuatedInteractiveTsks", + "fnd0EndDate", "fnd0StartDate", "fnd0Status" }; + TCProperty[] workflowTcProperties = workflow.getTCProperties(workflowProperties); + String workflowName = workflowTcProperties[0].getDisplayValue(); + TCComponent[] reviews = workflowTcProperties[1].getReferenceValueArray(); + if (workflowName.equals(processName)) { + for (int k = 0; k < reviews.length; k++) { + TCComponent review = reviews[k]; + String typeName = review.getType(); + if (typeName.equals("签发")) {// 任务:fnd0AliasTaskName;执行者:fnd0Performer + // fnd0AssigneeGroupRole owning_group + String[] reviewProperties = new String[] { "fnd0AliasTaskName", "fnd0Performer", + "owning_group", "fnd0Assigner", "fnd0Assignee" }; + TCProperty[] reviewTcProperties = review.getTCProperties(reviewProperties); + String aliasTaskName = reviewTcProperties[0].getDisplayValue(); + if (aliasTaskName.contains(":")) { + String reviewNodeName = aliasTaskName.split(":")[0]; + if (reviewNodeName.equals(reviewName)) { + assignee = reviewTcProperties[4].getDisplayValue(); + assigneeGroup = reviewTcProperties[2].getDisplayableValue(); + TCProperty assigneeProperty = reviewTcProperties[3]; + if (assigneeProperty.getDisplayValue().length() > 0) { + assigner = assigneeProperty.getDisplayValue(); + } else { + assigner = assignee; + } + } + } + status = workflowTcProperties[4].getDisplayValue().equals("已完成") ? "已完成" + : "未完成"; + endDateValue = workflowTcProperties[2].getDisplayValue(); + Date startDate = workflowTcProperties[2].getDateValue(); + Date endDate = workflowTcProperties[3].getDateValue(); + actualHours = "" + (endDate.getTime() - startDate.getTime()) / 1000 / 3600; + float point = (float) 0.0; + if (status.equals("已完成")) { + ZoneId zoneId = ZoneId.systemDefault(); + Instant instantEnd = endDate.toInstant(); + Instant instantProcessEnd = processEndTime.toInstant(); + LocalDate localEndDate = instantEnd.atZone(zoneId).toLocalDate(); + LocalDate localProcessEndDate = instantProcessEnd.atZone(zoneId) + .toLocalDate(); + long diff = localEndDate.toEpochDay() - localProcessEndDate.toEpochDay(); + String overtimeCoefficient = "";// 扣分系数 + postCoefficient = postCoefficientMap.get(assigneeGroup); + for (Map.Entry me : severityIntervalMap.entrySet()) { + String interval = me.getKey(); + String startDay = interval.split(",")[0]; + String endDay = interval.split(",")[1]; + boolean condition1 = false; + boolean condition2 = false; + if (startDay.startsWith("[")) { + condition1 = diff >= (Integer + .valueOf(startDay.substring(1, startDay.length() - 1))) + ? true + : false; + } else if (startDay.startsWith("(")) { + condition1 = diff > (Integer + .valueOf(startDay.substring(1, startDay.length() - 1))) + ? true + : false; + } + if (endDay.endsWith("]")) { + condition2 = diff <= (Integer + .valueOf(endDay.substring(0, endDay.length() - 2))) ? true + : false; + } else if (startDay.startsWith(")")) { + condition2 = diff < (Integer + .valueOf(endDay.substring(0, endDay.length() - 2))) ? true + : false; + } + if (condition1 == true && condition2 == true) { + overtimeCoefficient = me.getValue(); + } else { + continue; + } + } + if (!overtimeCoefficient.equals("")) { + point = 1 * Float.valueOf(overtimeCoefficient) + * Float.valueOf(taskNatureCoefficient) + * Float.valueOf(urgencyCoefficient);// TODO 公式待定,尤其时任务性质和难度系数 + } + } + } + } + } + } catch (TCException e) { + e.printStackTrace(); + } + } + } else { + continue; + } + } + } else { + MessageBox.post("请选择客户成品文件夹", "", MessageBox.INFORMATION); + } + return null; + } + + /** + * 通过数据方式获取工艺结束时间 + */ + private Date getEndTime(String targetName) { + // TODO + return null; + } + + /** + * 检查首选项是否设置 + * + * @param preferenceValue 首选项值 + * @param preferenceName 首选项名称 + * @return 没有配置就返回false + */ + private boolean getMessageInfo(String[] preferenceValue, String preferenceName) { + if (preferenceValue == null || preferenceValue.length == 0) { + MessageBox.post("请通知管理员检查首选项" + preferenceName + "是否配置", "", MessageBox.INFORMATION); + return false; + } + return true; + } + + /** + * 检查首选项是否设置 + * + * @param preferenceValue 首选项值 + * @param preferenceName 首选项名称 + * @return 没有配置就返回false + */ + private boolean getMessageboxInfo(String preferenceValue, String preferenceName) { + if (preferenceValue == null || preferenceValue.length() == 0) { + MessageBox.post("请通知管理员检查首选项" + preferenceName + "是否配置", "", MessageBox.INFORMATION); + return false; + } + return true; + } + + /** + * 循环便利项目文件夹下的所有文件夹,并添加到集合和map中 + * + * @param target 文件夹 + * @param path 文件路径 + * @param link 连接符 + * @param taskPathList 任务包路径集合 + * @param folderMap 任务包路径,任务包对象 + * @return 下载的命名引用文件 + */ + private void getAllFolderPath(TCComponent target, String path, String link, List taskPathList, + Map folderMap) { + try { + TCComponent[] contents = target.getRelatedComponents("contents"); + for (int i = 0; i < contents.length; i++) { + TCComponent content = contents[i]; + TCComponent[] childContents = content.getRelatedComponents("contents"); + path = path + link + content.getProperty("object_name"); + if (childContents.length > 0) { + getAllFolderPath(content, path, link, taskPathList, folderMap); + } else { + taskPathList.add(path); + folderMap.put(path, content); + } + } + } catch (TCException e) { + e.printStackTrace(); + } + } + + /** + * 下载文件 + * + * @param 数据集对象 + * @return 下载的命名引用文件 + */ + public String downLoadFile(TCComponent comp) { + if (comp == null) { + return ""; + } + String value = ""; + String tempPath = System.getenv("TEMP"); + if (tempPath == null) { + tempPath = ""; + } else if (!tempPath.endsWith("\\")) { + tempPath = tempPath + "\\"; + } + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); + try { + if (comp instanceof TCComponentDataset) { + TCComponentTcFile[] tcFiles = ((TCComponentDataset) comp).getTcFiles(); + File file = null; + System.out.println("tcFiles:" + tcFiles.length); + if (tcFiles != null && tcFiles.length != 0) { + file = tcFiles[0].getFmsFile(); + String fileName = file.getName(); + System.out.println("fileName:" + fileName); + String fileDix = fileName.substring(fileName.lastIndexOf("."), fileName.length()); + fileName = tempPath + sdf.format(new Date()) + fileDix; + File dirFile = new File(fileName); + FileUtility.copyFile(file, dirFile); + return fileName; + } + } + } catch (TCException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return value; + } +}