Quellcode durchsuchen

OMS发票信息部分代码上传

徐滕 vor 1 Monat
Ursprung
Commit
c9cffabe68

+ 83 - 0
src/main/java/com/jeeplus/modules/ruralprojectrecords/web/RuralProjectSignatureOldMessageDisposeController.java

@@ -61,6 +61,7 @@ import org.springframework.web.multipart.MultipartFile;
 import org.springframework.web.servlet.mvc.support.RedirectAttributes;
 import org.w3c.dom.Document;
 import org.w3c.dom.NodeList;
+import redis.clients.jedis.Jedis;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -1066,4 +1067,86 @@ public class RuralProjectSignatureOldMessageDisposeController extends BaseContro
         return map;
     }
 
+
+    /**
+     * 临时访问接口
+     * @param redisKeyPrefix
+     */
+    /**
+     * 临时访问接口:按前缀批量删除Redis key
+     * @param redisKeyPrefix 传入Redis key前缀(如OMS_invoice_download)
+     * @return 包含操作状态和key集合的结果
+     */
+    @RequestMapping(value = "/deleteRedisByKey")
+    @ResponseBody
+    public Map<String, Object> deleteRedisByKey(String redisKeyPrefix) {
+        Map<String, Object> resultMap = new HashMap<>();
+        // 初始化返回结果:默认操作失败
+        resultMap.put("success", false);
+        resultMap.put("code", 500);
+        resultMap.put("msg", "删除失败,未知异常");
+        Jedis jedis = null;
+
+        try {
+            // 1. 获取Redis连接
+            jedis = JedisUtils.getResource();
+            // 测试用:查询删除前的key集合(硬编码,可保留)
+            Set<String> downloadTaskKeys1 = jedis.keys(redisKeyPrefix + ":*");
+            resultMap.put("downloadTaskKeys1", downloadTaskKeys1);
+
+            // 2. 全量判空:连接非空 + 前缀非空非空串
+            if (jedis == null) {
+                resultMap.put("msg", "获取Redis连接失败");
+                return resultMap;
+            }
+            if (redisKeyPrefix == null || redisKeyPrefix.trim().isEmpty()) {
+                resultMap.put("msg", "Redis key前缀不能为空");
+                return resultMap;
+            }
+
+            // 3. 拼接通配符,匹配前缀下所有key
+            String redisPattern = redisKeyPrefix.trim() + "*";
+            // 4. 查询匹配的key集合
+            Set<String> matchKeys = jedis.keys(redisPattern);
+            if (matchKeys == null || matchKeys.isEmpty()) {
+                // 无匹配key,返回成功提示
+                resultMap.put("success", true);
+                resultMap.put("code", 200);
+                resultMap.put("msg", "未查询到匹配的Redis key,无需删除");
+                // 查询删除后(实际无删除)的key集合
+                Set<String> downloadTaskKeys2 = jedis.keys(redisKeyPrefix + ":*");
+                resultMap.put("downloadTaskKeys2", downloadTaskKeys2);
+                return resultMap;
+            }
+
+            // 5. 批量删除:Set转数组,调用del方法
+            String[] keyArray = matchKeys.toArray(new String[0]);
+            jedis.del(keyArray);
+
+            // 6. 关键:用有效连接查询删除后的真实key集合
+            Set<String> downloadTaskKeys2 = jedis.keys(redisKeyPrefix + ":*");
+            resultMap.put("downloadTaskKeys2", downloadTaskKeys2);
+
+            // 7. 更新返回结果:删除成功
+            resultMap.put("success", true);
+            resultMap.put("code", 200);
+            resultMap.put("msg", "成功删除" + matchKeys.size() + "个Redis key");
+
+        } catch (Exception e) {
+            // 捕获所有Redis操作异常,记录日志(建议添加日志框架,如logback/log4j2)
+            e.printStackTrace(); // 临时用,生产环境替换为日志记录
+            resultMap.put("msg", "Redis操作异常:" + e.getMessage());
+        } finally {
+            // 仅释放资源:关闭Jedis连接,归还到连接池
+            if (jedis != null) {
+                try {
+                    jedis.close();
+                } catch (Exception e) {
+                    e.printStackTrace(); // 关闭连接异常也记录
+                }
+            }
+        }
+        return resultMap;
+    }
+
 }

