财务预警项目总结
前言
财务预警这个项目呢,从4月开始调研到8月底验收了。算是我的一个从调研,需求,SOW等文档编制到代码开发,上线支持,后期的功能优化,并扩展客户另外提出的需求,到用户手册,验收交付完全独立交付的项目。 这其中呢,我可能有很多的感慨。
如何准确定位核心需求,减少客户思维过度发散?
从固定好的需求,到后面的每一次的沟通,都会增加或者调整需求。其中很重要的一个因素就是你要去用专业的水平和意见去指导客户。不然客户的思维真的是非常的发散,他们总觉得这样也可以做吧,那样也可以做吧?其实有些是没有必要的,所以这种时候,就应该站出来去指引客户,这种情况应该这种逻辑,这样处理,提出来专业的观点,这样就能够降低很多不必要的思维发散沟通,可以很大的提高工作效率!还有一种呢,就是我使用了原因图的方式,让客户真正的看到以后做出来的是什么样的东西?给客户最直观的展示,也可以降低因为都是各自想象,看不到实物而过度的思维发散。
针对开发过程中的需求变更,又该如何应对呢?
如果是在开发构建之前进行的需求变更,那么这个成本还是比较小的,一旦在开发构建活动开始之后进行的任何需求变更,都会对你造成一定程度的影响!如果是较大的需求变更,甚至会导致你的这个构建要重新来!一些不影响整体构建开发的需求变更,还可以接受,能改的就要改,最多也就是在目前的基础进行扩展开发。涉及到客户的体验,满意度。谁让客户是上帝呢?
那么较大的需求变更,该怎么处理呢?此时,项目组内就需要有一个需求变更的流程。所谓的需求变更流程也就是,当客户提出需求变更时,先有人员进行探讨和目前的开发构建活动是否冲突?是否值得这样做?有什么最简单的满足变更的方案?针对需求变更需要投入多少人力成本等等,如果上面这几项都已经分析了,那么就拿着方案去和客户谈,较多情况下,当拿着清单告诉客户需要增加多少成本的时候,那么一些不切实际的想法变更就会被客户放弃了。
阶段交付,降低风险
按阶段进行交付,类似于敏捷开发。完整的功能模块做完以后,与客户进行交付验证,最大好处我觉得就是,船小好调头,有什么问题可以及时发现并处理,还能验证是否符合客户要求。防止最后开发完毕以后进行交付,与客户期望差异过大,造成项目损失流产。
项目简介
那么这个项目,其中一部分工作就是,将EAS系统基础月度财务报表数据按照制定的固定模板生成数据,然后将数据导出,着使用预警系统的一键导入功能,将月度数据导入到系统中,和年度维护的国资委对标值进行比对,使用预警规则判定算法自动判定企业的风险等级。最终使用扩展报表平台对数据进行分析,使用Mbos云之家开发平台开发企业自建轻应用预警分析轻应用,那么这个轻应用呢在之前的文章中已经介绍过。因为涉及到项目的商业机密,因此这里就简单的介绍下数据整理导入这块的内容。
那么数据整理部分呢,包括以下几个模块逻辑:
1. 文件选取弹框,供用户选择导入Excel数据文件;
3. 获取国资委对标值 并进行处理赋值
4. 自动判定风险等级算法
5. 数据遍历导入
6. 日志记录、操作提示
文件选取
从存储数据页面(RiskItemListUICTEx)工具栏中添加数据导入按钮,点击数据导入,进行弹框(即跳转到ExcelRiskItemImportUI),供用户选取文件,进行导入操作。
1 **RiskItemListUICTEx** 2 //ListUI 工具栏 数据导入按钮 弹出对话框 3 @Override 4 public void actionExcelImport_actionPerformed(ActionEvent e) throws Exception { 5 // TODO 数据导入按钮 调出按钮 6 super.actionExcelImport_actionPerformed(e); 7 UIContext context = new UIContext(); 8 IUIFactory uiFactory = UIFactory.createUIFactory("com.kingdee.eas.base.uiframe.client.UIModelDialogFactory"); 9 IUIWindow TempVouSelectDlg = uiFactory.create("com.kingdee.eas.custom.financialrisk.client.ExcelRiskItemImportUI", context); 10 TempVouSelectDlg.show(); 11 super.onShow(); 12 actionRefresh_actionPerformed(e); 13 14 }
弹框效果:
选择文件 按钮逻辑:调用文件选择器,限制文件类型只能为xlsx,xls。然后将最后选择的Excel文件的路径回写到路径框中。
1 @Override 2 public void actionBtnChoose_actionPerformed(ActionEvent e) throws Exception { 3 super.actionBtnChoose_actionPerformed(e); 4 5 // 添加文件格式筛选filter 6 VoucherFileFilter fileFilter = new VoucherFileFilter(); 7 String path = System.getProperty("easclient.root"); 8 String strFileExt = "xlsx,xls"; 9 String strFileDesc = "Excel File(*.xlsx),Excel File(*.xls)"; 10 KDFileChooser chooser = new KDFileChooser(new File(path)); 11 fileFilter.setFileFilter(chooser, strFileDesc, strFileExt); 12 chooser.setAcceptAllFileFilterUsed(false); 13 chooser.setDialogTitle("风险预警指标统计表Excel火箭发射基地"); 14 int returnVal = chooser.showOpenDialog(this); 15 if (returnVal != 0) { 16 logger.error("Method:actionBtnChoose_actionPerformed chooser don't open dialog!"); 17 return; 18 } 19 File tempfile = chooser.getSelectedFile(); 20 boolean bFileExist = tempfile.exists(); 21 if (!bFileExist) { 22 logger.error("Method:actionBtnChoose_actionPerformed file.exist Error!"); 23 throw new VoucherExpImpException( 24 VoucherExpImpException.FIEL_NOT_EXIST); 25 } 26 this.riskTxtPath.setText(tempfile.getPath()); 27 logger.info("Method:actionBtnChoose_actionPerformed choose file is ok!"); 28 }
数据导入
文件选择完毕后,点击确定按钮开始执行数据导入。其中呢,包括进度条、企业风险等级判定。
1 @Override 2 public void actionBtnSubmit_actionPerformed(ActionEvent e) throws Exception { 3 super.actionBtnSubmit_actionPerformed(e); 4 5 final String filePath = this.riskTxtPath.getText(); 6 if (filePath == null) { 7 MsgBox.showInfo("请选择导入文件!"); 8 return; 9 } 10 11 final MonitorInfo info = new MonitorInfo("数据正在飞往火星,咻~咻~咻!", null, this, 12 true); 13 14 SwingWorker worker = new SwingWorker() { 15 public Object construct() { 16 try { 17 return importData(filePath); 18 } catch (Throwable e) { 19 MsgBox.showInfo("导入数据出错,请联系管理员!"); 20 return e; 21 } 22 } 23 24 public void finished() { 25 try { 26 ThreadPool.destroyMonitor(info); 27 Thread.sleep(1000); 28 } catch (InterruptedException e1) { 29 e1.printStackTrace(); 30 } 31 32 try { 33 Object value = getValue(); 34 if (value instanceof Throwable) { 35 36 } else { 37 handUIException((Throwable) value); 38 } 39 } catch (Exception e) { 40 e.printStackTrace(); 41 } 42 } 43 }; 44 info.setWorker(worker); 45 ThreadPool.addActionThread(info); 46 ThreadPool.setBackgroundRunButtonEnabled(false); 47 // 关闭当前窗口 48 MsgBox.showInfo("您发射的数据已安全到达火星~~~咻~~咻~~"); 49 getUIWindow().close(); 50 }
1 /** 2 * 3 * <p> 4 * Title: importData 5 * </p> 6 * <p> 7 * Description: 8 * </p> 9 * Excel数据遍历导入 10 */ 11 private String importData(String filePath) { 12 StringBuffer message = new StringBuffer("导入EXCEL信息如下:"); 13 message.append("\n"); 14 Workbook workbook = null; 15 InputStream is = null; 16 try { 17 is = new FileInputStream(filePath); 18 if (filePath.endsWith(".xlsx")) { 19 workbook = new XSSFWorkbook(is); 20 } else { 21 workbook = new HSSFWorkbook(is); 22 } 23 } catch (FileNotFoundException e) { 24 e.printStackTrace(); 25 } catch (IOException e) { 26 e.printStackTrace(); 27 } 28 Sheet sheet = workbook.getSheetAt(0); 29 Row row = null; 30 int rowNum = sheet.getLastRowNum(); 31 // 获取日期 32 Row dateRow = sheet.getRow(0); 33 // 获取第三个单元格值 (eg:2016-08) 34 String dateStr = dateRow.getCell(2).getStringCellValue(); 35 String[] date = dateStr.split("-"); 36 String year = date[0]; 37 String month = date[1]; 38 39 String pid = getSasacIDByYear(year); 40 List<Map<String, Object>> list = getSasacEntryByPID(pid); 41 for (int i = 0; i < list.size(); i++) { 42 String name = (String) list.get(i).get("name"); 43 BigDecimal aver = (BigDecimal) list.get(i).get("average"); 44 Double average = aver.doubleValue(); 45 BigDecimal po = (BigDecimal) list.get(i).get("poor"); 46 Double poor = po.doubleValue(); 47 initVariable(name, average, poor); 48 } 49 50 // 获取表头字段信息 51 row = sheet.getRow(1); 52 Map<String, Integer> titleMap = new HashMap<String, Integer>(); 53 // 把表头信息以及列索引存入到map 中 54 // 区别:getPhysicalNumberOfCells:是获取不为空的列个数 getLastCellNum 55 // 是获取最后一个不为空的列是第几个 56 for (int j = 0; j < row.getPhysicalNumberOfCells(); j++) { 57 String columName = row.getCell(j).getStringCellValue(); 58 titleMap.put(columName, j); 59 } 60 IRiskItem remoteInstance = null; 61 try { 62 remoteInstance = RiskItemFactory.getRemoteInstance(); 63 } catch (BOSException e1) { 64 e1.printStackTrace(); 65 } 66 // 从表头的下一行开始读取数据 67 for (int i = 2; i <= rowNum; i++) { 68 row = sheet.getRow(i); 69 RiskItemInfo riskItemInfo = new RiskItemInfo(); 70 /* 71 * map 中存放预警指标数据,如若分母为0,构不成表达式,则指标数据置为 -9999.99 72 */ 73 Map<String, Double> map = new HashMap<String, Double>(); 74 String companyName = row.getCell(titleMap.get("公司")) 75 .getStringCellValue(); 76 double totalAssets = row.getCell(titleMap.get("资产总额")) 77 .getNumericCellValue(); 78 double totalLiabilites = row.getCell(titleMap.get("负债总额")) 79 .getNumericCellValue(); 80 map.put("资产负债率", totalLiabilites / totalAssets); 81 double trafficProfit = row.getCell(titleMap.get("营业利润")) 82 .getNumericCellValue(); 83 map.put("营业利润", trafficProfit); 84 double totalProfit = row.getCell(titleMap.get("利润总额")) 85 .getNumericCellValue(); 86 double interestExpense = row.getCell(titleMap.get("利息支出")) 87 .getNumericCellValue(); 88 if (interestExpense == 0) { 89 map.put("己获利息倍数", -9999.99); 90 } else { 91 map.put("己获利息倍数", (totalProfit + interestExpense) 92 / interestExpense); 93 } 94 double currentAssets = row.getCell(titleMap.get("流动资产")) 95 .getNumericCellValue(); 96 double currentLiabilities = row.getCell(titleMap.get("流动负债")) 97 .getNumericCellValue(); 98 if (currentLiabilities == 0) { 99 map.put("流动比率", -9999.99); 100 } else { 101 map.put("流动比率", currentAssets / currentLiabilities); 102 } 103 104 double accountReceivable = row.getCell(titleMap.get("应收账款")) 105 .getNumericCellValue(); 106 double stock = row.getCell(titleMap.get("存货")) 107 .getNumericCellValue(); 108 if (currentAssets == 0) { // 流动资产 109 map.put("两金占流动资产比重", -9999.99); 110 } else { 111 map.put("两金占流动资产比重", (accountReceivable + stock) 112 / currentAssets); 113 } 114 115 if (currentLiabilities == 0) { // 流动负债 116 map.put("速动比率", -9999.99); 117 } else { 118 map.put("速动比率", (currentAssets - stock) / currentLiabilities); 119 } 120 121 double operaCashFlow = row.getCell(titleMap.get("经营现金净流量")) 122 .getNumericCellValue(); 123 if (currentLiabilities == 0) { // 流动负债 124 map.put("现金流动负债比率", -9999.99); 125 } else { 126 map.put("现金流动负债比率", operaCashFlow / currentLiabilities); 127 } 128 129 double shortLoan = row.getCell(titleMap.get("短期借款")) 130 .getNumericCellValue(); 131 double oneYearLongLiabilities = row.getCell( 132 titleMap.get("一年内到期的长期负债")).getNumericCellValue(); 133 double longLoan = row.getCell(titleMap.get("长期借款")) 134 .getNumericCellValue(); 135 double bondsPayable = row.getCell(titleMap.get("应付债券")) 136 .getNumericCellValue(); 137 double interestPayable = row.getCell(titleMap.get("应付利息")) 138 .getNumericCellValue(); 139 if (totalLiabilites == 0) { // 负债总额 140 map.put("带息负债比率", -9999.99); 141 } else { 142 map.put("带息负债比率", (shortLoan + oneYearLongLiabilities 143 + longLoan + bondsPayable + interestPayable) 144 / currentLiabilities); 145 } 146 147 double draft = row.getCell(titleMap.get("己贴现承兑汇票")) 148 .getNumericCellValue(); 149 double balance = row.getCell(titleMap.get("担保余额")) 150 .getNumericCellValue(); 151 double amountOfmatter = row.getCell(titleMap.get("贴现与担保外的被诉事项金额")) 152 .getNumericCellValue(); 153 double contingentLiabilities = row.getCell(titleMap.get("其他或有负债")) 154 .getNumericCellValue(); 155 double ownerRights = row.getCell(titleMap.get("所有者权益")) 156 .getNumericCellValue(); 157 if (ownerRights == 0) { // 所有者权益 158 map.put("或有负债比率", -9999.99); 159 } else { 160 map.put("或有负债比率",(draft + balance + amountOfmatter + contingentLiabilities)/ ownerRights); 161 } 162 163 double totalCosts = row.getCell(titleMap.get("年度总融资成本")) 164 .getNumericCellValue(); 165 double financingCosts = row.getCell(titleMap.get("各类融资成本")) 166 .getNumericCellValue(); 167 if (totalCosts == 0) { // 年度总融资成本 168 map.put("平均融资成本率", 0.00); 169 } else { 170 map.put("平均融资成本率", totalCosts / financingCosts); 171 } 172 173 // 三种状态:正常 关注 重点关注 174 String status = row.getCell(titleMap.get("企业债务风险等级")) 175 .getStringCellValue(); 176 // 是否集团所需企业 177 boolean flag = row.getCell(titleMap.get("是否集团所需企业")) 178 .getNumericCellValue() == 1 ? true : false; 179 String orgId = row.getCell(titleMap.get("企业组织ID")) 180 .getStringCellValue(); 181 // 排序编码 182 int sortNum = (int) row.getCell(titleMap.get("排序编码")) 183 .getNumericCellValue(); 184 String analysis = row.getCell(titleMap.get("简要分析")) 185 .getStringCellValue(); 186 187 // TODO: 根据组织ID 获取number longNumber 188 189 // TODO: 企业风险等级分析 190 String riskLevel = riskLevelSort(map); 191 192 // riskInfo 赋值 193 riskItemInfo.setYear(Integer.valueOf(year)); 194 riskItemInfo.setMonth(Integer.valueOf(month)); 195 riskItemInfo.setTotalAssets(BigDecimal.valueOf(Double 196 .valueOf(totalAssets))); 197 riskItemInfo.setCompanyName(companyName); 198 riskItemInfo.setTotalLiabilites(BigDecimal.valueOf(Double 199 .valueOf(totalLiabilites))); 200 riskItemInfo.setTotalProfit(BigDecimal.valueOf(Double 201 .valueOf(totalProfit))); 202 riskItemInfo.setInterestExpense(BigDecimal.valueOf(Double 203 .valueOf(interestExpense))); 204 riskItemInfo.setTrafficProfit(BigDecimal.valueOf(Double 205 .valueOf(trafficProfit))); 206 riskItemInfo.setCurrentAssets(BigDecimal.valueOf(Double 207 .valueOf(currentAssets))); 208 riskItemInfo.setCurrentLiabilities(BigDecimal.valueOf(Double 209 .valueOf(currentLiabilities))); 210 riskItemInfo.setAccountReceivable(BigDecimal.valueOf(Double 211 .valueOf(accountReceivable))); 212 riskItemInfo.setStock(BigDecimal.valueOf(Double.valueOf(stock))); 213 riskItemInfo.setOperaCashFlow(BigDecimal.valueOf(Double 214 .valueOf(operaCashFlow))); 215 riskItemInfo.setShortLoan(BigDecimal.valueOf(Double 216 .valueOf(shortLoan))); 217 riskItemInfo.setOneYearLongLiabilities(BigDecimal.valueOf(Double 218 .valueOf(oneYearLongLiabilities))); 219 riskItemInfo.setLongLoan(BigDecimal.valueOf(Double 220 .valueOf(longLoan))); 221 riskItemInfo.setOwnerRights(BigDecimal.valueOf(Double 222 .valueOf(ownerRights))); 223 // riskItemInfo.setStatus(status); 作废 224 riskItemInfo.setBondsPayable(BigDecimal.valueOf(Double 225 .valueOf(bondsPayable))); 226 riskItemInfo.setInterestPayable(BigDecimal.valueOf(Double 227 .valueOf(interestPayable))); 228 riskItemInfo.setDraft(BigDecimal.valueOf(Double.valueOf(draft))); 229 riskItemInfo 230 .setBalance(BigDecimal.valueOf(Double.valueOf(balance))); 231 riskItemInfo.setAmountOfmatter(BigDecimal.valueOf(Double 232 .valueOf(amountOfmatter))); 233 riskItemInfo.setContingentLiabilities(BigDecimal.valueOf(Double 234 .valueOf(contingentLiabilities))); 235 riskItemInfo.setTotalCosts(BigDecimal.valueOf(Double 236 .valueOf(totalCosts))); 237 riskItemInfo.setFinancingCosts(BigDecimal.valueOf(Double 238 .valueOf(financingCosts))); 239 240 if (status != null && !"".equals(status)) { 241 riskItemInfo.setStatus(status);// Excel 中直接维护了风险等级 242 } else { 243 riskItemInfo.setStatus(riskLevel); // 算法自动判定风险等级 244 } 245 246 riskItemInfo.setAnalysis(analysis);// 简要分析 算法自动判定风险等级 247 riskItemInfo.setFlag(flag); 248 riskItemInfo.setSortNum(sortNum);// 排序编号 249 250 try { 251 if (riskItemInfo != null && !riskItemInfo.isEmpty()) { 252 remoteInstance.save(riskItemInfo); 253 } else { 254 MsgBox.showError("读取数据失败!"); 255 SysUtil.abort(); 256 } 257 258 } catch (EASBizException e) { 259 MsgBox.showError("读取数据失败!"); 260 e.printStackTrace(); 261 } catch (BOSException e) { 262 MsgBox.showError("读取数据失败!"); 263 e.printStackTrace(); 264 } 265 266 } 267 try { 268 is.close(); 269 } catch (IOException e) { 270 MsgBox.showError("读取数据失败!"); 271 e.printStackTrace(); 272 } 273 274 message.append(filePath); 275 return message.toString(); 276 277 }
数据导入中需要对企业风险等级进行判定,而里面只有基础数据,对比还需要获取到国资委的对标值,因此需要使用基础数据获取到各个指标值,在获取到国资委对标值,在依据判定规则算法进行判定。
获取国资委年度对标值
年度对标值是按年度进行维护的,因此需要获取到导入的Excel中的字段 年,然后根据根据 年 查询 国资委数据单据头 获取对应的单据ID,在去分录中查询单据ID对应的分录明细数据。
1 /* 2 * 根据年份获取国资委企业绩效评价表中 的 表头id 3 */ 4 private String getSasacIDByYear(String year) { 5 EntityViewInfo view = new EntityViewInfo(); 6 SelectorItemCollection sic = new SelectorItemCollection(); 7 sic.add(new SelectorItemInfo("id")); 8 view.setSelector(sic); 9 10 FilterInfo filter = new FilterInfo(); 11 FilterItemInfo item = new FilterItemInfo("year", year); 12 filter.getFilterItems().add(item); 13 14 view.setFilter(filter); 15 String parentId = null; 16 try { 17 SasacCollection col = SasacFactory.getRemoteInstance() 18 .getSasacCollection(view); 19 if (col != null && col.size() > 0) { 20 parentId = col.get(0).getId().toString(); 21 } 22 } catch (BOSException e) { 23 e.printStackTrace(); 24 logger.error("国资委企业绩效评价表根据year 获取ID 出错!", e); 25 MsgBox.showInfo("尚未维护年度国资委绩效评价对标" + year); 26 } 27 if (parentId != null) { 28 return parentId; 29 } 30 return null; 31 } 32 33 // TODO: 根据表头id parentid 获取分录中对应结果集 34 private List<Map<String, Object>> getSasacEntryByPID(String pid) { 35 List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(); 36 37 EntityViewInfo view = new EntityViewInfo(); 38 SelectorItemCollection sic = new SelectorItemCollection(); 39 sic.add(new SelectorItemInfo("name")); 40 sic.add(new SelectorItemInfo("average")); 41 sic.add(new SelectorItemInfo("poor")); 42 view.setSelector(sic); 43 44 FilterInfo filter = new FilterInfo(); 45 filter.getFilterItems().add(new FilterItemInfo("parent", pid)); 46 47 view.setFilter(filter); 48 49 try { 50 CoreBaseCollection col = SasacEntryFactory.getRemoteInstance() 51 .getCollection(view); 52 if (col != null && col.size() > 0) { 53 for (int i = 0; i < col.size(); i++) { 54 Map<String, Object> map = new HashMap<String, Object>(); 55 SasacEntryInfo saInfo = (SasacEntryInfo) col.get(i); 56 String name = saInfo.getName(); 57 BigDecimal average = saInfo.getAverage(); 58 BigDecimal poor = saInfo.getPoor(); 59 // TODO: 装填到 Map 60 map.put("name", name); 61 map.put("average", average); 62 map.put("poor", poor); 63 list.add(map); 64 } 65 } 66 if (list != null || !list.isEmpty()) { 67 return list; 68 } 69 70 } catch (BOSException e) { 71 e.printStackTrace(); 72 } 73 return null; 74 }
因为只需要国资委对标值得平均值和较差值,因此进行不同指标的对标值得初始化。便于后面的 风险判定使用。
1 // 初始化 国资委对标值 平均值 较差值 2 private static Double P1, P2, Q1, Q2, R1, R2, S1, S2, T1, T2; 3 private static Double U1, U2, V1, V2, W1, W2, X1, X2, Y1, Y2; 4 ... 5 6 //初始化国资委对标值 赋值 7 private static void initVariable(String name, Double average, Double poor) { 8 if (name.contains("资产负债率")) { 9 P1 = average / 100; 10 P2 = poor / 100; 11 } else if (name.contains("营业利润")) { 12 Q1 = average / 100; 13 Q2 = poor / 100; 14 } else if (name.contains("已获利息倍数")) { 15 R1 = average / 100; 16 R2 = poor / 100; 17 } else if (name.contains("流动比率")) { 18 S1 = average / 100; 19 S2 = poor / 100; 20 } else if (name.contains("两金占流动资产比重")) { 21 T1 = average / 100; 22 T2 = poor / 100; 23 } else if (name.contains("速动比率")) { 24 U1 = average / 100; 25 U2 = poor / 100; 26 } else if (name.contains("现金流动负债比率")) { 27 V1 = average / 100; 28 V2 = poor / 100; 29 } else if (name.contains("带息负债比率")) { 30 W1 = average / 100; 31 W2 = poor / 100; 32 } else if (name.contains("或有负债比率")) { 33 X1 = average / 100; 34 X2 = poor / 100; 35 } else if (name.contains("平均融资成本率")) { 36 Y1 = average / 100; 37 Y2 = poor / 100; 38 } 39 }
风险判定
将基础数据按照指标公式得到的指标值存到Map(key:指标名称,value:指标值)中传给风险等级判定方法使用。然后根据上面的指标初始化对标值进行比对判定。
1 /** 2 * 3 * Title: riskLevelSort 4 * 企业风险等级归类 正常 关注 重点关注 (一)正常等级:绿色指标不少于4项,且资产负债率和平均融资成本率均未显示红色。 5 * (二)关注等级:绿色指标为3项,或绿色指标小于3项但无红色指标,或绿色指标不少于4项但资产负债率和平均融资成本率有1项显示红色。 6 * (三)重点关注等级:绿色指标少于3项且至少有1项红色指标,或营业利润为负且资产负债率、平均融资成本率均显示红色。 7 */ 8 private String riskLevelSort(Map<String, Double> map) { 9 // 风险等级 10 String riskLevel = null; 11 // 绿色指标数量 12 Integer greenNum = 0; 13 // 红色指标数量 14 Integer redNum = 0; 15 // 黄色指标数量 16 Integer yellowNum = 0; 17 // 营业利润 指标 是否为 负 (默认为负 true) 18 boolean trafficProfitFlag = true; 19 // 资产负债率 指标 显示 是否为 红色 (默认不为红色 true) 20 boolean b1 = true; 21 // 平均融资成本率 指标 显示 是否为 红色 (默认不为红色 true) 22 boolean b2 = true; 23 24 /* 25 * 指标判断 26 */ 27 Double r1 = map.get("资产负债率"); 28 if (r1 != -9999.99) { 29 if (r1 >= P2) { 30 redNum++; 31 // 资产负债率 指标 显示 红色 32 b1 = false; 33 } else if (r1 >= P1) { 34 yellowNum++; 35 } else { 36 greenNum++; 37 } 38 } 39 40 Double r2 = map.get("营业利润"); 41 if (r2 != -9999.99) { 42 if (r2 > Q1) { 43 greenNum++; 44 // 营业利润 指标 不 为负 45 trafficProfitFlag = false; 46 } else if (r2 >= Q2) { 47 yellowNum++; 48 } else { 49 redNum++; 50 } 51 } 52 53 Double r3 = map.get("己获利息倍数"); 54 if (r3 != -9999.99) { 55 if (r3 >= W1) { 56 greenNum++; 57 } else if (r3 >= W2) { 58 yellowNum++; 59 } else { 60 redNum++; 61 } 62 } 63 64 Double r4 = map.get("流动比率"); 65 if (r4 != -9999.99) { 66 if (r4 >= S1) { 67 greenNum++; 68 } else if (r4 >= S2) { 69 yellowNum++; 70 } else { 71 redNum++; 72 } 73 } 74 75 Double r5 = map.get("两金占流动资产比重"); 76 if (r5 != -9999.99) { 77 if (r5 > T2) { 78 redNum++; 79 } else if (r5 >= T1) { 80 yellowNum++; 81 } else { 82 greenNum++; 83 } 84 } 85 86 Double r6 = map.get("速动比率"); 87 if (r6 != -9999.99) { 88 if (r6 >= U1) { 89 greenNum++; 90 } else if (r6 >= U2) { 91 yellowNum++; 92 } else { 93 redNum++; 94 } 95 } 96 97 Double r7 = map.get("现金流动负债比率"); 98 if (r7 != -9999.99) { 99 if (r7 >= V1) { 100 greenNum++; 101 } else if (r7 >= V2) { 102 yellowNum++; 103 } else { 104 redNum++; 105 } 106 } 107 108 Double r8 = map.get("带息负债比率"); 109 if (r8 != -9999.99) { 110 if (r8 >= W2) { 111 redNum++; 112 } else if (r8 >= W1) { 113 yellowNum++; 114 } else { 115 greenNum++; 116 } 117 } 118 119 Double r9 = map.get("或有负债比率"); 120 if (r9 != -9999.99) { 121 if (r9 >= X2) { 122 redNum++; 123 } else if (r9 >= X1) { 124 yellowNum++; 125 } else { 126 greenNum++; 127 } 128 } 129 130 Double r10 = map.get("平均融资成本率"); 131 if (r10 != -9999.99) { 132 if (r10 >= Y2) { 133 redNum++; 134 // 平均融资成本率 指标 显示 红色 135 b2 = false; 136 } else if (r10 >= Y1) { 137 yellowNum++; 138 } else { 139 greenNum++; 140 } 141 }