+ 3 - 3
src/main/java/com/jeeplus/modules/workcalendar/service/WorkCalendarTaskService.java

@@ -504,7 +504,7 @@ public class WorkCalendarTaskService  {
      * 用于发票开票获取数电票信息处理
      * 和开票系统相关的定时任务
      */
-    @Scheduled(cron = "0 */1 * * * ?")
+    @Scheduled(cron = "0 */5 * * * ?")
     @Transactional(readOnly = false)
     public void processInvoiceDownloadTasks() {
         invoiceDownloadService.processInvoiceDownloadTasks();
@@ -515,7 +515,7 @@ public class WorkCalendarTaskService  {
      * 用于发票开票红冲定时任务信息处理
      * 和开票系统相关的定时任务
      */
-    @Scheduled(cron = "0 */3 * * * ?")
+    @Scheduled(cron = "0 */5 * * * ?")
     @Transactional(readOnly = false)
     public void processRedInvoiceScheduledTask() {
         redInvoiceScheduledService.processAllRedInvoiceTasks();
@@ -525,7 +525,7 @@ public class WorkCalendarTaskService  {
      * 用于发票开票时报9998错误时进行重新处理的方法
      * 和开票系统相关的定时任务
      */
-    @Scheduled(cron = "0 */10 * * * ?")
+    @Scheduled(cron = "0 */3 * * * ?")
     @Transactional(readOnly = false)
     public void redInvoiceRetryScheduledTask() {
         redInvoiceRetryScheduledService.handleInvoice9998RetryTask();

+ 2 - 2
src/main/java/com/jeeplus/modules/workinvoice/service/OMS/InvoiceDownloadService.java

@@ -69,7 +69,7 @@ public class InvoiceDownloadService {
 
                 if(StringUtils.isBlank(accessToken)){
                     // 获取AccessToken 9998重试5次
-                    accessToken = omsDisposeService.getOmsAccessTokenWithRetry(5, "accessToken", workInvoiceId);
+                    accessToken = omsDisposeService.getOmsAccessTokenWithRetry(5, "accessToken", workInvoiceId, informType);
                     if(StringUtils.isNotBlank(accessToken)){
                         jedis.setex("OMSAccessToken", 86400, accessToken);
                         System.out.println("重新获取token成功,存入Redis");
@@ -137,7 +137,7 @@ public class InvoiceDownloadService {
             String jsonInvoiceDownStr = JSON.toJSONString(invoiceDownInfo);
 
             String invoiceResultStr = HttpPostJsonUtil.doPost(
-                    "https://oms-sandbox.einvoice.js.cn:7079/prod-api/output/server/invoice/download",
+                    "https://www.oms.ejinshui-cloud.com:8899/prod-api/output/server/invoice/download",
                     jsonInvoiceDownStr
             );
             System.out.println("[InvoiceDownloadTask] 发票解析结果:" + invoiceResultStr);

+ 11 - 10
src/main/java/com/jeeplus/modules/workinvoice/service/OMS/OMSDisposeService.java

@@ -65,7 +65,7 @@ public class OMSDisposeService {
             accessToken = jedis.get("OMSAccessToken");
             if(StringUtils.isBlank(accessToken)){
                 // 获取AccessToken 9998重试5次
-                accessToken = getOmsAccessTokenWithRetry(10, "accessToken", workInvoiceId);
+                accessToken = getOmsAccessTokenWithRetry(10, "accessToken", workInvoiceId, informType);
                 if(StringUtils.isNotBlank(accessToken)){
                     jedis.setex("OMSAccessToken", seconds, accessToken);
                     map.put("token状态", "重新获取token成功,存入Redis");
@@ -130,7 +130,7 @@ public class OMSDisposeService {
                     InvoiceTokenInfo.setData(string);
                     String jsonInvoiceStr = JSON.toJSONString(InvoiceTokenInfo);
 
-                    String jsonInvoicResultStr = HttpPostJsonUtil.doPost("https://oms-sandbox.einvoice.js.cn:7079/prod-api/output/server/order/upload", jsonInvoiceStr);
+                    String jsonInvoicResultStr = HttpPostJsonUtil.doPost("https://www.oms.ejinshui-cloud.com:8899/prod-api/output/server/order/upload", jsonInvoiceStr);
                     System.out.println("✅ 订单提交接口返回值:" + jsonInvoicResultStr);
                     map.put("订单接口信息", jsonInvoicResultStr);
 
@@ -177,14 +177,14 @@ public class OMSDisposeService {
      * @return
      */
     @Transactional(readOnly = false)
-    public String getOmsAccessTokenWithRetry(int remainRetryTimes, String getKey, String workInvoiceId) {
+    public String getOmsAccessTokenWithRetry(int remainRetryTimes, String getKey, String workInvoiceId,  String informType) {
         try {
             OMSAccessTokenInfo tokenInfo = new OMSAccessTokenInfo();
             tokenInfo.setAppId(appId);
             tokenInfo.setAppKey(appKey);
             tokenInfo.setExchangeId(UUID.randomUUID().toString());
             String jsonStr = JSON.toJSONString(tokenInfo);
-            String accessTokenStr = HttpPostJsonUtil.doPost("https://oms-sandbox.einvoice.js.cn:7079/prod-api/server/accessToken", jsonStr);
+            String accessTokenStr = HttpPostJsonUtil.doPost("https://www.oms.ejinshui-cloud.com:8899/prod-api/server/accessToken", jsonStr);
 
             if(StringUtils.isBlank(accessTokenStr)){
                 System.err.println("获取AccessToken失败:接口返回空,剩余重试次数:"+remainRetryTimes);
@@ -208,7 +208,7 @@ public class OMSDisposeService {
                     int nextRetry = remainRetryTimes - 1;
                     System.err.println("⚠️ 获取AccessToken返回9998接口波动,30秒后重试,剩余次数:"+nextRetry);
                     Thread.sleep(30 * 1000);
-                    return getOmsAccessTokenWithRetry(nextRetry, getKey, workInvoiceId);
+                    return getOmsAccessTokenWithRetry(nextRetry, getKey, workInvoiceId, informType);
                 } else {
                     System.err.println("❌ 获取AccessToken失败:连续5次返回9998,重试次数耗尽!");
                     //需要将错误信息保存到对应开票信息表中
@@ -219,6 +219,7 @@ public class OMSDisposeService {
                         workInvoiceDao.updateAccessTokenErrorById(workInvoice);
                     }
                     //如果需要 可以将执行失败信息通过短信通知业务发起人
+                    handleInvoiceRetryAllFail("", workInvoiceId, "获取AccessToken失败,需要业务人员重新发起", informType); // 解析失败也执行兜底方法
 
                     return "";
                 }
@@ -403,7 +404,7 @@ public class OMSDisposeService {
                 //将错误信息保存到数据库
                 workInvoice.setOmsErrorMessage(errorMessage);
                 workInvoice.setOmsAccessToken(accessToken);
-                workInvoice.setInvoiceState("1");
+                workInvoice.setInvoiceState("3");
                 //修改结果
                 workInvoiceDao.updateAccessTokenErrorById(workInvoice);
 
@@ -438,7 +439,7 @@ public class OMSDisposeService {
             accessToken = jedis.get("OMSAccessToken");
             if(StringUtils.isBlank(accessToken)){
                 // 获取AccessToken 9998重试5次
-                accessToken = getOmsAccessTokenWithRetry(10, "accessToken", workInvoiceId);
+                accessToken = getOmsAccessTokenWithRetry(10, "accessToken", workInvoiceId, informType);
                 if(StringUtils.isNotBlank(accessToken)){
                     jedis.setex("OMSAccessToken", seconds, accessToken);
                     map.put("token状态", "重新获取token成功,存入Redis");
@@ -462,7 +463,7 @@ public class OMSDisposeService {
             InvoiceTokenInfo.setData(string);
             String jsonInvoiceStr = JSON.toJSONString(InvoiceTokenInfo);
 
-            String jsonInvoicResultStr = HttpPostJsonUtil.doPost("https://oms-sandbox.einvoice.js.cn:7079/prod-api/output/server/invoice/makeredinv", jsonInvoiceStr);
+            String jsonInvoicResultStr = HttpPostJsonUtil.doPost("https://www.oms.ejinshui-cloud.com:8899/prod-api/output/server/invoice/makeredinv", jsonInvoiceStr);
             System.out.println("✅ 快速红冲订单提交接口返回值:" + jsonInvoicResultStr);
             map.put("快速红冲订单接口信息", jsonInvoicResultStr);
 
@@ -501,7 +502,7 @@ public class OMSDisposeService {
             accessToken = jedis.get("OMSAccessToken");
             if(StringUtils.isBlank(accessToken)){
                 // 获取AccessToken 9998重试5次
-                accessToken = getOmsAccessTokenWithRetry(10, "accessToken", workInvoiceId);
+                accessToken = getOmsAccessTokenWithRetry(10, "accessToken", workInvoiceId, informType);
                 if(StringUtils.isNotBlank(accessToken)){
                     jedis.setex("OMSAccessToken", seconds, accessToken);
                     map.put("token状态", "重新获取token成功,存入Redis");
@@ -581,7 +582,7 @@ public class OMSDisposeService {
                     InvoiceTokenInfo.setData(string);
                     String jsonInvoiceStr = JSON.toJSONString(InvoiceTokenInfo);
 
-                    String jsonInvoicResultStr = HttpPostJsonUtil.doPost("https://oms-sandbox.einvoice.js.cn:7079/prod-api/output/server/redApply/apply", jsonInvoiceStr);
+                    String jsonInvoicResultStr = HttpPostJsonUtil.doPost("https://www.oms.ejinshui-cloud.com:8899/prod-api/output/server/redApply/apply", jsonInvoiceStr);
                     System.out.println("✅ 全场景红冲订单提交接口返回值:" + jsonInvoicResultStr);
                     map.put("全场景红冲订单接口信息", jsonInvoicResultStr);
 

+ 2 - 2
src/main/java/com/jeeplus/modules/workinvoice/service/OMS/RedInvoiceDownloadService.java

@@ -70,7 +70,7 @@ public class RedInvoiceDownloadService {
 
                 if(StringUtils.isBlank(accessToken)){
                     // 获取AccessToken 9998重试5次
-                    accessToken = omsDisposeService.getOmsAccessTokenWithRetry(5, "accessToken", workInvoiceId);
+                    accessToken = omsDisposeService.getOmsAccessTokenWithRetry(5, "accessToken", workInvoiceId, informType);
                     if(StringUtils.isNotBlank(accessToken)){
                         jedis.setex("OMSAccessToken", 86400, accessToken);
                         System.out.println("重新获取token成功,存入Redis");
@@ -142,7 +142,7 @@ public class RedInvoiceDownloadService {
             String jsonInvoiceDownStr = JSON.toJSONString(invoiceDownInfo);
 
             String invoiceResultStr = HttpPostJsonUtil.doPost(
-                    "https://oms-sandbox.einvoice.js.cn:7079/prod-api/output/server/invoice/download",
+                    "https://www.oms.ejinshui-cloud.com:8899/prod-api/output/server/invoice/download",
                     jsonInvoiceDownStr
             );
             System.out.println("[InvoiceDownloadTask] 发票解析结果:" + invoiceResultStr);

+ 2 - 2
src/main/java/com/jeeplus/modules/workinvoice/service/OMS/RedInvoiceRetryScheduledService.java

@@ -75,7 +75,7 @@ public class RedInvoiceRetryScheduledService {
 
                     if(StringUtils.isBlank(accessToken)){
                         // 获取AccessToken 9998重试5次
-                        accessToken = invoiceOMSService.getOmsAccessTokenWithRetry(5, "accessToken", workInvoiceId);
+                        accessToken = invoiceOMSService.getOmsAccessTokenWithRetry(5, "accessToken", workInvoiceId, informType);
                         if(StringUtils.isNotBlank(accessToken)){
                             jedis.setex("OMSAccessToken", 86400, accessToken);
                             System.out.println("重新获取token成功,存入Redis");
@@ -113,7 +113,7 @@ public class RedInvoiceRetryScheduledService {
                     if(null != workInvoice){
                         // 7. 调用OMS订单上传接口重试
                         String newResultStr = HttpPostJsonUtil.doPost(
-                                "https://oms-sandbox.einvoice.js.cn:7079/prod-api/output/server/order/upload",
+                                "https://www.oms.ejinshui-cloud.com:8899/prod-api/output/server/order/upload",
                                 jsonInvoiceStr
                         );
                         System.out.println("✅ 订单" + orderNo + "9998重试调用接口返回:" + newResultStr);

+ 2 - 2
src/main/java/com/jeeplus/modules/workinvoice/service/OMS/RedInvoiceScheduledService.java

@@ -75,7 +75,7 @@ public class RedInvoiceScheduledService {
 
                 if(StringUtils.isBlank(accessToken)){
                     // 获取AccessToken 9998重试5次
-                    accessToken = omsDisposeService.getOmsAccessTokenWithRetry(5, "accessToken", workInvoiceId);
+                    accessToken = omsDisposeService.getOmsAccessTokenWithRetry(5, "accessToken", workInvoiceId, informType);
                     if(StringUtils.isNotBlank(accessToken)){
                         jedis.setex("OMSAccessToken", 86400, accessToken);
                         System.out.println("重新获取token成功,存入Redis");
@@ -187,7 +187,7 @@ public class RedInvoiceScheduledService {
             String jsonInvoiceDownStr = JSON.toJSONString(invoiceDownInfo);
 
             // 调用查询接口(红字确认单接口,即红冲的第3步)
-            String invoiceResultStr = HttpPostJsonUtil.doPost("https://oms-sandbox.einvoice.js.cn:7079/prod-api/output/server/redApply/query", jsonInvoiceDownStr);
+            String invoiceResultStr = HttpPostJsonUtil.doPost("https://www.oms.ejinshui-cloud.com:8899/prod-api/output/server/redApply/query", jsonInvoiceDownStr);
             if (StringUtils.isBlank(invoiceResultStr)) {
                 throw new RuntimeException("查询接口返回空");
             }

+ 11 - 4
src/main/java/com/jeeplus/modules/workinvoice/utils/OMSNationUtil.java

@@ -92,6 +92,8 @@ public class OMSNationUtil {
     private static final String deptCode = Global.getConfig("omsDeptCode");
     private static final String sellerName = Global.getConfig("omsSellerName");
     private static final String sellerTaxno = Global.getConfig("omsSellerTaxno");
+    private static final String bankName = Global.getConfig("omsBankName");
+    private static final String bankAccount = Global.getConfig("omsBankAccount");
 
 
     /**
@@ -109,6 +111,8 @@ public class OMSNationUtil {
         omsImportInfo.setOrderno(workInvoiceId);
         omsImportInfo.setSellerName(sellerName);
         omsImportInfo.setSellerTaxno(sellerTaxno); //销方纳税人识别号,必填
+        omsImportInfo.setSellerBank(bankName); //销售方开户行名称
+        omsImportInfo.setSellerBankaccount(bankAccount); //销售方开户行账号
         //* 开票类型(此处固定是蓝字票)
         //* 01:红字发票 02:蓝字发票,必填
         omsImportInfo.setInvKind("02");
@@ -126,7 +130,7 @@ public class OMSNationUtil {
         //omsImportInfo.setBuyerName("深圳市爱人人餐饮服务有限公司");
         //omsImportInfo.setBuyerTaxno("500102203117204029");
         omsImportInfo.setBuyerName(workInvoice.getClient().getName());    //购买方名称
-        omsImportInfo.setBuyerTaxno(workInvoice.getClient().getOrUnicode());  //购买方信用代码
+        omsImportInfo.setBuyerTaxno(workInvoice.getClient().getUscCode());  //购买方信用代码
         omsImportInfo.setBuyerAddr(workInvoice.getClient().getAddress()); //购买方地址
         omsImportInfo.setBuyerPhone(workInvoice.getClient().getTelephone()); //购买方电话
         omsImportInfo.setBuyerBank(workInvoice.getBank()); //购买方开户行名称
@@ -147,8 +151,10 @@ public class OMSNationUtil {
             omsImportInfo.setBuyerType("0"); //购买方类型(0:企业;1:自然人) 默认企业
         }
 
-
-        //omsImportInfo.setRemarks("zzsytdm01,xfsytdm01");
+        // 如果开票信息存在备注,那么将备注信息进行添加
+        if (StringUtils.isNotBlank(workInvoice.getRemarks())) {
+            omsImportInfo.setRemarks(workInvoice.getRemarks());
+        }
 
 
         OrderItem orderItem = new OrderItem();
@@ -230,7 +236,7 @@ public class OMSNationUtil {
         //omsAllScenarioRedInvoiceInfo.setBuyerName("深圳市爱人人餐饮服务有限公司");
         //omsAllScenarioRedInvoiceInfo.setBuyerTaxno("500102203117204029");
         omsAllScenarioRedInvoiceInfo.setBuyerName(workInvoice.getClient().getName());    //购买方名称
-        omsAllScenarioRedInvoiceInfo.setBuyerTaxno(workInvoice.getClient().getOrUnicode());  //购买方信用代码
+        omsAllScenarioRedInvoiceInfo.setBuyerTaxno(workInvoice.getClient().getUscCode());  //购买方信用代码
         //原蓝票发票号码
         omsAllScenarioRedInvoiceInfo.setOriginalInvno(originalInvno);
         //原蓝票发票类型
@@ -337,6 +343,7 @@ public class OMSNationUtil {
         orderItem.setGoodstaxno(workInvoiceTaxClassificationCode.getGoodsTaxno());//税收分类编码
         orderItem.setOriLineCode("1");//对应蓝票明细序号
 
+
         orderItems.add(orderItem);
         omsAllScenarioRedInvoiceInfo.setApplyItems(orderItems);
 

+ 12 - 5
src/main/resources/jeeplus.properties

@@ -415,11 +415,18 @@ szPublicPassword: Xg@sys9hB2!xWm
 
 
 #OMS开票相关参数
-omsAppId: hyc1
-omsAppKey: hyc1
+omsAppId: JSXGXM
+omsAppKey: JSXGXM
 #组织编码
-omsDeptCode: 500102204228315131
+omsDeptCode: JSXG01
 #销售方纳税人识别号
-omsSellerTaxno: 500102204228315131
+omsSellerTaxno: 91320000746823994F
 #销售方名称
-omsSellerName: 深圳市松胜电子有限公司
+omsSellerName: 江苏兴光项目管理有限公司
+#销售方名称
+omsBankName: 中信银行南京龙江支行
+#销售方名称
+omsBankAccount: 7329010182600006811
+#访问接口地址前缀
+#omsUrl: https://oms-sandbox.einvoice.js.cn:7079
+omsUrl: https://www.oms.ejinshui-cloud.com:8899

+ 1 - 1
src/main/webapp/webpage/include/head.jsp

@@ -36,7 +36,7 @@
 
 <!-- jeeplus -->
 <link href="${ctxStatic}/common/jeeplus.css" type="text/css" rel="stylesheet" />
-<script src="${ctxStatic}/common/jeeplus.js?25" type="text/javascript"></script>
+<script src="${ctxStatic}/common/jeeplus.js?26" type="text/javascript"></script>
 <script type="text/javascript" src="${ctxStatic}/common/openShow.js"></script>
 
 <!-- jquery ui -->

+ 1 - 1
src/main/webapp/webpage/modules/sys/sysLogin.jsp

@@ -18,7 +18,7 @@
 	<link href="${ctxStatic}/awesome/4.4/css/font-awesome.min.css" rel="stylesheet" />
 	<!-- jeeplus -->
 	<link href="${ctxStatic}/common/jeeplus.css" type="text/css" rel="stylesheet" />
-	<script src="${ctxStatic}/common/jeeplus.js?25" type="text/javascript"></script>
+	<script src="${ctxStatic}/common/jeeplus.js?26" type="text/javascript"></script>
 	<link rel="shortcut icon" href="images/favicon.png" type="image/png">
 	<!-- text fonts -->
 	<link rel="stylesheet" href="${ctxStatic }/common/login/ace-fonts.css" />

+ 1 - 1
src/main/webapp/webpage/modules/sys/sysLogin2.jsp

@@ -16,7 +16,7 @@
 		<link href="${ctxStatic}/awesome/4.4/css/font-awesome.min.css" rel="stylesheet" />
 		<!-- jeeplus -->
 		<link href="${ctxStatic}/common/jeeplus.css" type="text/css" rel="stylesheet" />
-		<script src="${ctxStatic}/common/jeeplus.js?25" type="text/javascript"></script>
+		<script src="${ctxStatic}/common/jeeplus.js?26" type="text/javascript"></script>
 		<link rel="shortcut icon" href="images/favicon.png" type="image/png">
 		<!-- text fonts -->
 		<link rel="stylesheet" href="${ctxStatic }/common/login/ace-fonts.css" />