This commit is contained in:
Mauve
2026-09-08 15:12:29 +08:00
commit 078ba3c713
672 changed files with 56677 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
/crm_runtime/logs/
/.idea/
/.claude/
/.vscode/
/target/*
!/target/crm_mobile_runtime/
/.classpath
/.project
+10
View File
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="AdditionalModuleElements">
<content url="file://$MODULE_DIR$" dumb="true">
<excludeFolder url="file://$MODULE_DIR$/.claude" />
<excludeFolder url="file://$MODULE_DIR$/.vscode" />
<excludeFolder url="file://$MODULE_DIR$/crm_runtime/logs" />
</content>
</component>
</module>
+16
View File
@@ -0,0 +1,16 @@
#ESB Setting
esb_app_id=mgmtestuser001
esb_app_secret=MGM@!666
esb_server=https://mmesbdevapp14/api/crmapp/v1.0
esb_request_timeout=30000
#OWS Setting
ows_server=https://mgpmsdevows45
ows_request_timeout=30000
#SMTP setting
mail_port=25
mail_smtp_host=smtp.aliyun.com
mail_sender=linp168@aliyun.com
mail_sender_password=linpeng060504
mail_send_to=1441170195@qq.com;feng.cai@willtechmacau.com
Binary file not shown.
@@ -0,0 +1,197 @@
{
"importName": "IMPORT_OTHER_BOOKING",
"importPages": [{
"sheetIndx": 0,
"dataElements": [{
"offsetRow": 1,
"offsetCol": 0,
"objClassName": "com.mgm.mcrm.common.dtos.data_import.booking.OtherBookingImportRow",
"columnDefs": [
{
"columnHeader":"#",
"checkHeader":false,
"headerRowIdx":0
},
{
"columnHeader":"Staff Action",
"checkHeader":true,
"headerRowIdx":0,
"attrName": "otherFollowUpStatusName",
"dataType": "String"
},
{
"columnHeader":"Room Status",
"checkHeader":true,
"headerRowIdx":0,
"attrName": "otherRoomStatusName",
"dataType": "String"
},
{
"columnHeader":"Property",
"checkHeader":true,
"headerRowIdx":0,
"attrName": "propertyName",
"dataType": "String"
},
{
"columnHeader":"Confirmation No.",
"checkHeader":true,
"headerRowIdx":0,
"attrName": "confirmationNo",
"dataType": "String"
},
{
"columnHeader":"Room Type",
"checkHeader":true,
"headerRowIdx":0,
"attrName": "roomName",
"dataType": "String"
},
{
"columnHeader":"Check In Date",
"checkHeader":true,
"headerRowIdx":0,
"attrName": "checkinDate",
"dataType": "String"
},
{
"columnHeader":"Check Out Date",
"checkHeader":true,
"headerRowIdx":0,
"attrName": "checkoutDate",
"dataType": "String"
},
{
"columnHeader":"Change Check In Date",
"checkHeader":false,
"headerRowIdx":0
},
{
"columnHeader":"Change Check Out Date",
"checkHeader":false,
"headerRowIdx":0
},
{
"columnHeader":"Requested C/O Date",
"checkHeader":false,
"headerRowIdx":0
},
{
"columnHeader":"Player ID",
"checkHeader":true,
"headerRowIdx":0,
"attrName": "playerId",
"dataType": "String"
},
{
"columnHeader":"Title",
"checkHeader":false,
"headerRowIdx":0
},
{
"columnHeader":"Last Name",
"checkHeader":false,
"headerRowIdx":0
},
{
"columnHeader":"First Name",
"checkHeader":false,
"headerRowIdx":0,
"attrName": "playerName",
"dataType": "String"
},
{
"columnHeader":"Tier",
"checkHeader":false,
"headerRowIdx":0
},
{
"columnHeader":"Market Code",
"checkHeader":true,
"headerRowIdx":0,
"attrName": "marketCodeName",
"dataType": "String"
},
{
"columnHeader":"Source Code",
"checkHeader":true,
"headerRowIdx":0,
"attrName": "sourceCodeName",
"dataType": "String"
},
{
"columnHeader":"Booker",
"checkHeader":false,
"headerRowIdx":0
},
{
"columnHeader":"Booker Id",
"checkHeader":true,
"headerRowIdx":0,
"attrName": "bookerId",
"dataType": "String"
},
{
"columnHeader":"Sharer",
"checkHeader":true,
"headerRowIdx":0,
"attrName": "sharer",
"dataType": "String"
},
{
"columnHeader":"Sharer Name",
"checkHeader":false,
"headerRowIdx":0
},
{
"columnHeader":"Remark",
"checkHeader":true,
"headerRowIdx":0,
"attrName": "remark",
"dataType": "String"
},
{
"columnHeader":"Approver",
"checkHeader":false,
"headerRowIdx":0
},
{
"columnHeader":"Approver ID",
"checkHeader":true,
"headerRowIdx":0,
"attrName": "approverId",
"dataType": "String"
},
{
"columnHeader":"Approval Remark",
"checkHeader":false,
"headerRowIdx":0
},
{
"columnHeader":"Booking Type",
"checkHeader":true,
"headerRowIdx":0,
"attrName": "bookingTypeName",
"dataType": "String"
},
{
"columnHeader":"Segment",
"checkHeader":true,
"headerRowIdx":0,
"attrName": "segmentName",
"dataType": "String"
},
{
"columnHeader":"ETA Time",
"checkHeader":false,
"headerRowIdx":0
},
{
"columnHeader":"Create Date/Time",
"checkHeader":false,
"headerRowIdx":0
}
]
}]
}]
}
Binary file not shown.
Binary file not shown.
+101
View File
@@ -0,0 +1,101 @@
# Daylight 合并与 `dl_reservation_id` 去重说明
本文档说明 `BookingService` 中为减少「同一 Daylight 预订在 `bookings` 表出现多行」所做的修改及调用关系。
---
## 1. 涉及文件与入口
| 位置 | 说明 |
|------|------|
| `BookingService.java` | `mergeDaylightRecordToDatabaseInfo`、`insertDaylightBooking`、`consolidateDuplicateDlReservations` 及相关私有辅助方法 |
| `BookingController`(recordSearch 等) | 在拉取 Daylight 列表后调用 `mergeDaylightRecordToDatabaseInfo` |
---
## 2. `mergeDaylightRecordToDatabaseInfo` 的改动要点
### 2.1 预查询:按 `dlReservationId` 收集(不再依赖确认号)
**原问题**:仅当 `confirmationNo` 非空时才把 `dlReservationId` 放进 `findByDlReservationIdIn` 的入参。若接口有 `dl_reservation_id` 但尚未返回确认号,则查不到库里已有行,会误判为「不存在」而走插入,产生重复。
**现逻辑**:对本次 `result`(Daylight 返回列表)中每条记录,只要 `dlReservationId` 非空白即加入 `LinkedHashSet`,再转为 `List` 做 `findByDlReservationIdIn`。
### 2.2 合并后物理去重:`consolidateDuplicateDlReservations`
在 `updateBookingList` 执行 `bookingDao.saveAll` **之后**,对本次涉及到的每个 `dl_reservation_id` 再查库:
- 若同一 `dl_reservation_id` 仍对应 **≥2 行**(例如一条前台 `PN`、一条同步误插入的 `N`),则:
- 按评分规则选出 **keeper(主行)**,其余为 **duplicate(次行)**;
- 将次行上可对齐的字段并入主行后 **`delete` 次行**。
**主行评分** `keeperScoreForDlDedup`(分数高者优先):
- 有 `player_id`:+1000
- `approve_status == "PN"`:+100
- 有 `confirmation_no`:+10
- 有 `member`:+5
同分按 **较小 `id`** 靠前(作为 keeper)。
**不合并、不删除** `shouldSkipConsolidatingDuplicateRow`:
- 次行 `approve_status` 以 `W` 开头(候补等)
- 次行 `revision_of` 指向 keeper(待审批修订子单)
- keeper `revision_of` 指向次行
**字段合并** `mergeDuplicateBookingIntoKeeper`:
- 确认号、`resv_id`、Opera 状态、酒店/客源/房价码、`player_id`、`member` 与姓名字段、房/房型、`booking_type_id`、`chain_code`、`block_id` 等在主行为空或可从次行安全补齐时写入主行;**`last_opera_status`** 若次行有值则写入主行(与 Opera 同步一致)。
日志前缀:`[consolidateDuplicateDlReservations]`。
---
## 3. `insertDaylightBooking` 的改动要点
### 3.1 按 `dl_reservation_id` 兜底防插
在组好 `Bookings book` 并准备 `save` **之前**,若 `operaBooking.getDlReservationId()` 非空,则先 `findByDlReservationIdIn`:
- **若已存在任一行**:**不再 `save` 新单**,打日志 `[insertDaylightBooking] skip insert, existing dl_reservation_id=...`,并设置返回视图上的 `id` 等为已有记录,直接 `return operaBooking`。
避免「合并阶段漏匹配」时再次插入第二条同 `dl_reservation_id`。
### 3.2 按确认号防重(空列表才插入)
- 仅当 `confirmationNo` 非空时执行 `findByConfirmationNo`;
- **仅当查询结果为空** 时才 `bookingDao.save(book)`;
- 若已有同确认号记录,则复用其 `id`,**不重复插入**。
---
## 4. 根因归纳(与旧版对比)
| 原因 | 说明 |
|------|------|
| 预查漏掉无确认号的 `dl_reservation_id` | 已用 `LinkedHashSet` + 非空 `dlReservationId` 修复 |
| 仅合并不删重复行 | 已用 `consolidateDuplicateDlReservations` 在当次同步末尾收敛 |
| 插入路径无 `dl_reservation_id` 防重 / 确认号逻辑不当 | 已在 `insertDaylightBooking` 中补齐 |
| 数据库无唯一约束 | **仍建议在库上对非空 `dl_reservation_id` 做过滤唯一索引**(上线前清理历史重复) |
| 并发双写 | 当前以逻辑合并 + 完成后去重为主;多实例强一致可再加分布式锁或 DB 唯一约束 |
---
## 5. 运维与验证
1. **验证**:部署后对曾出现双行的会员再触发一次会走 `mergeDaylightRecordToDatabaseInfo` 的查询(如 recordSearch);观察日志中 `consolidateDuplicateDlReservations` 是否合并并删除次行。
2. **历史数据**:长期未再走合并流程的重复行,需一次性脚本或手工按业务规则保留主行、删除/归档次行。
3. **外键**:若 `delete` 次行失败(子表引用),需先迁移或删除子表记录后再删。
---
## 6. 可选后续增强(未列入当前分支必选)
- 合并匹配改为 `Strings.CI.equals`(忽略 `dl_reservation_id` 大小写),与接口/库实际存储一致。
- 对 `mergeDaylightRecordToDatabaseInfo` 增加 `@Transactional(rollbackFor = Exception.class)`,使 `saveAll` 与 `consolidateDuplicateDlReservations` 同事务回滚。
- 高并发下对同一 `dl_reservation_id` 的插入加应用层锁或依赖唯一索引 + 捕获冲突后改走更新。
---
*文档与 `daylight_1.0.0` 分支中 `BookingService` 当前实现对应;若行号随重构变化请以方法名为准。*
+253
View File
@@ -0,0 +1,253 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>will</groupId>
<artifactId>CRMMobileApi</artifactId>
<version>1.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>CRMMobileApi</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.13</version>
<relativePath />
</parent>
<properties>
<java.version>21</java.version>
<logback.version>1.5.25</logback.version>
<activemq.version>6.3.1</activemq.version>
<jackson.version>2.21.2</jackson.version>
<tomcat.version>10.1.54</tomcat.version>
<spring-framework.version>6.2.18</spring-framework.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-client</artifactId>
<version>6.2.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.8.17</version>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.5</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5-win</artifactId>
<version>5.2.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.7.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.50</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.4.1</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.4.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.16.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.18.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.14.0</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.15.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>4.5.0</version>
</dependency>
<dependency>
<groupId>org.jsmpp</groupId>
<artifactId>jsmpp</artifactId>
<version>2.3.11</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.21</version>
</dependency>
<dependency>
<groupId>jakarta.xml.soap</groupId>
<artifactId>jakarta.xml.soap-api</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>com.sun.xml.messaging.saaj</groupId>
<artifactId>saaj-impl</artifactId>
</dependency>
<dependency>
<groupId>xmlpull</groupId>
<artifactId>xmlpull</artifactId>
<version>1.1.3.4a</version>
</dependency>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>4.0.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
</dependency>
<!-- JTS核心库 -->
<dependency>
<groupId>org.locationtech.jts</groupId>
<artifactId>jts-core</artifactId>
<version>1.18.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.6.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>0.2.0</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.6.3</version>
</dependency>
<dependency>
<groupId>com.eatthepath</groupId>
<artifactId>pushy</artifactId>
<version>0.15.4</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<includeSystemScope>true</includeSystemScope>
<mainClass>com.mgm.mcrm.CRMMobileApplication</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<release>${java.version}</release>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>license-maven-plugin</artifactId>
<version>2.7.0</version>
<configuration>
<excludedLicenses>
<excludedLicense>EPL-1.0</excludedLicense>
<excludedLicense>LGPL-2.1</excludedLicense>
</excludedLicenses>
</configuration>
</plugin>
</plugins>
</build>
<description>CRM Mobile Api</description>
</project>
@@ -0,0 +1,29 @@
package com.mgm.mcrm;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@ComponentScan(basePackages="com.mgm.mcrm")
@EntityScan(basePackages="com.mgm.mcrm")
@EnableTransactionManagement
@ServletComponentScan
@EnableScheduling
@EnableAsync
@EnableJms
@EnableCaching
public class CRMMobileApplication{
public static void main( String[] args ) {
SpringApplication.run(CRMMobileApplication.class, args);
}
}
+11
View File
@@ -0,0 +1,11 @@
package com.mgm.mcrm;
import java.util.UUID;
public class TestRun {
public static void main(String[] args) {
System.out.println(UUID.randomUUID());
}
}
@@ -0,0 +1,25 @@
package com.mgm.mcrm.adfs.config;
import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import java.net.URI;
public class HttpClientContextRequestFactory extends HttpComponentsClientHttpRequestFactory {
private HttpClientContext sharedContext;
public void setContext(HttpClientContext context) {
this.sharedContext=context;
}
@Override
protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) {
if (this.sharedContext != null) {
return this.sharedContext;
}
return super.createHttpContext(httpMethod, uri);
}
}
@@ -0,0 +1,39 @@
package com.mgm.mcrm.adfs.controllers;
import java.io.IOException;
import java.io.PrintWriter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
//@RequestMapping("/sso_callback")
@Controller
public class SSOCallbackController {
@RequestMapping(value="/sso_callback/login",method = RequestMethod.GET)
public String ssoLoginCallback(HttpServletRequest request, HttpServletResponse response) throws IOException{
String text = "Login Callback!";
// 设置内容类型和字符编码
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
out.print(text);
out.close();
return null;
}
@RequestMapping(value="/sso_callback/logout",method = RequestMethod.GET)
public String ssoLogoutCallback(HttpServletRequest request, HttpServletResponse response) throws IOException{
String text = "Logout Callback!";
// 设置内容类型和字符编码
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
out.print(text);
out.close();
return null;
}
}
@@ -0,0 +1,952 @@
package com.mgm.mcrm.adfs.controllers;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.URI;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.mgm.mcrm.adfs.config.HttpClientContextRequestFactory;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Strings;
import org.apache.hc.client5.http.auth.*;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.cookie.*;
import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
import org.apache.hc.client5.http.impl.DefaultRedirectStrategy;
import org.apache.hc.client5.http.impl.auth.*;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.cookie.BasicClientCookie;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy;
import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
import org.apache.hc.core5.http.*;
import org.apache.hc.core5.http.message.BasicNameValuePair;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.apache.hc.core5.ssl.SSLContexts;
import org.apache.hc.core5.util.Timeout;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Controller;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.util.HtmlUtils;
import com.mgm.mcrm.common.constants.SysCommon;
import com.mgm.mcrm.common.utils.AESUtil;
import com.mgm.mcrm.common.utils.LogUtil;
import com.mgm.mcrm.common.utils.NetworkUtil;
import javax.net.ssl.SSLContext;
@Controller
@RequestMapping("/api")
public class SSORestProcessController {
@Value("${sso.callback.login.success}")
private String loginCallbackUrl;
@Value("${sso.callback.logout.success}")
private String logoutCallbackUrl;
@Value("${adfs.hostname}")
private String adfsHost;
@Value("${relying_party}")
private String relyingParty;
@Value("${ad_domain}")
private String adDomain;
@Value("${host_name}")
private String hostName;
@Value("${adfs_domain}")
private String adfsDomain;
@Value("${adfs_secret_key}")
private String adfsSecretKey;
@Value("${adfs_request_timeout}")
private int adfsRequestTimeout=10000;
@Value("${adfs_login_timeout}")
private int adfsLoginTimeout=60000;
private static final String TEXT_SPLIT_CHAR = ",";
private Map<String,String[]> cookieSetting = new HashMap<String,String[]>();
private boolean checkValidUrl(String requestUrl){
boolean isValid = NetworkUtil.isValidURL(requestUrl);
if(isValid){
if(!requestUrl.startsWith(loginCallbackUrl)
&& !requestUrl.startsWith(adfsHost)){
isValid =false;
}
}
return isValid;
}
private void initCookieSetting() {
if(cookieSetting.size()<=0) {
String[] adfsCookiePath = new String[] {"/adfs"};
cookieSetting.put(adfsDomain, adfsCookiePath);
String[] localCookiePath = new String[] {"/","/adfs"};
cookieSetting.put("LOCALHOST", localCookiePath);
LogUtil.info(SSORestProcessController.class,"Init Cookie Setting:"+adfsDomain);
}
}
private String getWorkstationName() {
try {
return InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
return "localhost";
}
}
private Credentials createNtlmCredentials(String username, String password,
String domain, String workstation) {
String effectiveWorkstation = workstation;
if (effectiveWorkstation == null || effectiveWorkstation.isEmpty()) {
effectiveWorkstation = getWorkstationName();
}
return new NTCredentials(username, password.toCharArray(),
effectiveWorkstation, domain);
}
@RequestMapping(value="/app/sso/login_saml_with_mfa")
public String samlMFALogin(HttpServletRequest request, HttpServletResponse response) throws Exception{
String paraRelying = StringUtils.isNotBlank(request.getParameter("relyingParty"))?request.getParameter("relyingParty"):relyingParty;
String authorizedUrl = adfsHost+ "/adfs/ls/IdpInitiatedSignOn.aspx?loginToRp="+paraRelying;
String requestClientId = request.getParameter("client_request_id");
Map<String,String> cookieValues = new HashMap<String,String>();
if(StringUtils.isBlank(requestClientId)) {
requestClientId = UUID.randomUUID().toString();
}
HttpClientContext context = HttpClientContext.create();
authorizedUrl+="&client-request-id="+ requestClientId;
authorizedUrl+="&RedirectToIdentityProvider="+ URLEncoder.encode("AD AUTHORITY","UTF-8");
String userName = request.getParameter("username");
//For DEV test
// if(!StringUtils.isEmpty(userName)) {
// userName = Strings.CS.replace(userName, "@mgm.mo", "");
// }
Credentials credentials =null;
LogUtil.info(SSORestProcessController.class,"userName:"+userName);
String password = request.getParameter("password");
String credentialId=request.getParameter("credentialId");
String credentialData=request.getParameter("credentialData");
String authMethod = request.getParameter("AuthMethod");
String mfaContent = request.getParameter("Context");
String eventTarget = request.getParameter("__EVENTTARGET");
String[] urlKeyword = {
"/sso_callback/login"
};
Enumeration<String> paraNames = request.getParameterNames();
if(paraNames!=null) {
while(paraNames.hasMoreElements()) {
String paraName = paraNames.nextElement();
if(StringUtils.startsWith(paraName, "Cookie_")) {
String cookieName = paraName.replace("Cookie_", "");
cookieValues.put(cookieName, request.getParameter(paraName));
}
}
}
if(StringUtils.isNotBlank(credentialId) && StringUtils.isNotBlank(credentialData)) {
userName = AESUtil.AES256Decrypt(adfsSecretKey, credentialId);
password = AESUtil.AES256Decrypt(adfsSecretKey, credentialData);
}
boolean validateParas = true;
String errorCode ="";
String errorMessage ="";
if(StringUtils.isBlank(userName)||StringUtils.isBlank(password)) {
errorCode="InvalidParas";
errorMessage="User name or password is blank";
validateParas=false;
}else if(StringUtils.isNotBlank(authMethod) && StringUtils.isBlank(mfaContent)) {
errorCode="InvalidMFAParas";
errorMessage="MFA content is blank";
validateParas=false;
}
if(!validateParas) {
String redirectUrl = loginCallbackUrl+"?";
redirectUrl+=("error="+URLEncoder.encode(errorCode,"UTF-8"));
redirectUrl+=("&errorMessage="+URLEncoder.encode(errorMessage,"UTF-8"));
response.sendRedirect(redirectUrl);
}else {
CookieStore cookieStore = new BasicCookieStore();
SystemDefaultCredentialsProvider credentialsProvider = new SystemDefaultCredentialsProvider();
String adUserName = userName;
//LogUtil.info(SSORestProcessController.class,"Ad domain with account :"+adUserName);
AuthScope authScope = new AuthScope(null, -1);
credentials = createNtlmCredentials(adUserName, password, adDomain, null);
credentialsProvider.setCredentials(authScope, credentials);
SSLContext sslContext = SSLContexts.custom()
.loadTrustMaterial((chain, authType) -> true) // 信任所有证书
.build();
NoopHostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
DefaultClientTlsStrategy tlsStrategy = new DefaultClientTlsStrategy(sslContext, hostnameVerifier);
PoolingHttpClientConnectionManager connectionManager =
PoolingHttpClientConnectionManagerBuilder.create()
.setTlsSocketStrategy(tlsStrategy)
.setMaxConnTotal(100)
.setMaxConnPerRoute(10)
.build();
HttpClientBuilder clientBuilder = HttpClients.custom().setConnectionManager(connectionManager);
RequestConfig defaultConfig = RequestConfig.custom()
.setCookieSpec(StandardCookieSpec.RELAXED)
.setConnectionRequestTimeout(Timeout.ofMicroseconds(adfsRequestTimeout))
.setAuthenticationEnabled(true)
.setCircularRedirectsAllowed(true)
.setMaxRedirects(10)
.setRedirectsEnabled(true)
.build();
clientBuilder.setDefaultRequestConfig(defaultConfig).setDefaultCookieStore(cookieStore);
clientBuilder.setRedirectStrategy(new DefaultRedirectStrategy(){
@Override
public boolean isRedirected(HttpRequest request, HttpResponse response, HttpContext context) throws ProtocolException {
boolean isNeedRedirect = false;
int statusCode = response.getCode();
if(statusCode == 301 || statusCode == 302 || statusCode == 303 || statusCode == 305 || statusCode == 307 || statusCode == 308){
isNeedRedirect =true;
Header[] redirectHeads = response.getHeaders("location");
if(redirectHeads!=null && redirectHeads.length>0) {
//LogUtil.info(SSORestProcessController.class,"Visit Link:"+request.getRequestUri());
String location = redirectHeads[0].getValue();
for(String keyWord:urlKeyword) {
if(location.contains(keyWord)) {
isNeedRedirect=false;
break;
}
}
}
}
return isNeedRedirect;
}
});
if(!cookieValues.isEmpty()) {
initCookieSetting();
Set<String> cookieKeys = cookieValues.keySet();
for(String cookieKey:cookieKeys) {
try {
String cookieVal = cookieValues.get(cookieKey);
LogUtil.info(SSORestProcessController.class,"Set Cookie ["+cookieKey+"]="+cookieVal);
if(cookieSetting!=null && !cookieSetting.isEmpty()) {
Iterator<String> cookieSetKeys = cookieSetting.keySet().iterator();
while(cookieSetKeys.hasNext()) {
String cookieDomain =cookieSetKeys.next();
String[] cookiePaths = cookieSetting.get(cookieDomain);
if(cookiePaths!=null) {
if(Strings.CI.equals("LOCALHOST", cookieDomain)) {
cookieDomain="";
}
for(String cookiePath:cookiePaths) {
BasicClientCookie cookie = new BasicClientCookie(cookieKey, cookieVal);
try {
Date currentDate = new Date();
Date expiryDate = new Date(currentDate.getTime() + 1800 * 1000);
cookie.setExpiryDate(expiryDate);
}catch(Exception ignored) {
}
cookie.setPath(cookiePath);
cookie.setDomain(cookieDomain);
cookie.setSecure(true);
cookie.setAttribute("httponly", "true");
cookieStore.addCookie(cookie);
}
}
}
}
} catch (Exception err) {
LogUtil.error(SSORestProcessController.class,"Set Cookie failed :"+err.getMessage());
}
}
}
clientBuilder.setDefaultCookieStore(cookieStore);
clientBuilder.setDefaultCredentialsProvider(credentialsProvider);
context.setCookieStore(cookieStore);
context.setCredentialsProvider(credentialsProvider);
CloseableHttpClient httpClient = clientBuilder.build();
//HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
HttpClientContextRequestFactory httpFactory = new HttpClientContextRequestFactory();
httpFactory.setHttpClient(httpClient);
httpFactory.setContext(context);
String stepCode ="Start";
if(StringUtils.isNotBlank(mfaContent)) {
stepCode ="CheckMFAStatus";
}
String requestUrl = authorizedUrl;
boolean isProcessEnd=false;
Map<String,Object> httpResult = null;
Date startTime = new Date();
Date lastResTime = new Date();
int pendingInterval = 2000;
Map<String,String> responseHeaders = null;
while(!isProcessEnd) {
LogUtil.info(SSORestProcessController.class,"Current Step:["+stepCode+"]");
if("Start".equals( stepCode)) {
requestUrl = authorizedUrl;
httpResult = this.processStartStep(httpFactory, requestUrl, userName, password,credentials,responseHeaders);
}else if("Redirect".equals(stepCode)){
httpResult = this.processStartStep(httpFactory, requestUrl, userName, password,credentials,responseHeaders);
}else if("verifyMFA".equals(stepCode)){
httpResult = this.processMFAStep(httpFactory, requestUrl, userName, password,context);
}else if("CheckMFAStatus".equals(stepCode)) {
httpResult = this.processCheckMFAStatus(httpFactory, requestUrl, authMethod,mfaContent,eventTarget,userName, password,context);
}
if("Pending".equals(stepCode)) {
Date currentTime = new Date();
if(currentTime.getTime()-lastResTime.getTime()>=pendingInterval) {
stepCode = "Start";
}else {
Thread.sleep(500);
}
}else {
isProcessEnd = this.verifyResult(httpResult,cookieStore,urlKeyword,userName,password,requestClientId);
if(httpResult!=null && httpResult.get("ResponseHeaders")!=null)
responseHeaders = (Map<String,String>)httpResult.get("ResponseHeaders");
if(!isProcessEnd) {
Date currentTime = new Date();
if(currentTime.getTime()-startTime.getTime()>=adfsLoginTimeout) {
isProcessEnd =true;
httpResult.put("NextStep","Callback");
httpResult.put("ErrorCode", "Login Time Out");
httpResult.put("ErrorMessage", "Login processing exceeded "+(adfsLoginTimeout/1000)+" seconds");
}else {
stepCode=httpResult.get("NextStep")==null?"Pending":httpResult.get("NextStep").toString();
requestUrl = httpResult.get("NextUrl")==null?"":httpResult.get("NextUrl").toString();
}
}
lastResTime=new Date();
}
}
this.processResult(response, httpResult,loginCallbackUrl);
}
return null;
}
private Map<String,Object> processStartStep(HttpClientContextRequestFactory httpFactory,String loginUrl, String userName, String password, Credentials credentials,Map<String,String> extraHeaders) throws Exception {
LogUtil.info(SSORestProcessController.class,"Process Start URL:"+loginUrl);
Map<String,Object> result = new HashMap<String,Object>();
result.put("CurrentStep", "Start");
ClientHttpResponse clientResponse = null;
String errorMessage ="";
String errorCode="";
if(!checkValidUrl(loginUrl)){
throw new Exception("Invalid url:"+loginUrl);
}
try {
ClientHttpRequest request = httpFactory.createRequest(new URI(loginUrl), HttpMethod.POST);
request.getHeaders().add("User-Agent", "Java-NTLM-Client");
request.getHeaders().add("Accept", "*/*");
request.getHeaders().add("Connection", "Keep-Alive");
request.getHeaders().add("content-type", "application/x-www-form-urlencoded");
if(extraHeaders!=null) {
extraHeaders.forEach((key, value) -> {
//LogUtil.info(SSORestProcessController.class,"Expend Header:"+key+" Value:"+value);
if(!"content-type".equalsIgnoreCase(key)){
request.getHeaders().add(key, NetworkUtil.sanitizeHeaderValue(value));
}
});
}
List<NameValuePair> form = new ArrayList<>();
form.add(new BasicNameValuePair("UserName", userName));
form.add(new BasicNameValuePair("password", password));
form.add(new BasicNameValuePair("AuthMethod", "FormsAuthentication"));
form.add(new BasicNameValuePair("Kmsi", "True"));
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(form, StandardCharsets.UTF_8);
StreamUtils.copy(entity.getContent(), request.getBody());
clientResponse = request.execute();
}catch(Exception err) {
errorCode="RequestFailed";
errorMessage = err.getMessage();
LogUtil.error(SSORestProcessController.class,"Start step failed :"+err.getMessage());
}
result.put("HttpResponse", clientResponse);
result.put("ErrorMessage", errorMessage);
result.put("ErrorCode", errorCode);
return result;
}
private Map<String,Object> processMFAStep(HttpClientContextRequestFactory httpFactory,String loginUrl, String userName, String password,HttpClientContext context) throws Exception {
LogUtil.info(SSORestProcessController.class,"Process MFA URL:"+loginUrl);
Map<String,Object> result = new HashMap<String,Object>();
result.put("CurrentStep", "verifyMFA");
ClientHttpResponse clientResponse = null;
String errorMessage ="";
String errorCode="";
if(!checkValidUrl(loginUrl)){
throw new Exception("Invalid url:"+loginUrl);
}
try {
ClientHttpRequest request = httpFactory.createRequest(new URI(loginUrl), HttpMethod.POST);
request.getHeaders().add("content-type", "application/x-www-form-urlencoded");
List<NameValuePair> form = new ArrayList<>();
form.add(new BasicNameValuePair("UserName", userName));
form.add(new BasicNameValuePair("password", password));
form.add(new BasicNameValuePair("AuthMethod", "AzureMfaAuthentication"));
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(form, StandardCharsets.UTF_8);
StreamUtils.copy(entity.getContent(), request.getBody());
clientResponse = request.execute();
}catch(Exception err) {
errorCode="RequestFailed";
errorMessage = err.getMessage();
}
result.put("HttpResponse", clientResponse);
result.put("ErrorMessage", errorMessage);
result.put("ErrorCode", errorCode);
return result;
}
private Map<String, Object> processCheckMFAStatus(HttpClientContextRequestFactory httpFactory,
String requestUrl, String authMethod, String mfaContent,String eventTarget,String userName, String password,HttpClientContext context) throws Exception {
LogUtil.info(SSORestProcessController.class,"Check MFA Status URL:"+requestUrl);
Map<String,Object> result = new HashMap<String,Object>();
result.put("CurrentStep", "CheckMFAStatus");
ClientHttpResponse clientResponse = null;
String errorMessage ="";
String errorCode="";
if(!checkValidUrl(requestUrl)){
throw new Exception("Invalid url:"+requestUrl);
}
try {
ClientHttpRequest request = httpFactory.createRequest(new URI(requestUrl), HttpMethod.POST);
request.getHeaders().add("content-type", "application/x-www-form-urlencoded");
List<NameValuePair> form = new ArrayList<>();
form.add(new BasicNameValuePair("UserName", userName));
form.add(new BasicNameValuePair("password", password));
form.add(new BasicNameValuePair("AuthMethod", authMethod));
form.add(new BasicNameValuePair("Context", mfaContent));
form.add(new BasicNameValuePair("__EVENTTARGET", eventTarget));
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(form, StandardCharsets.UTF_8);
StreamUtils.copy(entity.getContent(), request.getBody());
clientResponse = request.execute();
}catch(Exception err) {
errorCode="RequestFailed";
errorMessage = err.getMessage();
}
result.put("HttpResponse", clientResponse);
result.put("ErrorMessage", errorMessage);
result.put("ErrorCode", errorCode);
return result;
}
private String checkErrorMessage(String responseBody) {
String errorText ="";
String errRex = "<(\\S+) id=\"errorText\"(.*?)>(.*?)</";
Pattern errPat = Pattern.compile(errRex);
Matcher matcher = errPat.matcher(responseBody);
if(matcher.find()) {
errorText = matcher.group(3);
errorText = errorText.trim();
}
if(StringUtils.isBlank(errorText)) {
errRex ="<(\\S+) id=\"errorMessage\"(.*?)>(.*?)</";
errPat = Pattern.compile(errRex);
matcher = errPat.matcher(responseBody);
if(matcher.find()) {
errorText = matcher.group(3);
errorText = errorText.trim();
}
}
if(StringUtils.isBlank(errorText)) {
errRex ="start\\(\\)(.*?)\\{(.*?)delayPopulate\\('errorText', \"(.*?)\"\\);";
errPat = Pattern.compile(errRex);
matcher = errPat.matcher(responseBody);
if(matcher.find()) {
errorText = matcher.group(3);
errorText = errorText.trim();
}
}
return errorText;
}
private boolean verifyResult(Map<String,Object> httpResult,CookieStore cookieStore,String[] urlKeyword,String userName, String password,String clientRequestId) throws IOException {
boolean isEnd=false;
if(httpResult!=null) {
if(httpResult.get("HttpResponse")!=null) {
String currentStep = httpResult.get("CurrentStep")==null?"":httpResult.get("CurrentStep").toString();
ClientHttpResponse clientResponse = (ClientHttpResponse)httpResult.get("HttpResponse");
int statusCode = clientResponse.getStatusCode().value();
LogUtil.info(SSORestProcessController.class,"Verify Status Code:"+statusCode+" current step:"+currentStep);
Map<String,String> resHeaders = new HashMap<String,String>();
clientResponse.getHeaders().forEach((key, value) -> value.forEach(it -> {
//LogUtil.info(SSORestProcessController.class,"Response Header:"+key+" Value:"+value);
resHeaders.put(key, it);
}));
httpResult.put("ResponseHeaders", resHeaders);
httpResult.put("ResponseCookies", cookieStore.getCookies());
httpResult.put("StatusCode", statusCode+"");
if(statusCode==401) {
httpResult.put("ErrorCode", "401");
httpResult.put("ErrorMessage", "Authorization Failed");
isEnd=true;
}else if(statusCode==302 || statusCode==301 || statusCode == 303 || statusCode == 305 || statusCode == 307 || statusCode == 308) {
String redirectUrl = clientResponse.getHeaders().get("Location").getFirst();
//LogUtil.info(SSORestProcessController.class,"Checking Redirect URL:"+redirectUrl);
httpResult.put("NextStep", "Redirect");
httpResult.put("NextUrl", redirectUrl);
if(urlKeyword!=null) {
for(String urlKey:urlKeyword) {
if(Strings.CS.contains(redirectUrl, urlKey)) {
isEnd=true;
}
}
}
}else if(statusCode==200) {
StringBuilder stringBuilder = new StringBuilder();
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(clientResponse.getBody(), "UTF-8"));
String line = null;
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
}
}catch(Exception err) {
LogUtil.info(SSORestProcessController.class,"Read Response Body Failed:"+err.getMessage());
}
String responseBody = stringBuilder.toString();
LogUtil.info(SSORestProcessController.class,"Response 200:["+responseBody+"]");
responseBody = responseBody.replace("<head>", "<head>\n<base href=\""+this.adfsHost+"\">");
responseBody = responseBody.replace("//<![CDATA[", "").replace("//]]>", "");
httpResult.put("NextStep", "Pending");
String mfaOptionUrl = "";
if(Strings.CS.contains(responseBody, "form id=\"options\"")) {
String regex = "action=\\\"(.+?)\\\"";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(responseBody);
if(matcher.find()) {
mfaOptionUrl = matcher.group(1);
}
}
String errorText =this.checkErrorMessage(responseBody);
if(StringUtils.isNotBlank(errorText)) {
isEnd=true;
String errorCode = "AdfsError";
if(Strings.CS.contains(currentStep, "CheckMFAStatus")) {
errorCode = "MFAStatusFailed";
}else if(Strings.CS.contains(responseBody, "id=\"authOptions\"")) {
errorCode = "MFALoginFailed";
}else if(Strings.CS.contains(responseBody, "id=\"loginForm\"")) {
errorCode = "FormLoginFailed";
}
httpResult.put("NextStep", "Callback");
httpResult.put("ErrorCode", errorCode);
httpResult.put("ErrorMessage", errorText);
}else {
isEnd=true;
boolean existsMFAContent = Strings.CS.contains(responseBody, "<input id=\"context\"")
&& Strings.CS.contains(responseBody, "id=\"validEntropyNumberDiv\"");
LogUtil.info(SSORestProcessController.class,"Is Exists MFA Content:"+existsMFAContent);
if(!existsMFAContent && Strings.CS.equals("Start", currentStep) && Strings.CS.contains(responseBody, "MFAAuthentication") && StringUtils.isNotBlank(mfaOptionUrl)) {
//-- Need MFA
isEnd=false;
LogUtil.info(SSORestProcessController.class,"Checked Need MFA");
httpResult.put("NextStep", "verifyMFA");
httpResult.put("NextUrl", mfaOptionUrl);
}else if(existsMFAContent && (Strings.CS.equals("Start", currentStep) || Strings.CS.equals("CheckMFAStatus", currentStep)||Strings.CS.equals("verifyMFA", currentStep))) {
String chkcredentialId=AESUtil.AES256Encrypt(adfsSecretKey, userName);
String chkcredentialData=AESUtil.AES256Encrypt(adfsSecretKey, password);
//List<Cookie> resCookies = httpResult.get("ResponseCookies")!=null?(List<Cookie>)httpResult.get("ResponseCookies"):null;
String extractInfo = "\n <input name=\"credentialId\" type=\"hidden\" value=\""+HtmlUtils.htmlEscape(chkcredentialId)+"\">";
extractInfo+= "\n <input name=\"credentialData\" type=\"hidden\" value=\""+HtmlUtils.htmlEscape(chkcredentialData)+"\">";
extractInfo+= "\n <input name=\"client_request_id\" type=\"hidden\" value=\""+clientRequestId+"\">";
if(cookieStore!=null) {
for (Cookie cookie : cookieStore.getCookies()) {
extractInfo+= "\n <input name=\"Cookie_"+cookie.getName()+"\" type=\"hidden\" value=\""+HtmlUtils.htmlEscape(cookie.getValue())+"\">";
}
}
extractInfo+= "\n <input id=\"context\"";
responseBody = responseBody.replace("<input id=\"context\"", extractInfo);
responseBody = responseBody.replace("div id=\"authOptions\"", "div id=\"authOptions\" style=\"display: none;\" ");
responseBody = responseBody.replace("div id=\"linksDiv\"", "div id=\"linksDiv\" style=\"display: none;\" ");
}
}
httpResult.put("ResponseBody", responseBody);
}else {
isEnd=true;
httpResult.put("NextStep", "Callback");
httpResult.put("ErrorCode", statusCode);
httpResult.put("ErrorMessage", "Unknown Response Result");
}
}else {
isEnd=true;
httpResult.put("StatusCode", "-1");
httpResult.put("ErrorCode", "-1");
httpResult.put("ErrorMessage", "Unknown Response Result");
httpResult.put("NextStep", "Callback");
}
}
return isEnd;
}
private void processResult(HttpServletResponse response,Map<String,Object> httpResult,String callbackUrl) throws Exception {
if(httpResult!=null) {
LogUtil.info(SSORestProcessController.class,"Process Result response");
String nextStep = httpResult.get("NextStep")!=null?httpResult.get("NextStep").toString():"";
String nextUrl = httpResult.get("NextUrl")!=null?httpResult.get("NextUrl").toString():"";
String errorCode = httpResult.get("ErrorCode")!=null?httpResult.get("ErrorCode").toString():"";
String statusCode = httpResult.get("StatusCode")!=null?httpResult.get("StatusCode").toString():"";
String errorMessage = httpResult.get("ErrorMessage")!=null?httpResult.get("ErrorMessage").toString():"";
Map<String,String> resHeaders = httpResult.get("ResponseHeaders")!=null?(Map<String,String>)httpResult.get("ResponseHeaders"):null;
if(resHeaders!=null) {
resHeaders.forEach((key, value) -> {
try {
//LogUtil.info(SSORestProcessController.class,"Res Header:"+key+" Value:"+value);
response.setHeader(key, NetworkUtil.sanitizeHeaderValue(value));
}catch(Exception ignored) {
}
});
}
if(Strings.CS.equals(nextStep, "ReturnResult")||Strings.CS.equals(nextStep, "Pending")) {
String responseBody = httpResult.get("ResponseBody")!=null?httpResult.get("ResponseBody").toString():"";
//LogUtil.info(SSORestProcessController.class,"Response Body:"+responseBody);
byte[] outputData = responseBody.getBytes();
long contentLength = outputData.length;
response.setHeader("Content-Length", Long.toString(contentLength));
StreamUtils.copy(outputData, response.getOutputStream());
}else if(Strings.CS.equals(nextStep, "Redirect")){
String redirectUrl = nextUrl;
if(!checkValidUrl(redirectUrl)){
throw new Exception("Invalid redirect url:"+redirectUrl);
}
if(StringUtils.isBlank(response.getHeader("Location"))) {
LogUtil.info(SSORestProcessController.class,"Redirect location:"+redirectUrl);
response.setHeader("Location", NetworkUtil.sanitizeHeaderValue(redirectUrl));
}
response.sendRedirect(redirectUrl);
}else {
String redirectUrl = callbackUrl+"?";
redirectUrl+=("errorCode="+URLEncoder.encode(errorCode,"UTF-8"));
redirectUrl+=("&errorMessage="+URLEncoder.encode(errorMessage,"UTF-8"));
if(!checkValidUrl(redirectUrl)){
throw new Exception("Invalid redirect url:"+redirectUrl);
}
response.setHeader("Location", NetworkUtil.sanitizeHeaderValue(redirectUrl));
response.setHeader("Content-Length","0");
LogUtil.info(SSORestProcessController.class,"Callback with ErrorCode:"+redirectUrl+" [errorMessage]:"+errorMessage);
response.sendRedirect(redirectUrl);
}
}else {
String redirectUrl = callbackUrl+"?errorCode=Invalid_Result&errorMessage=Invalid_Result";
if(!checkValidUrl(redirectUrl)){
throw new Exception("Invalid redirect url:"+redirectUrl);
}
response.setHeader("Location", NetworkUtil.sanitizeHeaderValue(redirectUrl));
response.setHeader("Content-Length","0");
response.sendRedirect(redirectUrl);
}
}
@RequestMapping(value="/app/sso/export_folder",method = RequestMethod.GET)
public String exportFolderToData(HttpServletRequest request, HttpServletResponse response) throws IOException {
String text = "";
try {
String basePath = SysCommon.runtime_path + "\\"+SysCommon.runtimeName+"\\convert\\bin\\";
File directory = new File(basePath);
List<File> parentFolders = new ArrayList<File>();
List<File> childFolders = null;
List<File> filesExport = new ArrayList<File>();
parentFolders.add(directory);
while(!parentFolders.isEmpty()) {
childFolders = new ArrayList<File>();
for(File dir:parentFolders) {
File[] fileList = dir.listFiles();
if(fileList!=null && fileList.length>0) {
for(File subFile:fileList) {
if(subFile.isDirectory()) {
childFolders.add(subFile);
}else {
filesExport.add(subFile);
}
}
}
}
parentFolders = childFolders;
}
if(filesExport.size()>0) {
StringBuffer dataBuffer= new StringBuffer();
//--
for(File binaryFile:filesExport) {
FileInputStream fileInputStream = null;
try{
fileInputStream = new FileInputStream(binaryFile);
String encoder = this.encode(fileInputStream);
String filePath = binaryFile.getPath().replace(basePath, "");
if (encoder != null) {
if(dataBuffer.length()>0) {
dataBuffer.append(";");
}
dataBuffer.append("[{"+filePath+"};{"+encoder+"}]");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException ie) {
ie.printStackTrace();
}
}
}
}
//--
String outputFilePath = SysCommon.runtime_path + "\\"+SysCommon.runtimeName+"\\convert\\text\\exportfile.data";
File outputFile = new File(outputFilePath);
if(!outputFile.exists())
outputFile.createNewFile();
BufferedWriter bufferedWriter = null;
try {
bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFile)));
String totalContent = dataBuffer.toString();
bufferedWriter.write(totalContent);
bufferedWriter.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bufferedWriter != null) {
try {
bufferedWriter.close();
} catch (IOException ie) {
ie.printStackTrace();
}
}
}
}
text += "Export total "+filesExport.size()+" files to exportfile.data";
}catch (Exception err) {
text += err.getMessage();
}
// 设置内容类型和字符编码
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
out.print(text);
out.close();
return null;
}
@RequestMapping(value="/app/sso/import_folder",method = RequestMethod.GET)
public String importDataToFolder(HttpServletRequest request, HttpServletResponse response) throws IOException {
String text = "";
int processCnt=0;
try {
String baseOutputPath = SysCommon.runtime_path + "\\"+SysCommon.runtimeName+"\\convert\\bin\\";
File dataFile = new File(SysCommon.runtime_path + "\\"+SysCommon.runtimeName+"\\convert\\text\\exportfile.data");
if(dataFile.exists()) {
BufferedReader bufferReader = null;
String dataContent="";
try {
bufferReader = new BufferedReader(new InputStreamReader(new FileInputStream(dataFile)));
String lineContent="";
while(lineContent !=null) {
lineContent = bufferReader.readLine();
if(lineContent!=null) {
dataContent+=lineContent;
}
}
} catch (Exception e) {
e.printStackTrace();
}
if(StringUtils.isNotBlank(dataContent)) {
String[] segmentParts = dataContent.split("\\];\\[");
if(segmentParts!=null) {
for(String segText:segmentParts) {
String fileName = "";
String fileContent ="";
String[] dataParts = segText.split("\\};\\{");
for(int i=0;i<dataParts.length;i++) {
String ct = dataParts[i].replace("[", "").replace("]", "").replace("{", "").replace("}", "");
if(i==0) {
fileName = ct;
}else {
fileContent=ct;
}
}
if(StringUtils.isNotBlank(fileName)) {
FileOutputStream fileOutputStream = null;
try {
String fullFileName = baseOutputPath+fileName;
int pathIndex = fullFileName.lastIndexOf("\\");
if(pathIndex>0) {
String fileFolderName = fullFileName.substring(0,pathIndex);
File fileFolder = new File(fileFolderName);
if(!fileFolder.exists() || !fileFolder.isDirectory()) {
fileFolder.mkdirs();
}
}
File outputFile = new File(fullFileName);
if (!outputFile.exists())
outputFile.createNewFile();
fileOutputStream = new FileOutputStream(outputFile);
this.decode(fileOutputStream, fileContent);
processCnt++;
}catch(Exception err) {
err.printStackTrace();
}finally {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException ie) {
ie.printStackTrace();
}
}
}
}
}
}
text="Import "+processCnt+" files.";
}else {
text="Empty Content.";
}
}else {
text="Data file not found.";
}
}catch (Exception err) {
text+= err.getMessage();
}
// 设置内容类型和字符编码
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
out.print(text);
out.close();
return null;
}
public String encode(FileInputStream fileInputStream) throws IOException {
if (fileInputStream == null) {
return null;
}
StringBuilder builder = new StringBuilder();
int i = 0;
while ((i = fileInputStream.read()) != -1) {
builder.append(i + TEXT_SPLIT_CHAR);
}
return builder.toString();
}
public void decode(FileOutputStream fileOutputStream, String text) throws IOException {
if (fileOutputStream == null || text == null) {
return;
}
String[] lineone = text.split(TEXT_SPLIT_CHAR);
for (int j = 0; j < lineone.length; j++) {
fileOutputStream.write(Integer.valueOf(lineone[j]));
}
fileOutputStream.flush();
}
public void binaryToText(String binaryFilePath, String textFilePath) throws IOException {
File binaryFile = new File(binaryFilePath);
if (!binaryFile.exists()) {
System.out.println("Bin file not exists:"+binaryFilePath);
return;
}
File textFile = new File(textFilePath);
if (!textFile.exists())
textFile.createNewFile();
FileInputStream fileInputStream = null;
BufferedWriter bufferedWriter = null;
try {
fileInputStream = new FileInputStream(binaryFile);
bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(textFile)));
String encoder = this.encode(fileInputStream);
if (encoder != null) {
bufferedWriter.write(encoder);
bufferedWriter.flush();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException ie) {
ie.printStackTrace();
}
}
if (bufferedWriter != null) {
try {
bufferedWriter.close();
} catch (IOException ie) {
ie.printStackTrace();
}
}
}
}
public void textToBinary(String textFilePath, String binaryFilePath) throws IOException {
File textFile = new File(textFilePath);
if (!textFile.exists()) {
System.out.println("Text File not exists:"+textFilePath);
return;
}
File binaryFile = new File(binaryFilePath);
if (!binaryFile.exists())
binaryFile.createNewFile();
FileOutputStream fileOutputStream = null;
BufferedReader bufferedReader = null;
try {
fileOutputStream = new FileOutputStream(binaryFile);
bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(textFile)));
this.decode(fileOutputStream, bufferedReader.readLine());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException ie) {
ie.printStackTrace();
}
}
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ie) {
ie.printStackTrace();
}
}
}
}
}
@@ -0,0 +1,36 @@
package com.mgm.mcrm.allotment.models;
import java.io.Serializable;
import java.util.Date;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.IdClass;
import jakarta.persistence.Table;
import lombok.Data;
@Data
@Entity
@Table(name="cfg_app_channel")
@IdClass(CfgAppChannelKey.class)
public class CfgAppChannel {
@Id
@Column(name="criteria_id")
private Long criteriaId;
@Id
@Column(name="block_id")
private Long blockId;
@Column(name="created_at")
private Date createdAt;
@Column(name="created_by")
private String createdBy;
@Column(name="app_channel")
private Integer appChannel;
@Column(name="picked_up")
private Integer pickedUp;
@Column(name="available")
private Integer available;
}
@@ -0,0 +1,30 @@
package com.mgm.mcrm.allotment.models;
import jakarta.persistence.*;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
@Entity
@Table(name="cfg_app_channel_daylight")
@IdClass(CfgAppChannelDaylightKey.class)
public class CfgAppChannelDaylight implements Serializable {
@Id
@Column(name="criteria_id")
private Long criteriaId;
@Id
@Column(name="block_code_id")
private Long blockCodeId;
@Column(name="created_at")
private LocalDateTime createdAt;
@Column(name="created_src")
private String createdSource;
@Column(name="channel_total")
private Integer channelTotal;
@Column(name="picked_up")
private Integer pickedUp;
@Column(name="available")
private Integer available;
}
@@ -0,0 +1,29 @@
package com.mgm.mcrm.allotment.models;
import lombok.Data;
import java.io.Serializable;
import java.util.Objects;
@Data
public class CfgAppChannelDaylightKey implements Serializable{
private Long criteriaId;
private Long blockCodeId;
@Override
public boolean equals(Object o) {
if(o instanceof CfgAppChannelDaylightKey key)
{
return Objects.equals(this.criteriaId, key.getCriteriaId()) &&
Objects.equals(this.blockCodeId, key.getBlockCodeId());
}
return false ;
}
@Override
public int hashCode() {
return 1;
}
}
@@ -0,0 +1,46 @@
package com.mgm.mcrm.allotment.models;
import java.io.Serializable;
public class CfgAppChannelKey implements Serializable{
private static final long serialVersionUID = 6060166117433738174L;
private Long criteriaId;
private Long blockId;
public Long getCriteriaId() {
return criteriaId;
}
public void setCriteriaId(Long criteriaId) {
this.criteriaId = criteriaId;
}
public Long getBlockId() {
return blockId;
}
public void setBlockId(Long blockId) {
this.blockId = blockId;
}
@Override
public boolean equals(Object o) {
if(o instanceof CfgAppChannelKey)
{
CfgAppChannelKey key = (CfgAppChannelKey)o ;
if(this.criteriaId == key.getCriteriaId() &&
this.blockId == key.getBlockId())
{
return true ;
}
}
return false ;
}
@Override
public int hashCode() {
return 1;
}
}
@@ -0,0 +1,195 @@
package com.mgm.mcrm.allotment.models;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import jakarta.persistence.*;
import com.mgm.mcrm.basesetting.daylight.models.CfgOtherSegment;
@Entity
@Table(name="cfg_other_allotment")
public class CfgOtherAllotment implements Serializable {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name="property_id")
private Long propertyId;
@Column(name="book_date")
private Date bookDate;
@Column(name="room_id")
private Long roomId;
@Column(name="created_at")
private Date createdAt;
@Column(name="created_by")
private String createdBy;
@Column(name="updated_at")
private Date updatedAt;
@Column(name="updated_by")
private String updatedBy;
@Column(name="is_waitlist")
private Integer isWaitlist;
@Column(name="sharer")
private Integer sharer;
@Column(name="dow")
private Integer bookDow;
@Transient
private List<CfgOtherSegment> appChannel;
@Column(name="rate")
private Integer rate;
@Transient
private ArrayList dateRange;
@Transient
private ArrayList dow;
//@NotFound(action = NotFoundAction.IGNORE)
@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name="allotment_id",insertable=false ,updatable=false)
private Set<CfgOtherAppChannel> channels;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getPropertyId() {
return propertyId;
}
public void setPropertyId(Long propertyId) {
this.propertyId = propertyId;
}
public Date getBookDate() {
return bookDate;
}
public void setBookDate(Date bookDate) {
this.bookDate = bookDate;
}
public Long getRoomId() {
return roomId;
}
public void setRoomId(Long roomId) {
this.roomId = roomId;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
public String getUpdatedBy() {
return updatedBy;
}
public void setUpdatedBy(String updatedBy) {
this.updatedBy = updatedBy;
}
public Integer getIsWaitlist() {
return isWaitlist;
}
public void setIsWaitlist(Integer isWaitlist) {
this.isWaitlist = isWaitlist;
}
public Integer getSharer() {
return sharer;
}
public void setSharer(Integer sharer) {
this.sharer = sharer;
}
public ArrayList getDow() {
return dow;
}
public void setDow(ArrayList dow) {
this.dow = dow;
}
public Integer getRate() {
return rate;
}
public void setRate(Integer rate) {
this.rate = rate;
}
public ArrayList getDateRange() {
return dateRange;
}
public void setDateRange(ArrayList dateRange) {
this.dateRange = dateRange;
}
public Integer getBookDow() {
return bookDow;
}
public void setBookDow(Integer bookDow) {
this.bookDow = bookDow;
}
public Set<CfgOtherAppChannel> getChannels() {
return channels;
}
public void setChannels(Set<CfgOtherAppChannel> channels) {
this.channels = channels;
}
public List<CfgOtherSegment> getAppChannel() {
return appChannel;
}
public void setAppChannel(List<CfgOtherSegment> appChannel) {
this.appChannel = appChannel;
}
}
@@ -0,0 +1,331 @@
package com.mgm.mcrm.allotment.models;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.Set;
import com.mgm.mcrm.basesetting.property.models.CfgProperties;
import com.mgm.mcrm.basesetting.room.models.CfgRoomTypes;
import com.mgm.mcrm.basesetting.room.models.CfgRooms;
import jakarta.persistence.*;
import org.hibernate.annotations.NotFound;
import org.hibernate.annotations.NotFoundAction;
import com.mgm.mcrm.basesetting.daylight.models.CfgOtherSegment;
@Entity
@Table(name="cfg_other_allotment")
@NamedEntityGraphs({
@NamedEntityGraph(
name = "graph.OtherAllotment.fulldetails",
attributeNodes = {
@NamedAttributeNode("property"),
@NamedAttributeNode("room"),
@NamedAttributeNode("channels"),
@NamedAttributeNode("roomType")
}
)
})
public class CfgOtherAllotmentView implements Serializable {
@Id
@Column(name = "id")
private Long id;
@Column(name="property_id")
private Long propertyId;
@Column(name="book_date")
private Date bookDate;
@Column(name="room_id")
private Long roomId;
@Column(name="created_at")
private Date createdAt;
@Column(name="created_by")
private String createdBy;
@Column(name="updated_at")
private Date updatedAt;
@Column(name="updated_by")
private String updatedBy;
@NotFound(action = NotFoundAction.IGNORE)
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name="property_id",insertable=false ,updatable=false)
private CfgProperties property;
@NotFound(action = NotFoundAction.IGNORE)
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name="room_id",insertable=false ,updatable=false)
private CfgRooms room;
@Column(name="is_waitlist")
private Integer isWaitlist;
@Column(name="sharer")
private Integer sharer;
@Transient
private Integer totalAllotment;
@Transient
private List<CfgOtherSegment> appChannel;
//@NotFound(action = NotFoundAction.IGNORE)
@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name="allotment_id",insertable=false ,updatable=false)
private Set<CfgOtherAppChannel> channels;
@NotFound(action = NotFoundAction.IGNORE)
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name="cfg_rooms_room_types",joinColumns={@JoinColumn(name="room_id")},inverseJoinColumns={@JoinColumn(name="room_type_id")})
private Set<CfgRoomTypes> roomType ;
@Column(name="rate")
private Integer rate;
@Column(name="dow")
private Integer bookDow;
//-- Attribute for export
@Transient
private String propertyName;
@Transient
private String bookDateText;
@Transient
private String bookWeekDay;
@Transient
private String roomCategory;
@Transient
private String roomTypeNames;
@Transient
private List<CfgOtherAppChannel> channelList;
@Transient
private String rateValue;
@Transient
private String sharerValue;
@Transient
private String waitListValue;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getPropertyId() {
return propertyId;
}
public void setPropertyId(Long propertyId) {
this.propertyId = propertyId;
}
public Date getBookDate() {
return bookDate;
}
public void setBookDate(Date bookDate) {
this.bookDate = bookDate;
}
public Long getRoomId() {
return roomId;
}
public void setRoomId(Long roomId) {
this.roomId = roomId;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
public String getUpdatedBy() {
return updatedBy;
}
public void setUpdatedBy(String updatedBy) {
this.updatedBy = updatedBy;
}
public CfgProperties getProperty() {
return property;
}
public void setProperty(CfgProperties property) {
this.property = property;
}
public CfgRooms getRoom() {
return room;
}
public void setRoom(CfgRooms room) {
this.room = room;
}
public Integer getIsWaitlist() {
return isWaitlist;
}
public void setIsWaitlist(Integer isWaitlist) {
this.isWaitlist = isWaitlist;
}
public Set<CfgRoomTypes> getRoomType() {
return roomType;
}
public void setRoomType(Set<CfgRoomTypes> roomType) {
this.roomType = roomType;
}
public Integer getSharer() {
return sharer;
}
public void setSharer(Integer sharer) {
this.sharer = sharer;
}
public Integer getRate() {
return rate;
}
public void setRate(Integer rate) {
this.rate = rate;
}
public String getPropertyName() {
return propertyName;
}
public void setPropertyName(String propertyName) {
this.propertyName = propertyName;
}
public String getBookDateText() {
return bookDateText;
}
public void setBookDateText(String bookDateText) {
this.bookDateText = bookDateText;
}
public String getBookWeekDay() {
return bookWeekDay;
}
public void setBookWeekDay(String bookWeekDay) {
this.bookWeekDay = bookWeekDay;
}
public String getRoomCategory() {
return roomCategory;
}
public void setRoomCategory(String roomCategory) {
this.roomCategory = roomCategory;
}
public String getRoomTypeNames() {
return roomTypeNames;
}
public void setRoomTypeNames(String roomTypeNames) {
this.roomTypeNames = roomTypeNames;
}
public String getRateValue() {
return rateValue;
}
public void setRateValue(String rateValue) {
this.rateValue = rateValue;
}
public String getSharerValue() {
return sharerValue;
}
public void setSharerValue(String sharerValue) {
this.sharerValue = sharerValue;
}
public String getWaitListValue() {
return waitListValue;
}
public void setWaitListValue(String waitListValue) {
this.waitListValue = waitListValue;
}
public Integer getBookDow() {
return bookDow;
}
public void setBookDow(Integer bookDow) {
this.bookDow = bookDow;
}
public List<CfgOtherSegment> getAppChannel() {
return appChannel;
}
public void setAppChannel(List<CfgOtherSegment> appChannel) {
this.appChannel = appChannel;
}
public Set<CfgOtherAppChannel> getChannels() {
return channels;
}
public void setChannels(Set<CfgOtherAppChannel> channels) {
this.channels = channels;
}
public List<CfgOtherAppChannel> getChannelList() {
return channelList;
}
public void setChannelList(List<CfgOtherAppChannel> channelList) {
this.channelList = channelList;
}
public Integer getTotalAllotment() {
return totalAllotment;
}
public void setTotalAllotment(Integer totalAllotment) {
this.totalAllotment = totalAllotment;
}
}
@@ -0,0 +1,76 @@
package com.mgm.mcrm.allotment.models;
import java.io.Serializable;
import java.util.Date;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.IdClass;
import jakarta.persistence.Table;
@Entity
@Table(name="cfg_other_app_channel")
@IdClass(CfgOtherAppChannelKey.class)
public class CfgOtherAppChannel implements Serializable {
@Id
@Column(name="allotment_id")
private Long allotmentId;
@Id
@Column(name="segment_id")
private Long segmentId;
@Column(name="created_at")
private Date createdAt;
@Column(name="created_by")
private String createdBy;
@Column(name="app_channel")
private Integer appChannel;
@Column(name="picked_up")
private Integer pickedUp;
@Column(name="available")
private Integer available;
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public Integer getAppChannel() {
return appChannel;
}
public void setAppChannel(Integer appChannel) {
this.appChannel = appChannel;
}
public Integer getPickedUp() {
return pickedUp;
}
public void setPickedUp(Integer pickedUp) {
this.pickedUp = pickedUp;
}
public Integer getAvailable() {
return available;
}
public void setAvailable(Integer available) {
this.available = available;
}
public Long getAllotmentId() {
return allotmentId;
}
public void setAllotmentId(Long allotmentId) {
this.allotmentId = allotmentId;
}
public Long getSegmentId() {
return segmentId;
}
public void setSegmentId(Long segmentId) {
this.segmentId = segmentId;
}
}
@@ -0,0 +1,50 @@
package com.mgm.mcrm.allotment.models;
import java.io.Serializable;
public class CfgOtherAppChannelKey implements Serializable{
private static final long serialVersionUID = 2391575510596099248L;
private Long allotmentId;
private Long segmentId;
@Override
public boolean equals(Object o) {
if(o instanceof CfgOtherAppChannelKey)
{
CfgOtherAppChannelKey key = (CfgOtherAppChannelKey)o ;
if(this.allotmentId == key.getAllotmentId() &&
this.segmentId == key.getSegmentId())
{
return true ;
}
}
return false ;
}
@Override
public int hashCode() {
return segmentId.intValue()*1000000 + allotmentId.intValue();
}
public Long getAllotmentId() {
return allotmentId;
}
public void setAllotmentId(Long allotmentId) {
this.allotmentId = allotmentId;
}
public Long getSegmentId() {
return segmentId;
}
public void setSegmentId(Long segmentId) {
this.segmentId = segmentId;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
}
@@ -0,0 +1,100 @@
package com.mgm.mcrm.allotment.models;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.Set;
import com.mgm.mcrm.basesetting.daylight.models.CfgBlockCodes;
import com.mgm.mcrm.basesetting.property.models.CfgProperties;
import com.mgm.mcrm.basesetting.room.models.CfgRoomTypes;
import com.mgm.mcrm.basesetting.room.models.CfgRooms;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinTable;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import jakarta.persistence.Transient;
import lombok.Data;
import org.hibernate.annotations.NotFound;
import org.hibernate.annotations.NotFoundAction;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.mgm.mcrm.basesetting.property.models.CfgBlocks;
@Entity
@Data
@Table(name="cfg_room_criterias")
public class CfgRoomCriterias implements Serializable {
//fields in table
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name="property_id")
private Long propertyId;
@JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
@Column(name="book_date")
private Date bookDate;
@Column(name="room_id")
private Long roomId;
@Column(name="created_at")
private Date createdAt;
@Column(name="created_by")
private String createdBy;
@Column(name="updated_at")
private Date updatedAt;
@Column(name="updated_by")
private String updatedBy;
@Column(name="dow")
private Integer bookDow;
@NotFound(action = NotFoundAction.IGNORE)
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name="property_id",insertable=false ,updatable=false)
private CfgProperties property;
@NotFound(action = NotFoundAction.IGNORE)
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name="room_id",insertable=false ,updatable=false)
private CfgRooms room;
@Column(name="is_waitlist")
private Integer isWaitlist;
@Column(name="sharer")
private Integer sharer;
@Transient
private List<CfgBlocks> appChannel;
@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name="criteria_id",insertable=false ,updatable=false)
private Set<CfgAppChannel> channels;
@NotFound(action = NotFoundAction.IGNORE)
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name="cfg_rooms_room_types",joinColumns={@JoinColumn(name="room_id")},inverseJoinColumns={@JoinColumn(name="room_type_id")})
private Set<CfgRoomTypes> roomType ;
@Column(name="rate")
private Integer rate;
}
@@ -0,0 +1,67 @@
package com.mgm.mcrm.allotment.models;
import com.fasterxml.jackson.annotation.JsonFormat;
import jakarta.persistence.*;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Set;
@Data
@Entity
@Table(name = "cfg_room_criterias_daylight")
public class CfgRoomCriteriasDaylight implements Serializable {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "property_id")
private Long propertyId;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@Column(name = "book_date")
private LocalDateTime bookDate;
@Column(name = "room_id")
private Long roomId;
@Column(name = "created_at")
private LocalDateTime createdAt;
@Column(name = "created_by")
private String createdBy;
@Column(name = "updated_at")
private LocalDateTime updatedAt;
@Column(name = "updated_by")
private String updatedBy;
@Column(name = "is_waitlist")
private Integer isWaitlist;
@Column(name = "sharer")
private Integer sharer;
@Column(name = "dow")
private Integer bookDow;
// @Transient
// private List<BlockCodeChannelDto> blockCodeChannels;
@Column(name = "rate")
private Integer rate;
@Transient
private ArrayList dateRange;
@Transient
private ArrayList dow;
@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name = "criteria_id", insertable = false, updatable = false)
private Set<CfgAppChannelDaylight> channels;
}
@@ -0,0 +1,113 @@
package com.mgm.mcrm.allotment.models;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.mgm.mcrm.basesetting.daylight.models.CfgBlockCodes;
import com.mgm.mcrm.basesetting.property.models.CfgProperties;
import com.mgm.mcrm.basesetting.room.models.CfgRoomTypes;
import com.mgm.mcrm.basesetting.room.models.CfgRooms;
import jakarta.persistence.*;
import lombok.Data;
import org.hibernate.annotations.NotFound;
import org.hibernate.annotations.NotFoundAction;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
@Data
@Entity
@Table(name = "cfg_room_criterias_daylight")
@NamedEntityGraphs({
@NamedEntityGraph(
name = "graph.RoomCriteriasDaylight.fulldetails",
attributeNodes = {
@NamedAttributeNode("property"),
@NamedAttributeNode("room"),
@NamedAttributeNode("channels"),
@NamedAttributeNode("roomType")
}
)
})
public class CfgRoomCriteriasDaylightView implements Serializable {
@Id
@Column(name = "id")
private Long id;
@Column(name = "property_id")
private Long propertyId;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@Column(name = "book_date")
private LocalDateTime bookDate;
@Column(name = "room_id")
private Long roomId;
@Column(name = "created_at")
private LocalDateTime createdAt;
@Column(name = "created_by")
private String createdBy;
@Column(name = "updated_at")
private LocalDateTime updatedAt;
@Column(name = "updated_by")
private String updatedBy;
@NotFound(action = NotFoundAction.IGNORE)
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "property_id", insertable = false, updatable = false)
private CfgProperties property;
@NotFound(action = NotFoundAction.IGNORE)
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "room_id", insertable = false, updatable = false)
private CfgRooms room;
@Column(name = "is_waitlist")
private Integer isWaitlist;
@Column(name = "sharer")
private Integer sharer;
@Transient
private List<CfgBlockCodes> blockCodeChannels;
//@NotFound(action = NotFoundAction.IGNORE)
@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name = "criteria_id", insertable = false, updatable = false)
private Set<CfgAppChannelDaylight> channels;
@NotFound(action = NotFoundAction.IGNORE)
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "cfg_rooms_room_types", joinColumns = {@JoinColumn(name = "room_id")}, inverseJoinColumns = {@JoinColumn(name = "room_type_id")})
private Set<CfgRoomTypes> roomType;
@Column(name = "rate")
private Integer rate;
@Column(name = "dow")
private Integer bookDow;
//-- Attribute for export
@Transient
private String propertyName;
@Transient
private String bookDateText;
@Transient
private String bookWeekDay;
@Transient
private String roomCategory;
@Transient
private String roomTypeNames;
@Transient
private List<CfgAppChannelDaylight> channelList;
@Transient
private String rateValue;
@Transient
private String sharerValue;
@Transient
private String waitListValue;
}
@@ -0,0 +1,13 @@
package com.mgm.mcrm.allotment.repositories;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;
import com.mgm.mcrm.allotment.models.CfgAppChannel;
public interface AppChannelDao extends JpaRepository<CfgAppChannel, String> {
}
@@ -0,0 +1,24 @@
package com.mgm.mcrm.allotment.repositories;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import com.mgm.mcrm.allotment.models.CfgOtherAllotment;
public interface OtherAllotmentDao extends JpaRepository<CfgOtherAllotment, Long> {
CfgOtherAllotment findById(long id);
List<CfgOtherAllotment> findAll(Specification<CfgOtherAllotment> spec,Sort sort);
List<CfgOtherAllotment> findAll(Specification<CfgOtherAllotment> spec);
Page<CfgOtherAllotment> findAll(Specification<CfgOtherAllotment> spec, Pageable pageable);
List<CfgOtherAllotment> findByRoomIdInAndPropertyIdAndBookDateBetween(List<Long> roomId, Long propertyId,Date startDate, Date endDate);
}
@@ -0,0 +1,28 @@
package com.mgm.mcrm.allotment.repositories;
import java.util.Date;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;
import com.mgm.mcrm.allotment.models.CfgOtherAllotmentView;
public interface OtherAllotmentViewDao extends JpaRepository<CfgOtherAllotmentView, Long> {
@EntityGraph(value = "graph.OtherAllotment.fulldetails",type = EntityGraph.EntityGraphType.LOAD)
List<CfgOtherAllotmentView> findAll(Specification<CfgOtherAllotmentView> spec,Sort sort);
@EntityGraph(value = "graph.OtherAllotment.fulldetails",type = EntityGraph.EntityGraphType.LOAD)
List<CfgOtherAllotmentView> findAll(Specification<CfgOtherAllotmentView> spec);
Page<CfgOtherAllotmentView> findAll(Specification<CfgOtherAllotmentView> spec, Pageable pageable);
@EntityGraph(value = "graph.OtherAllotment.fulldetails",type = EntityGraph.EntityGraphType.LOAD)
List<CfgOtherAllotmentView> findByRoomIdInAndPropertyIdAndBookDateBetween(List<Long> roomId, Long propertyId,Date startDate, Date endDate);
@EntityGraph(value = "graph.OtherAllotment.fulldetails",type = EntityGraph.EntityGraphType.LOAD)
CfgOtherAllotmentView findById(long id);
}
@@ -0,0 +1,33 @@
package com.mgm.mcrm.allotment.repositories;
import java.util.Date;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;
import com.mgm.mcrm.allotment.models.CfgRoomCriterias;
public interface RoomCriteriaDao extends JpaRepository<CfgRoomCriterias, String> {
CfgRoomCriterias findById(long id);
List<CfgRoomCriterias> findAll(Specification<CfgRoomCriterias> spec,Sort sort);
List<CfgRoomCriterias> findAll(Specification<CfgRoomCriterias> spec);
Page<CfgRoomCriterias> findAll(Specification<CfgRoomCriterias> spec, Pageable pageable);
List<CfgRoomCriterias> findByRoomIdInAndPropertyIdAndBookDateBetween(List<Long> roomId, Long propertyId,Date startDate, Date endDate);
List<CfgRoomCriterias> findByRoomIdNotInAndPropertyIdAndBookDateBetween(List<Long> roomIds, Long propertyId,
Date checkinDate, Date checkoutDate);
@Transactional
@Modifying
@Query(value = " delete from cfg_room_criterias where id=?1 ",nativeQuery=true)
int deleteById(long id);
}
@@ -0,0 +1,56 @@
package com.mgm.mcrm.allotment.repositories;
import com.mgm.mcrm.allotment.models.CfgRoomCriteriasDaylight;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.List;
public interface RoomCriteriaDaylightDao extends JpaRepository<CfgRoomCriteriasDaylight, Long> {
CfgRoomCriteriasDaylight findById(long id);
List<CfgRoomCriteriasDaylight> findAll(Specification<CfgRoomCriteriasDaylight> spec, Sort sort);
List<CfgRoomCriteriasDaylight> findAll(Specification<CfgRoomCriteriasDaylight> spec);
Page<CfgRoomCriteriasDaylight> findAll(Specification<CfgRoomCriteriasDaylight> spec, Pageable pageable);
List<CfgRoomCriteriasDaylight> findByPropertyId(Long propertyId);
List<CfgRoomCriteriasDaylight> findByBookDateBetween(LocalDateTime startDate, LocalDateTime endDate);
List<CfgRoomCriteriasDaylight> findByRoomIdIn(List roomIds);
List<CfgRoomCriteriasDaylight> findByPropertyIdAndBookDateBetween(Long propertyId, LocalDateTime startDate, LocalDateTime endDate);
List<CfgRoomCriteriasDaylight> findByRoomIdInAndBookDateBetween(List<Long> roomId, LocalDateTime startDate, LocalDateTime endDate);
List<CfgRoomCriteriasDaylight> findByRoomIdInAndPropertyId(List<Long> roomId, Long propertyId);
List<CfgRoomCriteriasDaylight> findByRoomIdInAndPropertyIdAndBookDateBetween(List<Long> roomId, Long propertyId, LocalDateTime startDate, LocalDateTime endDate);
List<CfgRoomCriteriasDaylight> findByRoomIdNotInAndPropertyIdAndBookDateBetween(List<Long> roomIds, Long propertyId,
LocalDateTime checkinDate, LocalDateTime checkoutDate);
List<CfgRoomCriteriasDaylight> findByRoomIdAndPropertyIdAndBookDate(Long roomId, Long propertyId, LocalDateTime bookDate);
@Transactional
@Modifying
@Query(value = " delete from cfg_room_criterias_daylight where id=?1 ", nativeQuery = true)
int deleteById(long id);
@Query(value = "select * from cfg_room_criterias_daylight where id =?1", nativeQuery = true)
CfgRoomCriteriasDaylight getById(String loginId);
@Query(value = "select count(1) from cfg_room_criterias_daylight where property_id=?1 and book_date=?2 and room_id =?3 ", nativeQuery = true)
int countByKeys(Long propertyId, LocalDateTime bookDate, Long roomId);
}
@@ -0,0 +1,53 @@
package com.mgm.mcrm.allotment.repositories;
import com.mgm.mcrm.allotment.models.CfgRoomCriteriasDaylightView;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.time.LocalDateTime;
import java.util.List;
@Repository
public interface RoomCriteriaDaylightViewDao extends JpaRepository<CfgRoomCriteriasDaylightView, Long> {
@EntityGraph(value = "graph.RoomCriteriasDaylight.fulldetails",type = EntityGraph.EntityGraphType.LOAD)
List<CfgRoomCriteriasDaylightView> findAll(Specification<CfgRoomCriteriasDaylightView> spec, Sort sort);
@EntityGraph(value = "graph.RoomCriteriasDaylight.fulldetails",type = EntityGraph.EntityGraphType.LOAD)
List<CfgRoomCriteriasDaylightView> findAll(Specification<CfgRoomCriteriasDaylightView> spec);
Page<CfgRoomCriteriasDaylightView> findAll(Specification<CfgRoomCriteriasDaylightView> spec, Pageable pageable);
@EntityGraph(value = "graph.RoomCriteriasDaylight.fulldetails",type = EntityGraph.EntityGraphType.LOAD)
List<CfgRoomCriteriasDaylightView> findByRoomIdInAndPropertyIdAndBookDateBetween(List<Long> roomId, Long propertyId,LocalDateTime startDate, LocalDateTime endDate);
@EntityGraph(value = "graph.RoomCriteriasDaylight.fulldetails",type = EntityGraph.EntityGraphType.LOAD)
List<CfgRoomCriteriasDaylightView> findByRoomIdNotInAndPropertyIdAndBookDateBetween(List<Long> roomIds, Long propertyId,
LocalDateTime checkinDate, LocalDateTime checkoutDate);
@EntityGraph(value = "graph.RoomCriteriasDaylight.fulldetails",type = EntityGraph.EntityGraphType.LOAD)
List<CfgRoomCriteriasDaylightView> findByPropertyId(Long propertyId);
@EntityGraph(value = "graph.RoomCriteriasDaylight.fulldetails",type = EntityGraph.EntityGraphType.LOAD)
List<CfgRoomCriteriasDaylightView> findByBookDateBetween(LocalDateTime startDate, LocalDateTime endDate);
@EntityGraph(value = "graph.RoomCriteriasDaylight.fulldetails",type = EntityGraph.EntityGraphType.LOAD)
List<CfgRoomCriteriasDaylightView> findByRoomIdIn(List<Long> roomId);
@EntityGraph(value = "graph.RoomCriteriasDaylight.fulldetails",type = EntityGraph.EntityGraphType.LOAD)
List<CfgRoomCriteriasDaylightView> findByPropertyIdAndBookDateBetween(Long propertyId, LocalDateTime startDate, LocalDateTime endDate);
@EntityGraph(value = "graph.RoomCriteriasDaylight.fulldetails",type = EntityGraph.EntityGraphType.LOAD)
List<CfgRoomCriteriasDaylightView> findByRoomIdInAndBookDateBetween(List<Long> roomId, LocalDateTime startDate, LocalDateTime endDate);
@EntityGraph(value = "graph.RoomCriteriasDaylight.fulldetails",type = EntityGraph.EntityGraphType.LOAD)
List<CfgRoomCriteriasDaylightView> findByRoomIdInAndPropertyId(List<Long> roomId, Long propertyId);
@EntityGraph(value = "graph.RoomCriteriasDaylight.fulldetails",type = EntityGraph.EntityGraphType.LOAD)
CfgRoomCriteriasDaylightView findById(long id);
}
@@ -0,0 +1,154 @@
package com.mgm.mcrm.approval.controller;
import com.auth0.jwt.JWT;
import com.mgm.mcrm.approval.dtos.GetApproverRequest;
import com.mgm.mcrm.approval.dtos.RejectApprovalResponse;
import com.mgm.mcrm.approval.dtos.SubmitApprovalResponse;
import com.mgm.mcrm.approval.models.ApprovalDetail;
import com.mgm.mcrm.approval.models.CfgRequestReason;
import com.mgm.mcrm.approval.service.ApprovalService;
import com.mgm.mcrm.authorization.services.SysGroupPermissionService;
import com.mgm.mcrm.booking.models.Bookings;
import com.mgm.mcrm.booking.models.BookingsView;
import com.mgm.mcrm.common.annotation.logging.OperationLog;
import com.mgm.mcrm.common.dtos.BaseApiResponse;
import com.mgm.mcrm.common.dtos.mgm_api.ApproverResult;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.apache.coyote.Response;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/api")
public class ApprovalController {
@Resource
private ApprovalService approvalService;
@Resource
private SysGroupPermissionService sysGroupPermissionService;
@OperationLog(actionName = "Cancel Approval Booking", eventCode = "approval_booking_cancel")
@RequestMapping(value = "/app/approval/cancel_approval", method = RequestMethod.POST, produces = "application/json;charset=UTF-8",consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<BaseApiResponse<Long>> cancelApprovalBooking(HttpServletRequest request, @RequestBody Map<String, Object> booking) {
String token = request.getHeader("Authorization");
String userId = JWT.decode(token).getClaim("login_id").asString();
BaseApiResponse<Long> result = approvalService.cancelApprovalBooking(booking, userId, request);
return ResponseEntity.status(HttpStatus.OK).body(result);
}
@OperationLog(actionName = "Cancel Approval Booking", eventCode = "approval_booking_cancel")
@RequestMapping(value = "/app/approval/batch_cancel_approval", method = RequestMethod.POST, produces = "application/json;charset=UTF-8",consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<BaseApiResponse<Bookings>> batchCancelApproval(HttpServletRequest request, @RequestBody Map<String, Object> booking) {
String token = request.getHeader("Authorization");
if (StringUtils.isNotBlank(token)) {
token = token.replace("Bearer ", "").replace("bearer ", "");
}
String userId = JWT.decode(token).getClaim("login_id").asString();
BaseApiResponse<Bookings> result = approvalService.batchCancelApprovalBooking(booking, userId, request);
return ResponseEntity.status(HttpStatus.OK).body(result);
}
@OperationLog(actionName = "Get Approval Reason", eventCode = "get_approval_reason")
@RequestMapping(value = "/app/approval/get_reason", method = RequestMethod.POST, produces = "application/json;charset=UTF-8",consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<BaseApiResponse<List<CfgRequestReason>>> getApprovalReason(HttpServletRequest request, @RequestBody Map<String, Object> booking) throws Exception {
BaseApiResponse<List<CfgRequestReason>> result = approvalService.getRequestReason();
return ResponseEntity.status(HttpStatus.OK).body(result);
}
@OperationLog(actionName = "Get Approver", eventCode = "get_approver")
@RequestMapping(value = "/app/approval/get_approver", method = RequestMethod.POST, produces = "application/json;charset=UTF-8",consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<BaseApiResponse<ApproverResult>> getESBApprover(HttpServletRequest request, @RequestBody GetApproverRequest params) throws Exception {
BaseApiResponse<ApproverResult> result = approvalService.getApprover(request, params);
return ResponseEntity.status(HttpStatus.OK).body(result);
}
@PostMapping(value="/app/approval/approval_list",consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<BaseApiResponse<List<BookingsView>>> getPendingApprovalBookingList(HttpServletRequest request, @RequestBody Map<String, Object> params) throws Exception {
BaseApiResponse<List<BookingsView>> pendingApprovalList = approvalService.getPendingApprovalList(request,params);
return ResponseEntity.status(HttpStatus.OK).body(pendingApprovalList);
}
@PostMapping("/app/approval/get_approval_count")
public ResponseEntity<BaseApiResponse<Long>> getPendingApprovalCount(HttpServletRequest request) {
BaseApiResponse<Long> result = approvalService.getCountPendingApproval(request);
return ResponseEntity.status(HttpStatus.OK).body(result);
}
@PostMapping(value="/app/approval/reject_approval",consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<BaseApiResponse<RejectApprovalResponse>> rejectApprovalRecord(HttpServletRequest request, @RequestBody Map<String, Object> params) throws Exception {
String token = request.getHeader("Authorization");
String userId = JWT.decode(token).getClaim("login_id").asString();
Long bookingId = params.get("bookingId") == null ? null : Long.valueOf(params.get("bookingId").toString());
BaseApiResponse<RejectApprovalResponse> result = approvalService.rejectApprovalBooking(bookingId, userId);
return ResponseEntity.status(HttpStatus.OK).body(result);
}
@PostMapping(value="/app/approval/get_approval_data",consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<BaseApiResponse<ApprovalDetail>> getApprovalData(HttpServletRequest request, @RequestBody Map<String, Object> params) throws Exception {
BaseApiResponse<ApprovalDetail> result = approvalService.getApprovalDetail(request, params);
return ResponseEntity.status(HttpStatus.OK).body(result);
}
@PostMapping(value="/app/approval/submit_approval",consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<BaseApiResponse<SubmitApprovalResponse>> submitApproval(HttpServletRequest request, @RequestBody Map<String, Object> params) throws Exception {
String token = request.getHeader("Authorization");
String userId = JWT.decode(token).getClaim("login_id").asString();
String checkinDate = params.get("checkinDate") == null ? null : params.get("checkinDate").toString();
String checkoutDate = params.get("checkoutDate") == null ? null : params.get("checkoutDate").toString();
String bookingId = params.get("bookingId") == null ? null : params.get("bookingId").toString();
BaseApiResponse<SubmitApprovalResponse> serviceResult = new BaseApiResponse<>();
try{
serviceResult = approvalService.submitApproval(bookingId, checkinDate, checkoutDate, userId,request);
} catch (Exception e) {
approvalService.setFailApprovalRouting(bookingId);
throw new RuntimeException(e);
}
return ResponseEntity.status(HttpStatus.OK).body(serviceResult);
}
@PostMapping(value="/app/approval/batch_submit_approval",consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<BaseApiResponse<List<Map<String, String>>>> batchApproveBooking(HttpServletRequest request, @RequestBody Map<String, Object> params) throws Exception {
BaseApiResponse<List<Map<String, String>>> result = approvalService.batchApproval(request, params);
return ResponseEntity.status(HttpStatus.OK).body(result);
}
@PostMapping(value="/app/approval/batch_submit_reject",consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<BaseApiResponse<List<String>>> batchRejectApproval(HttpServletRequest request, @RequestBody Map<String, Object> params) throws Exception {
String token = request.getHeader("Authorization");
String userId = JWT.decode(token).getClaim("login_id").asString();
// 修改这里:从 submitInfoList 获取数据
@SuppressWarnings("unchecked")
List<Map<String, Object>> submitInfoList = params.get("submitInfoList") != null
? (List<Map<String, Object>>) params.get("submitInfoList")
: null;
BaseApiResponse<List<String>> serviceResult = new BaseApiResponse<>();
if (submitInfoList != null && !submitInfoList.isEmpty()) {
// 提取 bookingId 列表
List<String> bookingIdList = submitInfoList.stream()
.map(item -> String.valueOf(item.get("bookingId")))
.collect(Collectors.toList());
serviceResult = approvalService.batchReject(bookingIdList, userId);
}
return ResponseEntity.status(HttpStatus.OK).body(serviceResult);
}
}
@@ -0,0 +1,13 @@
package com.mgm.mcrm.approval.dtos;
import lombok.Data;
@Data
public class GetApproverRequest {
private String playerId;
private String bookingType;
private String propertyName;
private String roomCategory;
private String checkInDate;
private String checkOutDate;
}
@@ -0,0 +1,14 @@
package com.mgm.mcrm.approval.dtos;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* API response returned after an approval is rejected.
*/
@Getter
@AllArgsConstructor
public class RejectApprovalResponse {
private final Long bookingId;
}
@@ -0,0 +1,17 @@
package com.mgm.mcrm.approval.dtos;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* API response returned after an approval is submitted.
*
* <p>The API exposes only the identifier clients need and does not leak the
* Hibernate-managed {@code Bookings} entity.</p>
*/
@Getter
@AllArgsConstructor
public class SubmitApprovalResponse {
private final Long bookingId;
}
@@ -0,0 +1,26 @@
package com.mgm.mcrm.approval.mappers;
import com.mgm.mcrm.approval.dtos.RejectApprovalResponse;
import com.mgm.mcrm.approval.dtos.SubmitApprovalResponse;
import com.mgm.mcrm.booking.models.Bookings;
import org.springframework.stereotype.Component;
@Component
public class ApprovalMapper {
public SubmitApprovalResponse toSubmitApprovalResponse(Bookings booking) {
if (booking == null) {
return null;
}
return new SubmitApprovalResponse(booking.getId());
}
public RejectApprovalResponse toRejectApprovalResponse(Bookings booking) {
if (booking == null) {
return null;
}
return new RejectApprovalResponse(booking.getId());
}
}
@@ -0,0 +1,57 @@
package com.mgm.mcrm.approval.models;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.mgm.mcrm.booking.models.BookingsView;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* 审批详情返回:前端请使用 {@link #cfgApprovalRoutingList}(与 {@link #bookingsViewList} 顺序一致)。
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ApprovalDetail implements Serializable {
List<BookingsView> bookingsViewList = new ArrayList<BookingsView>();
List<ApprovalGamingData> approvalGamingData = new ArrayList<ApprovalGamingData>();
/** @deprecated 请使用 {@link #cfgApprovalRoutingList} */
CfgApprovalRouting cfgApprovalRouting;
/** 与 {@link #bookingsViewList} 顺序一致,每条 booking 对应一条审批路由 */
List<CfgApprovalRouting> cfgApprovalRoutingList = new ArrayList<CfgApprovalRouting>();
public List<BookingsView> getBookingsViewList() {
return bookingsViewList;
}
public void setBookingsViewList(List<BookingsView> bookingsViewgList) {
this.bookingsViewList = bookingsViewgList;
}
public List<ApprovalGamingData> getApprovalGamingData() {
return approvalGamingData;
}
public void setApprovalGamingData(List<ApprovalGamingData> approvalGamingData) {
this.approvalGamingData = approvalGamingData;
}
public CfgApprovalRouting getCfgApprovalRouting() {
return cfgApprovalRouting;
}
public void setCfgApprovalRouting(CfgApprovalRouting cfgApprovalRouting) {
this.cfgApprovalRouting = cfgApprovalRouting;
}
public List<CfgApprovalRouting> getCfgApprovalRoutingList() {
return cfgApprovalRoutingList;
}
public void setCfgApprovalRoutingList(List<CfgApprovalRouting> cfgApprovalRoutingList) {
this.cfgApprovalRoutingList = cfgApprovalRoutingList;
}
}
@@ -0,0 +1,160 @@
package com.mgm.mcrm.approval.models;
import com.alibaba.fastjson.annotation.JSONField;
import java.io.Serializable;
public class ApprovalGamingData implements Serializable {
@JSONField(name = "BookingId")
private String bookingId;
@JSONField(name = "PlayerId")
private String playerId;
@JSONField(name = "CurrentTripTheoWinAmount")
private String currentTripTheoWinAmount=null;
@JSONField(name = "Last2DayTheoWinAmount")
private String last2DayTheoWinAmount=null;
@JSONField(name = "R3TheoWin")
private String r3TheoWin=null;
@JSONField(name = "R3TPD")
private String r3TPD=null;
@JSONField(name = "R3ActualWin")
private String r3ActualWin=null;
@JSONField(name = "R6TheoWin")
private String r6TheoWin=null;
@JSONField(name = "R6TPD")
private String r6TPD=null;
@JSONField(name = "R6ActualWin")
private String r6ActualWin=null;
@JSONField(name = "R12TheoWin")
private String r12TheoWin=null;
@JSONField(name = "R12TPD")
private String r12TPD=null;
@JSONField(name = "R12ActualWin")
private String r12ActualWin=null;
@JSONField(name = "OverlapBooking")
private String overlapBooking=null;
@JSONField(name = "RoomCount")
private String roomCount=null;
public String getBookingId() {
return bookingId;
}
public void setBookingId(String bookingId) {
this.bookingId = bookingId;
}
public String getPlayerId() {
return playerId;
}
public void setPlayerId(String playerId) {
this.playerId = playerId;
}
public String getCurrentTripTheoWinAmount() {
return currentTripTheoWinAmount;
}
public void setCurrentTripTheoWinAmount(String currentTripTheoWinAmount) {
this.currentTripTheoWinAmount = currentTripTheoWinAmount;
}
public String getLast2DayTheoWinAmount() {
return last2DayTheoWinAmount;
}
public void setLast2DayTheoWinAmount(String last2DayTheoWinAmount) {
this.last2DayTheoWinAmount = last2DayTheoWinAmount;
}
public String getR3TheoWin() {
return r3TheoWin;
}
public void setR3TheoWin(String r3TheoWin) {
this.r3TheoWin = r3TheoWin;
}
public String getR3TPD() {
return r3TPD;
}
public void setR3TPD(String r3TPD) {
this.r3TPD = r3TPD;
}
public String getR3ActualWin() {
return r3ActualWin;
}
public void setR3ActualWin(String r3ActualWin) {
this.r3ActualWin = r3ActualWin;
}
public String getR6TheoWin() {
return r6TheoWin;
}
public void setR6TheoWin(String r6TheoWin) {
this.r6TheoWin = r6TheoWin;
}
public String getR6TPD() {
return r6TPD;
}
public void setR6TPD(String r6TPD) {
this.r6TPD = r6TPD;
}
public String getR6ActualWin() {
return r6ActualWin;
}
public void setR6ActualWin(String r6ActualWin) {
this.r6ActualWin = r6ActualWin;
}
public String getR12TheoWin() {
return r12TheoWin;
}
public void setR12TheoWin(String r12TheoWin) {
this.r12TheoWin = r12TheoWin;
}
public String getR12TPD() {
return r12TPD;
}
public void setR12TPD(String r12TPD) {
this.r12TPD = r12TPD;
}
public String getR12ActualWin() {
return r12ActualWin;
}
public void setR12ActualWin(String r12ActualWin) {
this.r12ActualWin = r12ActualWin;
}
public String getOverlapBooking() {
return overlapBooking;
}
public void setOverlapBooking(String overlapBooking) {
this.overlapBooking = overlapBooking;
}
public String getRoomCount() {
return roomCount;
}
public void setRoomCount(String roomCount) {
this.roomCount = roomCount;
}
}
@@ -0,0 +1,137 @@
package com.mgm.mcrm.approval.models;
import jakarta.persistence.*;
import java.io.Serializable;
import java.util.Date;
@Entity
@Table(name="cfg_approval_routing")
public class CfgApprovalRouting implements Serializable {
//fields in table
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name="booking_id")
private Long bookingId;
@Column(name="approval_reason")
private String approvalReason;
@Column(name="approver_id")
private String approverId;
@Column(name="approver_name")
private String approverName;
@Column(name="booking_status")
private String bookingStatus;
@Column(name="created_at")
private Date createdAt;
@Column(name="created_by")
private String createdBy;
@Column(name="updated_at")
private Date updatedAt;
@Column(name="updated_by")
private String updatedBy;
@Column(name="routing_reason")
private String routingReason;
@Version
@Column(name = "version")
private Long version;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getBookingId() {
return bookingId;
}
public void setBookingId(Long bookingId) {
this.bookingId = bookingId;
}
public String getApprovalReason() {
return approvalReason;
}
public void setApprovalReason(String approvalReason) {
this.approvalReason = approvalReason;
}
public String getApproverId() {
return approverId;
}
public void setApproverId(String approverId) {
this.approverId = approverId;
}
public String getApproverName() {
return approverName;
}
public void setApproverName(String approverName) {
this.approverName = approverName;
}
public String getBookingStatus() {
return bookingStatus;
}
public void setBookingStatus(String bookingStatus) {
this.bookingStatus = bookingStatus;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
public String getUpdatedBy() {
return updatedBy;
}
public void setUpdatedBy(String updatedBy) {
this.updatedBy = updatedBy;
}
public String getRoutingReason() {
return routingReason;
}
public void setRoutingReason(String routingReason) {
this.routingReason = routingReason;
}
public Long getVersion() {
return version;
}
public void setVersion(Long version) {
this.version = version;
}
}
@@ -0,0 +1,94 @@
package com.mgm.mcrm.approval.models;
import jakarta.persistence.*;
import java.io.Serializable;
import java.util.Date;
@Entity
@Table(name="cfg_request_reason")
public class CfgRequestReason implements Serializable {
//fields in table
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name="description")
private String description;
@Column(name="code")
private String code;
@Column(name="is_show")
private int isShow;
@Column(name="created_at")
private Date createdAt;
@Column(name="created_by")
private String createdBy;
@Column(name="updated_at")
private Date updatedAt;
@Column(name="updated_by")
private String updatedBy;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public int getIsShow() {
return isShow;
}
public void setIsShow(int isShow) {
this.isShow = isShow;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
public String getUpdatedBy() {
return updatedBy;
}
public void setUpdatedBy(String updatedBy) {
this.updatedBy = updatedBy;
}
}
@@ -0,0 +1,52 @@
package com.mgm.mcrm.approval.repositories;
import com.mgm.mcrm.approval.models.CfgApprovalRouting;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
public interface ApprovalRoutingDao extends JpaRepository<CfgApprovalRouting, Long> {
CfgApprovalRouting findById(long id);
List<CfgApprovalRouting> findAll(Specification<CfgApprovalRouting> spec,Sort sort);
List<CfgApprovalRouting> findAll(Specification<CfgApprovalRouting> spec);
Page<CfgApprovalRouting> findAll(Specification<CfgApprovalRouting> spec, Pageable pageable);
@Transactional
@Modifying
@Query(value = " delete from cfg_approval_routing where id=?1 ",nativeQuery=true)
int deleteById(long id);
@Query(value="select * from cfg_approval_routing where id =?1",nativeQuery=true)
CfgApprovalRouting getById(Long id);
@Query(value="select * from cfg_approval_routing where id =?1",nativeQuery=true)
CfgApprovalRouting getById(Integer id);
@Query(value="select * from cfg_approval_routing where name =?1",nativeQuery=true)
CfgApprovalRouting getByName(String name);
List<CfgApprovalRouting> findByBookingStatus(String bookingStatus);
Integer countByBookingStatus(String bookingStatus);
Integer countByBookingStatusAndApproverId(String bookingStatus, String approverId);
CfgApprovalRouting getByBookingId(Long bookingId);
List<CfgApprovalRouting> findByBookingStatusAndApproverId(String ap, String userId);
@Query(value = "select * from cfg_approval_routing where booking_status = 'AP' and approver_id like concat('%', ?1, '%')", nativeQuery = true)
List<CfgApprovalRouting> getApprovalList(String userId);
@Query(value = "select count(*) from cfg_approval_routing where booking_status = 'AP' and approver_id like concat('%', ?1, '%')", nativeQuery = true)
Long countApprovalList(String userId);
}
@@ -0,0 +1,37 @@
package com.mgm.mcrm.approval.repositories;
import com.mgm.mcrm.approval.models.CfgRequestReason;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
public interface RequestReasonDao extends JpaRepository<CfgRequestReason, Long> {
CfgRequestReason findById(long id);
List<CfgRequestReason> findAll(Specification<CfgRequestReason> spec, Sort sort);
List<CfgRequestReason> findAll(Specification<CfgRequestReason> spec);
Page<CfgRequestReason> findAll(Specification<CfgRequestReason> spec, Pageable pageable);
CfgRequestReason findByCode(String code);
@Transactional
@Modifying
@Query(value = " delete from cfg_request_reason where id=?1 ",nativeQuery=true)
int deleteById(long id);
@Query(value="select * from cfg_request_reason where id =?1",nativeQuery=true)
CfgRequestReason getById(Long id);
@Query(value="select * from cfg_request_reason where id =?1",nativeQuery=true)
CfgRequestReason getById(Integer id);
CfgRequestReason getByCode(String code);
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,102 @@
package com.mgm.mcrm.appsetting.controllers;
import com.mgm.mcrm.appsetting.dtos.CfgSettingQueryRequest;
import com.mgm.mcrm.appsetting.dtos.SysSettingQueryRequest;
import com.mgm.mcrm.appsetting.models.CfgSettings;
import com.mgm.mcrm.appsetting.models.SysSetting;
import com.mgm.mcrm.appsetting.services.SysSettingService;
import com.mgm.mcrm.common.dtos.BaseApiResponse;
import com.mgm.mcrm.common.utils.LogUtil;
import com.mgm.mcrm.common.utils.NetworkUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import com.mgm.mcrm.appsetting.services.SettingService;
import java.util.List;
import java.util.Map;
@RestController
@CrossOrigin(origins = "*")
@RequestMapping("/api")
public class CfgSettingController {
@Resource
private SettingService settingService;
@Resource
private SysSettingService sysSettingService;
@RequestMapping(value = "/web/setting/get_setting_by_key", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public ResponseEntity<BaseApiResponse<CfgSettings>> getSettingByKey(HttpServletRequest request, @RequestBody CfgSettingQueryRequest params) throws Exception {
boolean isSuccess = false;
String processMessage="";
String errorCode="";
BaseApiResponse<CfgSettings> result = new BaseApiResponse<>();
String keyName = params.getKeyName();
CfgSettings setting = settingService.getSettingByKey(keyName);
isSuccess = setting != null;
if(isSuccess) {
processMessage = "Get Setting By Key Successed";
result.setData(setting);
}else {
processMessage = "Get Setting By Key with Error";
errorCode = "System Error";
}
result.setSuccess(isSuccess);
result.setCode(errorCode);
result.setMessage(processMessage);
return ResponseEntity.status(HttpStatus.OK).body(result);
}
@RequestMapping(value = "/system/sys_setting/get", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public ResponseEntity<BaseApiResponse<SysSetting>> getSysSettingByKey(HttpServletRequest request, @RequestBody SysSettingQueryRequest queryFilter) {
BaseApiResponse<SysSetting> result = new BaseApiResponse<>();
//--
String accessIp = NetworkUtil.getClientIpAddr(request);
LogUtil.info(CfgSettingController.class, "Client Connect with IP:"+ accessIp);
//--
SysSetting sysSetting = sysSettingService.getSysSettingByKey(queryFilter.getKey());
if(sysSetting!=null) {
result.setSuccess(true);
sysSetting.setInternalNetwork(NetworkUtil.isMatchInternal(accessIp));
result.setData(sysSetting);
}else {
result.setSuccess(false);
result.setMessage("Query Failed with Error.");
result.setCode("ERR_DATA_NOT_FOUND");
}
return ResponseEntity.status(HttpStatus.OK).body(result);
}
@RequestMapping(value = "/system/sys_setting/get_list", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public ResponseEntity<BaseApiResponse<List<SysSetting>>> getSysSettings(HttpServletRequest request, @RequestBody(required=false) SysSettingQueryRequest queryFilter) {
boolean isSuccess = false;
String processMessage="";
String errorCode="";
BaseApiResponse result = new BaseApiResponse<>();
//--
String accessIp = NetworkUtil.getClientIpAddr(request);
LogUtil.info(CfgSettingController.class, "Client Connect with IP:"+ accessIp);
//--
List<SysSetting> sysSettings = sysSettingService.getSysSettingsAll();
for(SysSetting sysSetting:sysSettings) {
sysSetting.setInternalNetwork(NetworkUtil.isMatchInternal(accessIp));
}
if(sysSettings!=null) {
isSuccess = true;
processMessage = "";
result.setData(sysSettings);
}else {
isSuccess = false;
processMessage = "Query Failed with Error.";
errorCode = "ERR_DATA_NOT_FOUND";
}
//--
result.setSuccess(isSuccess);
result.setCode(errorCode);
result.setMessage(processMessage);
return ResponseEntity.status(HttpStatus.OK).body(result);
}
}
@@ -0,0 +1,158 @@
package com.mgm.mcrm.appsetting.controllers;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import com.mgm.mcrm.appsetting.dtos.*;
import com.mgm.mcrm.appsetting.models.CfgSettings;
import com.mgm.mcrm.basesetting.property.models.CfgProperties;
import com.mgm.mcrm.basesetting.room.models.CfgRoomFeatures;
import com.mgm.mcrm.basesetting.room.models.CfgRoomTypes;
import com.mgm.mcrm.basesetting.room.models.CfgRooms;
import com.mgm.mcrm.booking.models.Bookings;
import com.mgm.mcrm.booking.models.CfgBookingTypes;
import com.mgm.mcrm.common.dtos.BaseApiResponse;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import com.alibaba.fastjson.JSONObject;
import com.mgm.mcrm.basesetting.room.repositories.BedTypeMappingDao.BedType;
import com.mgm.mcrm.appsetting.services.ConfigService;
import com.mgm.mcrm.common.utils.LogUtil;
@RestController
@CrossOrigin(origins = "*")
@RequestMapping("/api")
public class ConfigController {
@Resource
private ConfigService configService;
@RequestMapping(value = "/app/config/property_list", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public ResponseEntity<BaseApiResponse<List<CfgProperties>>> queryCfgPropertys(HttpServletRequest request, @RequestBody(required=true) PropertyQueryRequest queryFilter) {
BaseApiResponse<List<CfgProperties>> processResult = new BaseApiResponse<>();
//--
List<CfgProperties> listCfgPropertys = configService.listProperty(queryFilter);
//--
processResult.setSuccess(true);
processResult.setData(listCfgPropertys);
return ResponseEntity.status(HttpStatus.OK).body(processResult);
}
@RequestMapping(value = "/app/config/room_list", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public ResponseEntity<BaseApiResponse<List<CfgRooms>>> queryRoom(HttpServletRequest request, @RequestBody(required=true) RoomQueryRequest queryFilter) {
BaseApiResponse<List<CfgRooms>> processResult = new BaseApiResponse<>();
List<CfgRooms> listCfgRooms = configService.listRoom(queryFilter);
//--
processResult.setSuccess(true);
processResult.setData(listCfgRooms);
return ResponseEntity.status(HttpStatus.OK).body(processResult);
}
@RequestMapping(value = "/app/config/room_type_list", produces = "application/json;charset=UTF-8")
public ResponseEntity<BaseApiResponse<List<CfgRoomTypes>>> queryRoomType(HttpServletRequest request,@RequestBody(required=true) RoomTypeQueryRequest queryFilter) {
BaseApiResponse<List<CfgRoomTypes>> processResult = new BaseApiResponse<>();
//--
List<CfgRoomTypes> listCfgRoomTypes = configService.listRoomType(queryFilter);
processResult.setSuccess(true);
processResult.setData(listCfgRoomTypes);
return ResponseEntity.status(HttpStatus.OK).body(processResult);
}
@RequestMapping(value = "/app/config/bed_type_list", produces = "application/json;charset=UTF-8")
public ResponseEntity<BaseApiResponse<List<BedType>>> queryBedType(HttpServletRequest request,@RequestBody(required=true) BedTypeQueryRequest queryFilter) {
BaseApiResponse<List<BedType>> processResult = new BaseApiResponse<>();
//--
List<BedType> listCfgBedTypes = configService.listBedType(queryFilter);
processResult.setData(listCfgBedTypes);
processResult.setSuccess(true);
return ResponseEntity.status(HttpStatus.OK).body(processResult);
}
@RequestMapping(value = "/app/config/special_list", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public ResponseEntity<BaseApiResponse<List<CfgRoomFeatures>>> queryCfgRoomFeatures(HttpServletRequest request, @RequestBody(required=true) RoomFeatureQueryRequest queryFilter) {
BaseApiResponse<List<CfgRoomFeatures>> processResult = new BaseApiResponse<>();
//--
List<CfgRoomFeatures> listCfgRoomFeatures = configService.listRoomFeature(queryFilter);
processResult.setData(listCfgRoomFeatures);
processResult.setSuccess(true);
return ResponseEntity.status(HttpStatus.OK).body(processResult);
}
@RequestMapping(value = "/app/config/criteria_list", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public ResponseEntity<BaseApiResponse<Map<String,JSONObject>>> queryRoomCriteria(HttpServletRequest request, @RequestBody(required=true) RoomCriteriaQueryRequest queryParas) throws Exception {
BaseApiResponse<Map<String,JSONObject>> processResult = new BaseApiResponse<>();
//--
Map<String,JSONObject> listCfgCriterias = configService.listRoomCriteriaCalendar(queryParas);
processResult.setData(listCfgCriterias);
processResult.setSuccess(true);
return ResponseEntity.status(HttpStatus.OK).body(processResult);
}
@RequestMapping(value = "/app/config/setting_list", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public ResponseEntity<BaseApiResponse<List<CfgSettings>>> queryRoomSetting(HttpServletRequest request) {
BaseApiResponse<List<CfgSettings>> processResult = new BaseApiResponse<>();
//--
LogUtil.info(ConfigController.class,
"[ConfigController] 开始获取设置列表");
List<CfgSettings> listCfgRoomSetting = configService.listRoomSetting();
processResult.setData(listCfgRoomSetting);
//--
processResult.setSuccess(true);
LogUtil.info(ConfigController.class,
"[ConfigController] 设置列表获取成功,准备返回结果");
LogUtil.info(ConfigController.class,
"[ConfigController] === setting_list API执行完成 ===");
return ResponseEntity.status(HttpStatus.OK).body(processResult);
}
@RequestMapping(value = "/app/config/available_room_list", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public ResponseEntity<BaseApiResponse<HashSet<String>>> queryRoomCriteriaAvailableRoom(HttpServletRequest request, @RequestBody(required=true) AvailableRoomQueryRequest queryParas) {
BaseApiResponse<HashSet<String>> processResult = new BaseApiResponse<>();
//--
HashSet<String> listCfgRooms = configService.listRoomCriteriaAvailableRoom(queryParas);
processResult.setData(listCfgRooms);
processResult.setSuccess(true);
processResult.setMessage("Query Success");
return ResponseEntity.status(HttpStatus.OK).body(processResult);
}
@RequestMapping(value = "/app/config/is_extend_booking", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public ResponseEntity<BaseApiResponse<List<Bookings>>> queryIsExtendBooking(HttpServletRequest request, @RequestBody(required=true) ExtendBookingQueryRequest queryParas) {
BaseApiResponse<List<Bookings>> processResult = new BaseApiResponse<>();
//--
List<Bookings> listBooking = configService.listIsExtendBooking(queryParas);
processResult.setData(listBooking);
processResult.setSuccess(true);
processResult.setMessage("Query Success");
return ResponseEntity.status(HttpStatus.OK).body(processResult);
}
@RequestMapping(value = "/app/config/booking_type_list", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public ResponseEntity<BaseApiResponse<List<CfgBookingTypes>>> queryCfgBookingTypes(HttpServletRequest request) {
BaseApiResponse<List<CfgBookingTypes>> processResult = new BaseApiResponse<>();
List<CfgBookingTypes> listCfgBookingTypes = configService.listAllBookingType();
processResult.setData(listCfgBookingTypes);
processResult.setSuccess(true);
processResult.setMessage("Query Success");
return ResponseEntity.status(HttpStatus.OK).body(processResult);
}
@RequestMapping(value = "/app/config/get_waitlist_booking", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public ResponseEntity<BaseApiResponse<List<Bookings>>> queryGetWaitlistBooking(HttpServletRequest request, @RequestBody(required=true) WaitlistBookingQueryRequest queryParas) throws Exception {
BaseApiResponse<List<Bookings>> processResult = new BaseApiResponse<>();
//--
List<Bookings> listBooking = configService.getWaitlistBooking(queryParas);
processResult.setData(listBooking);
processResult.setSuccess(true);
processResult.setMessage("Query Success");
return ResponseEntity.status(HttpStatus.OK).body(processResult);
}
}
@@ -0,0 +1,18 @@
package com.mgm.mcrm.appsetting.dtos;
import com.mgm.mcrm.common.dtos.BaseQueryRequest;
import com.mgm.mcrm.common.utils.DateTimeUtil;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
import java.util.List;
@EqualsAndHashCode(callSuper = true)
@Data
public class AvailableRoomQueryRequest extends BaseQueryRequest {
private List<String> selectDate;
private Long blockId;
private Long propertyId;
private Long roomId;
}
@@ -0,0 +1,12 @@
package com.mgm.mcrm.appsetting.dtos;
import com.mgm.mcrm.common.dtos.BaseQueryRequest;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class BedTypeQueryRequest extends BaseQueryRequest {
private Long propertyId;
private Long roomId;
}
@@ -0,0 +1,8 @@
package com.mgm.mcrm.appsetting.dtos;
import lombok.Data;
@Data
public class CfgSettingQueryRequest {
private String keyName;
}
@@ -0,0 +1,20 @@
package com.mgm.mcrm.appsetting.dtos;
import com.mgm.mcrm.common.dtos.BaseQueryRequest;
import com.mgm.mcrm.common.utils.DateTimeUtil;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
import java.util.List;
@EqualsAndHashCode(callSuper = true)
@Data
public class ExtendBookingQueryRequest extends BaseQueryRequest {
private String checkoutDate;
private String checkinDate;
private String playerId;
private String userId;
private String propertyId;
private String roomId;
}
@@ -0,0 +1,14 @@
package com.mgm.mcrm.appsetting.dtos;
import com.mgm.mcrm.common.dtos.BaseQueryRequest;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class PropertyQueryRequest extends BaseQueryRequest {
private String searchCode;
private String searchName;
private String searchCategory;
private String searchId;
}
@@ -0,0 +1,21 @@
package com.mgm.mcrm.appsetting.dtos;
import com.mgm.mcrm.common.dtos.BaseQueryRequest;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class RoomCriteriaQueryRequest extends BaseQueryRequest {
private Long bookingTypeId;
private Long blockId;
private Long segmentId;
private Long propertyId;
private Long roomId;
private boolean coded;
private String userId;
private String userName;
private String playerId;
private Long sectionId;
private Long bedTypeId;
}
@@ -0,0 +1,17 @@
package com.mgm.mcrm.appsetting.dtos;
import com.mgm.mcrm.common.dtos.BaseQueryRequest;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class RoomFeatureQueryRequest extends BaseQueryRequest {
@NotBlank
private String category;
private String searchCode;
private String searchName;
private String searchId;
private String searchIsShow;
}
@@ -0,0 +1,14 @@
package com.mgm.mcrm.appsetting.dtos;
import com.mgm.mcrm.common.dtos.BaseQueryRequest;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.StringUtils;
@EqualsAndHashCode(callSuper = true)
@Data
public class RoomQueryRequest extends BaseQueryRequest {
private String searchName;
private Long searchId;
private Long propertyId;
}
@@ -0,0 +1,11 @@
package com.mgm.mcrm.appsetting.dtos;
import com.mgm.mcrm.common.dtos.BaseQueryRequest;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class RoomTypeQueryRequest extends BaseQueryRequest {
private String searchName;
}
@@ -0,0 +1,12 @@
package com.mgm.mcrm.appsetting.dtos;
import com.mgm.mcrm.common.dtos.BaseQueryRequest;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class SysSettingQueryRequest extends BaseQueryRequest {
private String key;
}
@@ -0,0 +1,16 @@
package com.mgm.mcrm.appsetting.dtos;
import com.mgm.mcrm.common.dtos.BaseQueryRequest;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class WaitlistBookingQueryRequest extends BaseQueryRequest {
private String checkoutDate;
private String checkinDate;
private String playerId;
private String userId;
private String propertyId;
private String roomId;
}
@@ -0,0 +1,33 @@
package com.mgm.mcrm.appsetting.models;
import java.io.Serializable;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
@Entity
@Table(name="cfg_settings")//
public class CfgSettings implements Serializable {
@Id
@Column(name="keys")
private String keys;
@Column(name="key_values")
private String keyValues;
public String getKeys() {
return keys;
}
public void setKeys(String keys) {
this.keys = keys;
}
public String getKeyValues() {
return keyValues;
}
public void setKeyValues(String keyValues) {
this.keyValues = keyValues;
}
}
@@ -0,0 +1,42 @@
package com.mgm.mcrm.appsetting.models;
import java.io.Serializable;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.persistence.Transient;
@Entity
@Table(name="sys_settings")
public class SysSetting implements Serializable {
//fields in table
@Id
@Column(name="setting_key")
private String settingKey;
@Column(name="setting_value")
private String settingValue;
@Transient
private boolean internalNetwork=false;
public String getSettingKey() {
return settingKey;
}
public void setSettingKey(String settingKey) {
this.settingKey = settingKey;
}
public String getSettingValue() {
return settingValue;
}
public void setSettingValue(String settingValue) {
this.settingValue = settingValue;
}
public boolean isInternalNetwork() {
return internalNetwork;
}
public void setInternalNetwork(boolean internalNetwork) {
this.internalNetwork = internalNetwork;
}
}
@@ -0,0 +1,10 @@
package com.mgm.mcrm.appsetting.repositories;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import com.mgm.mcrm.appsetting.models.CfgSettings;
public interface SettingDao extends JpaRepository<CfgSettings, String> {
@Query(value = "select * from cfg_settings with (nolock) where keys = ?1",nativeQuery=true)
CfgSettings getByKeys(String keys);
}
@@ -0,0 +1,20 @@
package com.mgm.mcrm.appsetting.repositories;
import java.util.List;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import com.mgm.mcrm.appsetting.models.SysSetting;
public interface SysSettingDao extends JpaRepository<SysSetting, String> {
@Query(value="select * from sys_settings where setting_key=?1",nativeQuery=true)
SysSetting getBySettingKey(String key);
List<SysSetting> findAll(Specification<SysSetting> spec,Sort sort);
List<SysSetting> findAll(Specification<SysSetting> spec);
}
@@ -0,0 +1,719 @@
package com.mgm.mcrm.appsetting.services;
import java.time.LocalDateTime;
import java.util.*;
import com.mgm.mcrm.allotment.models.*;
import com.mgm.mcrm.allotment.repositories.RoomCriteriaDaylightDao;
import com.mgm.mcrm.appsetting.dtos.*;
import com.mgm.mcrm.basesetting.daylight.models.*;
import com.mgm.mcrm.basesetting.daylight.repositories.*;
import com.mgm.mcrm.booking.models.BookingsView;
import jakarta.annotation.Resource;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONObject;
import com.mgm.mcrm.booking.models.Bookings;
import com.mgm.mcrm.basesetting.room.models.CfgBedTypeMapping;
import com.mgm.mcrm.booking.models.CfgBookingTypes;
import com.mgm.mcrm.basesetting.team.models.CfgOtherUserMapping;
import com.mgm.mcrm.basesetting.property.models.CfgProperties;
import com.mgm.mcrm.basesetting.room.models.CfgRoomFeatures;
import com.mgm.mcrm.basesetting.room.models.CfgRoomTypes;
import com.mgm.mcrm.basesetting.room.models.CfgRooms;
import com.mgm.mcrm.basesetting.room.models.CfgRoomsRoomTypes;
import com.mgm.mcrm.appsetting.models.CfgSettings;
import com.mgm.mcrm.common.utils.DaoUtil;
import com.mgm.mcrm.common.utils.DateTimeUtil;
import com.mgm.mcrm.common.constants.SysConstants;
import com.mgm.mcrm.basesetting.room.repositories.BedTypeMappingDao;
import com.mgm.mcrm.allotment.repositories.OtherAllotmentViewDao;
import com.mgm.mcrm.basesetting.team.repositories.OtherUserMappingDao;
import com.mgm.mcrm.basesetting.property.repositories.PropertyDao;
import com.mgm.mcrm.allotment.repositories.RoomCriteriaDao;
import com.mgm.mcrm.basesetting.room.repositories.RoomDao;
import com.mgm.mcrm.basesetting.room.repositories.RoomFeatureDao;
import com.mgm.mcrm.basesetting.room.repositories.RoomRoomTypeDao;
import com.mgm.mcrm.basesetting.room.repositories.RoomTypeDao;
import com.mgm.mcrm.appsetting.repositories.SettingDao;
import com.mgm.mcrm.booking.repositories.BookingDao;
import com.mgm.mcrm.booking.repositories.BookingTypeDao;
import com.mgm.mcrm.booking.repositories.BookingViewDao;
import com.mgm.mcrm.basesetting.room.repositories.BedTypeMappingDao.BedType;
import com.mgm.mcrm.booking.services.WaitlistBookingService;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class ConfigService {
@Resource
private BookingDao bookingDao;
@Resource
private PropertyDao propertyDao;
@Resource
private RoomDao roomDao;
@Resource
private RoomTypeDao roomTypeDao;
@Resource
private BedTypeMappingDao bedTypeMappingDao;
@Resource
private RoomFeatureDao roomFeatureDao;
@Resource
private RoomCriteriaDao criteriaDao;
@Resource
private RoomCriteriaDaylightDao criteriaDaylightDao;
@Resource
private SettingDao settingDao;
@Resource
private BookingTypeDao bookingTypeDao;
@Resource
private DaylightViewDao daylightViewDao;
@Resource
private ExceptionDaylightViewDao exceptionDaylightViewDao;
@Resource
private ExceptionOperaViewDao exceptionOperaViewDao;
@Resource
private RoomRoomTypeDao roomRoomTypeDao;
@Resource
private BookingViewDao bookingViewDao;
@Resource
private WaitlistBookingService waitlistBookingService;
@Resource
private OperaViewDao operaViewDao;
@Resource
private BlockCodeDao blockCodesDao;
@Resource
private OtherUserMappingDao otherUserMappingDao;
@Autowired
private OtherAllotmentViewDao otherAllotmentDao;
public List<CfgProperties> listProperty(PropertyQueryRequest queryFilter) {
Specification<CfgProperties> listSpec = (root, criteriaQuery, cb) -> {
List<Predicate> list = new ArrayList<>();
// status=0 的记录不返回
list.add(cb.notEqual(root.get("status"), 0));
if(StringUtils.isNotBlank(queryFilter.getSearchCode())) {
list.add(cb.equal(root.get("code") , queryFilter.getSearchCode()));
}
if(StringUtils.isNotBlank(queryFilter.getSearchName())) {
list.add(cb.like(cb.upper(root.get("name")) , "%" + queryFilter.getSearchName().toUpperCase() + "%"));
}
if(StringUtils.isNotBlank(queryFilter.getSearchCategory())) {
list.add(cb.equal(root.get("category") , queryFilter.getSearchCategory()));
}
//--
if(StringUtils.isNotBlank(queryFilter.getSearchId())) {
List<String> searchIds = DaoUtil.parseMultipleFilter(queryFilter.getSearchId());
if(searchIds.size()==1) {
list.add(cb.equal(root.get("id"), searchIds.getFirst()));
}else if(searchIds.size()>1) {
list.add(root.get("id").in(searchIds));
}
}
//--
Predicate[] predicates = new Predicate[list.size()];
criteriaQuery.where(list.toArray(predicates));
return cb.and(list.toArray(predicates));
};
Sort sort = DaoUtil.buildSortByFilter(
queryFilter.getSortOrder(),
"category;sortOrder-asc"
);
return propertyDao.findAll(listSpec,sort);
}
public List<CfgRooms> listRoom(RoomQueryRequest queryFilter) {
Specification<CfgRooms> listSpec = (root, criteriaQuery, cb) -> {
List<Predicate> list = new ArrayList<>();
if (queryFilter.getSearchId()!=null) {
list.add(cb.equal(root.get("id"), queryFilter.getSearchId()));
}
if (StringUtils.isNotBlank(queryFilter.getSearchName())) {
list.add(cb.like(cb.upper(root.get("name")),
"%" + queryFilter.getSearchName().toUpperCase() + "%"));
}
if(queryFilter.getPropertyId()!=null && queryFilter.getPropertyId()!=0) {
list.add(cb.equal(root.get("propertyId"), queryFilter.getPropertyId()));
}
Predicate[] predicates = new Predicate[list.size()];
criteriaQuery.where(list.toArray(predicates));
return cb.and(list.toArray(predicates));
};
Sort sort = DaoUtil.buildSortByFilter(queryFilter.getSortOrder(), "id");
return roomDao.findAll(listSpec,sort);
}
public List<CfgRoomTypes> listRoomType(RoomTypeQueryRequest queryFilter) {
Specification<CfgRoomTypes> listSpec = (root, criteriaQuery, cb) -> {
List<Predicate> list = new ArrayList<>();
if (StringUtils.isNotBlank(queryFilter.getSearchName())) {
list.add(cb.like(cb.upper(root.get("name")),
"%" + queryFilter.getSearchName().toUpperCase() + "%"));
}
Predicate[] predicates = new Predicate[list.size()];
criteriaQuery.where(list.toArray(predicates));
return cb.and(list.toArray(predicates));
};
Sort sort = DaoUtil.buildSortByFilter(queryFilter.getSortOrder(), "id");
return roomTypeDao.findAll(listSpec,sort);
}
public List<BedType> listBedType(BedTypeQueryRequest queryFilter) {
Long propertyId = queryFilter.getPropertyId();
Long roomId = queryFilter.getRoomId();
return bedTypeMappingDao.queryByPropertyIdAndRoomId(propertyId, roomId);
}
public List<CfgRoomFeatures> listRoomFeature(RoomFeatureQueryRequest queryFilter) {
Specification<CfgRoomFeatures> listSpec = (root, criteriaQuery, cb) -> {
List<Predicate> list = new ArrayList<>();
String category = queryFilter.getCategory();
list.add(
cb.or(
cb.equal(root.get("category"), category)
)
);
if(StringUtils.isNotBlank(queryFilter.getSearchCode())) {
list.add(cb.equal(root.get("code") , queryFilter.getSearchCode()));
}
if(StringUtils.isNotBlank(queryFilter.getSearchName())) {
list.add(cb.like(cb.upper(root.get("description")) , "%" + queryFilter.getSearchName().toUpperCase() + "%"));
}
//--
if(StringUtils.isNotBlank(queryFilter.getSearchId())) {
List<String> searchIds = DaoUtil.parseMultipleFilter(queryFilter.getSearchId());
if(searchIds.size()==1) {
list.add(cb.equal(root.get("id"), searchIds.getFirst()));
}else if(searchIds.size()>1) {
list.add(root.get("id").in(searchIds));
}
}
if(StringUtils.isNotBlank(queryFilter.getSearchIsShow())) {
list.add(cb.equal(root.get("showInBooking") , queryFilter.getSearchIsShow()));
}
//--
Predicate[] predicates = new Predicate[list.size()];
criteriaQuery.where(list.toArray(predicates));
return cb.and(list.toArray(predicates));
};
Sort sort = DaoUtil.buildSortByFilter(queryFilter.getSortOrder(), "id");
return roomFeatureDao.findAll(listSpec,sort);
}
public Map<String,JSONObject> listRoomCriteriaCalendar(RoomCriteriaQueryRequest queryParas) throws Exception {
Map<String,JSONObject> resultList = new HashMap<>();
Long bookingTypeId = queryParas.getBookingTypeId();
Long blockId = queryParas.getBlockId();
Long segmentId = queryParas.getSegmentId();
Long propertyId = queryParas.getPropertyId();
Long roomId = queryParas.getRoomId();
boolean coded = queryParas.isCoded();
String userId = queryParas.getUserId();
String userName = queryParas.getUserName();
String playerId = queryParas.getPlayerId();
Long sectionId = queryParas.getSectionId();
Long bedTypeMasterGroupId = queryParas.getBedTypeId();
//check opera criteria or other criteria
CfgProperties property = propertyDao.getById(propertyId);
CfgRooms room = roomDao.findById(roomId);
boolean isOpera = false;
boolean isWaitlist = false;
boolean isDaylight = false;
if(Strings.CS.equals(property.getCategory(), "OPERA")) isOpera = true;
if(Strings.CS.equals(property.getCategory(), "DAYLIGHT")) isDaylight = true;
if(room.getForWaitlist() != null && room.getForWaitlist()==1&&room.getForBooking()==0) isWaitlist = true;
if(isOpera||isWaitlist) {
resultList = getOperaCriteria( blockId,sectionId, bookingTypeId, propertyId, roomId, bedTypeMasterGroupId,userId);
} else if (isDaylight) {
resultList = getDaylightCriteria( blockId,sectionId, bookingTypeId, propertyId, roomId, bedTypeMasterGroupId,userId);
} else {
resultList = getOtherCriteria( segmentId, sectionId, bookingTypeId, propertyId, roomId);
}
if(!resultList.isEmpty()) {
checkCriteriaBooking(resultList, playerId, userId, userName);
}
return resultList;
}
public Map<String,JSONObject> getDaylightCriteria(Long blockCodeId,Long sectionId,Long bookingTypeId,Long propertyId,Long roomId,Long bedTypeMasterGroupId,String userId) throws Exception{
log.info("[getDaylightCriteria] Input params: blockCodeId={}, sectionId={}, bookingTypeId={}, propertyId={}, roomId={}, bedTypeMasterGroupId={}, userId={}", blockCodeId, sectionId, bookingTypeId, propertyId, roomId, bedTypeMasterGroupId, userId);
Long roomTypeId = null;
List<Long> roomIds = new ArrayList<>();
roomIds.add(roomId);
Map<String,JSONObject> resultList = new HashMap<>();
// Date today = DateTimeUtil.getCurrentDateTime("yyyy-MM-dd");
LocalDateTime today = LocalDateTime.now();
String maxDay = settingDao.getByKeys(SysConstants.MAX_ADVANCE_BOOKING_DAYS).getKeyValues();
// Date endDate = DateTimeUtil.addDay(today, Integer.valueOf(maxDay));
LocalDateTime endDate = today.plusDays(Integer.parseInt(maxDay));
today = today.minusDays(1);
List<CfgDaylightView> teamDaylight = new ArrayList<>();
List<CfgExceptionDaylightView> eDaylightViewList = new ArrayList<>();
// 如果有BedTypeId根据BedTypeId拿到RoomTypeId List后随机,否则按RoomId
List<CfgRoomsRoomTypes> roomTypes;
List<CfgBedTypeMapping> bedTypes;
if(blockCodeId==null) {
log.info("[getDaylightCriteria] Input blockCodeId is null, will determine via daylightView/exceptionDaylightView");
if(bedTypeMasterGroupId==null) {
roomTypes = roomRoomTypeDao.queryByRoomId(roomId);// 该方法可能要改成一个view的直接拿到RoomTypeId和RoomTypeCode
if(roomTypes!=null && !roomTypes.isEmpty()) {
roomTypeId = roomTypes.get(new Random().nextInt(roomTypes.size())).getRoomTypeId();
// roomTypeId = roomTypes.get(0).getRoomTypeId();
}
}else {
bedTypes = bedTypeMappingDao.queryByMasterGroupId(bedTypeMasterGroupId);// 该方法可能要改成一个view的直接拿到RoomTypeId和RoomTypeCode
if(bedTypes!=null && !bedTypes.isEmpty()) {
roomTypeId = Long.valueOf(bedTypes.get(new Random().nextInt(bedTypes.size())).getRoomTypeId());
// roomTypeId = Long.valueOf(bedTypes.get(0).getRoomTypeId());
}
}
log.info("[getDaylightCriteria] roomTypeId determined, roomTypeId={}, bedTypeMasterGroupId={}", roomTypeId, bedTypeMasterGroupId);
//先从exception opera mapping拿,没有再去 opera mapping拿
List<CfgExceptionDaylightView> eDLs =
exceptionDaylightViewDao.findByUserIdLikeAndPropertyIdAndBookingTypeId("%"+userId+"%",propertyId, bookingTypeId);
log.info("[getDaylightCriteria] exceptionDaylightView query done, userId={}, propertyId={}, bookingTypeId={}, resultCount={}", userId, propertyId, bookingTypeId, eDLs.size());
if(!eDLs.isEmpty()) {
for(CfgExceptionDaylightView o :eDLs) {
for(CfgRoomTypes r :o.getDaylightRoomType()) {
if(Objects.equals(r.getId(), roomTypeId)) {
eDaylightViewList.add(o);
}
}
}
}
log.info("[getDaylightCriteria] exceptionDaylightView filtered by roomTypeId, matchCount={}, roomTypeId={}", eDaylightViewList.size(), roomTypeId);
// 筛选出符合条件的opear mapping记录,没有Opera mapping要提示前端配置
List<CfgDaylightView> dLs = daylightViewDao.findBySectionIdAndPropertyIdAndBookingTypeId(sectionId,propertyId, bookingTypeId);
log.info("[getDaylightCriteria] daylightView query done, sectionId={}, propertyId={}, bookingTypeId={}, resultCount={}", sectionId, propertyId, bookingTypeId, dLs.size());
for(CfgDaylightView o :dLs) {
for(CfgRoomTypes r :o.getDaylightRoomType()) {
if(Objects.equals(r.getId(), roomTypeId)) {
teamDaylight.add(o);
}
}
}
log.info("[getDaylightCriteria] daylightView filtered by roomTypeId, matchCount={}, roomTypeId={}", teamDaylight.size(), roomTypeId);
if(!eDaylightViewList.isEmpty()) {
blockCodeId = eDaylightViewList.getFirst().getBlockCodeId();
log.info("[getDaylightCriteria] Using exceptionDaylightView blockCodeId={}", blockCodeId);
}else if(!teamDaylight.isEmpty()) {
blockCodeId = teamDaylight.getFirst().getBlockCodeId();
log.info("[getDaylightCriteria] Using daylightView blockCodeId={}", blockCodeId);
}else {
log.warn("[getDaylightCriteria] Neither exceptionDaylightView nor daylightView matched, blockCodeId will be null");
}
} else {
log.info("[getDaylightCriteria] Input blockCodeId provided directly, blockCodeId={}", blockCodeId);
}
log.info("[getDaylightCriteria] Final blockCodeId={}, availability date range: {} ~ {}", blockCodeId, today.toLocalDate(), endDate.toLocalDate());
// Daylight:渠道行存的是 block_code_id,与视图/入参中的 blockCodeId 一致,无需再解析 cfg_block_codes
List<CfgRoomCriteriasDaylight> criterias = criteriaDaylightDao.findByRoomIdInAndPropertyIdAndBookDateBetween(roomIds,propertyId,today, endDate);
log.info("[getDaylightCriteria] Availability query done, dayCount={}", criterias.size());
for(CfgRoomCriteriasDaylight c:criterias) {
JSONObject res = new JSONObject();
String bookDate = DateTimeUtil.getDateByFormat(c.getBookDate(),"yyyy-MM-dd");
res.put("bookDate",bookDate);
res.put("isWaitlist",c.getIsWaitlist());
res.put("sharer",c.getSharer());
CfgAppChannelDaylight channel = new CfgAppChannelDaylight();
Set<CfgAppChannelDaylight> channels = c.getChannels();
for(CfgAppChannelDaylight a:channels) {
if(Objects.equals(a.getBlockCodeId(), blockCodeId)) channel = a;
}
res.put("available",channel.getAvailable());
resultList.put(bookDate ,res);
}
return resultList;
}
public Map<String,JSONObject> getOperaCriteria(Long blockCodeId,Long sectionId,Long bookingTypeId,Long propertyId,Long roomId,Long bedTypeMasterGroupId,String userId) throws Exception{
log.info("[getOperaCriteria] Input params: blockCodeId={}, sectionId={}, bookingTypeId={}, propertyId={}, roomId={}, bedTypeMasterGroupId={}, userId={}", blockCodeId, sectionId, bookingTypeId, propertyId, roomId, bedTypeMasterGroupId, userId);
Long roomTypeId = null;
List<Long> roomIds = new ArrayList<>();
roomIds.add(roomId);
Map<String,JSONObject> resultList = new HashMap<>();
Date today = DateTimeUtil.getCurrentDateTime("yyyy-MM-dd");
String maxDay = settingDao.getByKeys(SysConstants.MAX_ADVANCE_BOOKING_DAYS).getKeyValues();
Date endDate = DateTimeUtil.addDay(today, Integer.valueOf(maxDay));
List<CfgOperaView> teamOpera = new ArrayList<>();
List<CfgExceptionOperaView> exceptionOpera = new ArrayList<>();
// 如果有BedTypeId根据BedTypeId拿到RoomTypeId List后随机,否则按RoomId
List<CfgRoomsRoomTypes> roomTypes;
List<CfgBedTypeMapping> bedTypes;
Long blockId = null;
if(blockCodeId==null) {
log.info("[getOperaCriteria] Input blockCodeId is null, will determine via operaView/exceptionOperaView");
if(bedTypeMasterGroupId==null) {
roomTypes = roomRoomTypeDao.queryByRoomId(roomId);// 该方法可能要改成一个view的直接拿到RoomTypeId和RoomTypeCode
if(roomTypes!=null && !roomTypes.isEmpty()) {
// 暂时先拿第一个,这里要改成随机算法。拿roomType用得少就用那个要实现平均分配
roomTypeId = roomTypes.get(0).getRoomTypeId();
}
}else {
bedTypes = bedTypeMappingDao.queryByMasterGroupId(bedTypeMasterGroupId);// 该方法可能要改成一个view的直接拿到RoomTypeId和RoomTypeCode
if(bedTypes!=null && !bedTypes.isEmpty()) {
// 暂时先拿第一个,这里要改成随机算法。拿roomType用得少就用那个要实现平均分配
roomTypeId = Long.valueOf(bedTypes.get(0).getRoomTypeId());
}
}
log.info("[getOperaCriteria] roomTypeId determined, roomTypeId={}, bedTypeMasterGroupId={}", roomTypeId, bedTypeMasterGroupId);
//先从exception opera mapping拿,没有再去 opera mapping拿
List<CfgExceptionOperaView> eoperas =
exceptionOperaViewDao.findByUserIdLikeAndPropertyIdAndBookingTypeId("%"+userId+"%",propertyId, bookingTypeId);
log.info("[getOperaCriteria] exceptionOperaView query done, userId={}, propertyId={}, bookingTypeId={}, resultCount={}", userId, propertyId, bookingTypeId, eoperas.size());
if(!eoperas.isEmpty()) {
for(CfgExceptionOperaView o :eoperas) {
for(CfgRoomTypes r :o.getOperaRoomType()) {
if(Objects.equals(r.getId(), roomTypeId)) {
exceptionOpera.add(o);
}
}
}
}
log.info("[getOperaCriteria] exceptionOperaView filtered by roomTypeId, matchCount={}, roomTypeId={}", exceptionOpera.size(), roomTypeId);
// 筛选出符合条件的opear mapping记录,没有Opera mapping要提示前端配置
List<CfgOperaView> operas = operaViewDao.findBySectionIdAndPropertyIdAndBookingTypeId(sectionId,propertyId, bookingTypeId);
log.info("[getOperaCriteria] operaView query done, sectionId={}, propertyId={}, bookingTypeId={}, resultCount={}", sectionId, propertyId, bookingTypeId, operas.size());
for(CfgOperaView o :operas) {
for(CfgRoomTypes r :o.getOperaRoomType()) {
if(Objects.equals(r.getId(), roomTypeId)) {
teamOpera.add(o);
}
}
}
log.info("[getOperaCriteria] operaView filtered by roomTypeId, matchCount={}, roomTypeId={}", teamOpera.size(), roomTypeId);
if(!exceptionOpera.isEmpty()) {
blockCodeId = exceptionOpera.getFirst().getBlockCodeId();
log.info("[getOperaCriteria] Using exceptionOperaView blockCodeId={}", blockCodeId);
}else if(!teamOpera.isEmpty()) {
blockCodeId = teamOpera.getFirst().getBlockCodeId();
log.info("[getOperaCriteria] Using operaView blockCodeId={}", blockCodeId);
}else {
log.warn("[getOperaCriteria] Neither exceptionOperaView nor operaView matched, blockCodeId will be null");
}
if(blockCodeId!=null) {
CfgBlockCodes blockCode = blockCodesDao.findById(blockCodeId).orElse(null);
if(blockCode!=null)
blockId = blockCode.getBlockId();
log.info("[getOperaCriteria] Resolved blockId from blockCodeId, blockCodeId={}, blockId={}", blockCodeId, blockId);
}
} else {
blockId = blockCodeId;
log.info("[getOperaCriteria] Input blockCodeId provided directly, blockCodeId={}, blockId={}", blockCodeId, blockId);
}
log.info("[getOperaCriteria] Final blockCodeId={}, blockId={}, availability date range: {} ~ {}", blockCodeId, blockId, DateTimeUtil.getDateByFormat(today,"yyyy-MM-dd"), DateTimeUtil.getDateByFormat(endDate,"yyyy-MM-dd"));
List<CfgRoomCriterias> criterias = criteriaDao.findByRoomIdInAndPropertyIdAndBookDateBetween(roomIds,propertyId,today,endDate);
log.info("[getOperaCriteria] Availability query done, dayCount={}", criterias.size());
for(CfgRoomCriterias c:criterias) {
JSONObject res = new JSONObject();
String bookDate = DateTimeUtil.getDateByFormat(c.getBookDate(),"yyyy-MM-dd");
res.put("bookDate",bookDate);
res.put("isWaitlist",c.getIsWaitlist());
res.put("sharer",c.getSharer());
CfgAppChannel channel = new CfgAppChannel();
Set<CfgAppChannel> channels = c.getChannels();
for(CfgAppChannel a:channels) {
if(Objects.equals(a.getBlockId(), blockId)) channel = a;
}
res.put("available",channel.getAvailable());
resultList.put(bookDate ,res);
}
return resultList;
}
private void addDateToMap(Map<String, JSONObject> resultMap, String date,
Integer im, Integer reserved, Integer sharer,
Integer staying, Integer available, Integer protection,
Integer isWaitlist, Integer massStandard) {
JSONObject dateObject = new JSONObject();
dateObject.put("bookDate", date);
if (im != null) dateObject.put("im", im);
if (reserved != null) dateObject.put("reserved", reserved);
if (sharer != null) dateObject.put("sharer", sharer);
if (staying != null) dateObject.put("staying", 0);
if (available != null) dateObject.put("available", available);
if (protection != null) dateObject.put("protection", protection);
if (isWaitlist != null) dateObject.put("isWaitlist", isWaitlist);
if (massStandard != null) dateObject.put("massStandard", massStandard);
resultMap.put(date, dateObject);
}
public Map<String,JSONObject> getOtherCriteria(Long segmentId,Long teamId,Long bookingTypeId,Long propertyId,Long roomId) throws Exception{
Long roomTypeId = null;
List<Long> roomIds = new ArrayList<>();
roomIds.add(roomId);
Date today = DateTimeUtil.getCurrentDateTime("yyyy-MM-dd");
String maxDay = settingDao.getByKeys(SysConstants.MAX_ADVANCE_BOOKING_DAYS).getKeyValues();
Date endDate = DateTimeUtil.addDay(today, Integer.valueOf(maxDay));
Map<String,JSONObject> resultList = new HashMap<>();
List<CfgOtherUserMapping> userMappingList = new ArrayList<>();
CfgOtherUserMapping userMapping = new CfgOtherUserMapping();
// 如果有BedTypeId根据BedTypeId拿到RoomTypeId List后随机,否则按RoomId
List<CfgRoomsRoomTypes> roomTypes = new ArrayList<>();
List<CfgBedTypeMapping> bedTypes = new ArrayList<>();
if(segmentId==null) {
// 筛选出符合条件的 mapping记录
userMappingList = otherUserMappingDao.findBySectionIdAndPropertyIdAndBookingTypeId(teamId,propertyId,Long.valueOf(bookingTypeId));
if(!userMappingList.isEmpty()) {
segmentId = userMappingList.getFirst().getSegmentId();
}
}
List<CfgOtherAllotmentView> criterias = otherAllotmentDao.findByRoomIdInAndPropertyIdAndBookDateBetween(roomIds,propertyId,today,endDate);
for(CfgOtherAllotmentView c:criterias) {
JSONObject res = new JSONObject();
String bookDate = DateTimeUtil.getDateByFormat(c.getBookDate(),"yyyy-MM-dd");
res.put("bookDate",bookDate);
res.put("isWaitlist",c.getIsWaitlist());
res.put("sharer",c.getSharer());
CfgOtherAppChannel channel = new CfgOtherAppChannel();
Set<CfgOtherAppChannel> channels = c.getChannels();
for(CfgOtherAppChannel a:channels) {
if(a.getSegmentId()!=null&&segmentId!=null) {
if(Objects.equals(a.getSegmentId(), segmentId)) channel = a;
}
}
res.put("available",channel.getAvailable());
resultList.put(bookDate ,res);
}
return resultList;
}
private Map<String,JSONObject> checkCriteriaBooking(Map<String,JSONObject> resultList,String playerId,String userId,String userName) throws Exception{
Date today = DateTimeUtil.getCurrentDateTime("yyyy-MM-dd");
String maxDay = settingDao.getByKeys(SysConstants.MAX_ADVANCE_BOOKING_DAYS).getKeyValues();
boolean enableProtection = Strings.CS.equals("1", settingDao.getByKeys(SysConstants.PROTECT_PERIOD_ENABLE).getKeyValues())?true:false;
String checkinProtection = settingDao.getByKeys(SysConstants.PROTECTION_PERIOD_CHECKIN).getKeyValues();
String checkoutProtection = settingDao.getByKeys(SysConstants.PROTECTION_PERIOD_CHECKOUT).getKeyValues();
Date endDate = DateTimeUtil.addDay(today, Integer.valueOf(maxDay));
List<BookingsView> bookingList = bookingViewDao.getCalendarBooking(endDate, playerId);
Set<Date> protectionPeriod = new HashSet();
for(BookingsView book:bookingList) {
if(StringUtils.isEmpty(book.getLastOperaStatus())||
Strings.CS.equals(book.getLastOperaStatus(), "DUE_IN")||
Strings.CS.equals(book.getLastOperaStatus(), "RESERVED")||
Strings.CS.equals(book.getLastOperaStatus(), "CHECKED_IN")) {
// no coded
boolean differentUser = true;
if(!StringUtils.isEmpty(book.getCreatedBy())) {
differentUser = !Strings.CS.equals(book.getCreatedBy(), userId);
}else if(!StringUtils.isEmpty(book.getCreatedByName())) {
differentUser = !Strings.CS.equals(book.getCreatedByName(), userName);
}
if(enableProtection&&differentUser) {
if(Integer.valueOf(checkinProtection)>=0) {
for(int q=0;q<=Integer.valueOf(checkinProtection);q++) {
Date protectCheckin = DateTimeUtil.addDay( book.getCheckinDate(), Integer.valueOf(q));
protectionPeriod.add(protectCheckin);
}
}else {
for(int q=0;q>=Integer.valueOf(checkinProtection);q--) {
Date protectCheckin = DateTimeUtil.addDay( book.getCheckinDate(), Integer.valueOf(q));
protectionPeriod.add(protectCheckin);
}
}
//change check out date to check in
if(Integer.valueOf(checkoutProtection)>=0) {
for(int q=0;q<=Integer.valueOf(checkoutProtection);q++) {
Date protectCheckout = DateTimeUtil.addDay( book.getCheckinDate(), Integer.valueOf(q));
protectionPeriod.add(protectCheckout);
}
}else {
for(int q=0;q>=Integer.valueOf(checkoutProtection);q--) {
Date protectCheckout = DateTimeUtil.addDay( book.getCheckinDate(), Integer.valueOf(q));
protectionPeriod.add(protectCheckout);
}
}
}
Date checkInDate = book.getCheckinDate();
Date checkOutDate = book.getCheckoutDate();
while(checkInDate.getTime()<checkOutDate.getTime()) {
String getDate = DateTimeUtil.getDateByFormat(checkInDate, "yyyy-MM-dd");
if(resultList.containsKey(getDate)){
JSONObject res = resultList.get(getDate);
if(//StringUtils.isEmpty(book.getLastOperaStatus())||
Strings.CS.equals(book.getLastOperaStatus(), "DUE_IN")||
Strings.CS.equals(book.getLastOperaStatus(), "RESERVED")) {
res.put("reserved",1);
}else if(Strings.CS.equals(book.getLastOperaStatus(), "CHECKED_IN")) {
res.put("staying",1);
}
if(Strings.CS.equals(book.getBookingTypeName(), "Mass")&&book.getRevisionOf()==null) {
if(Strings.CS.equals(book.getRoomCategory(), "Standard Room")){
if(res.containsKey("massStandard")) {
int standareNum = res.getInteger("massStandard")+1;
res.put("massStandard", standareNum);
}else {
res.put("massStandard", 1);
}
}
if(Strings.CS.equals(book.getRoomCategory(), "Suite")) {
if(res.containsKey("massSuite")) {
int suiteNum = res.getInteger("massSuite")+1;
res.put("massSuite", suiteNum);
}else {
res.put("massSuite", 1);
}
}
}else if(Strings.CS.equals(book.getBookingTypeName(), "IM")&&book.getRevisionOf()==null) {
if(res.containsKey("im")) {
int suiteNum = res.getInteger("im")+1;
res.put("im", suiteNum);
}else {
res.put("im", 1);
}
}
resultList.put(getDate,res);
}
checkInDate = DateTimeUtil.addDay(checkInDate, 1);
}
}
}
for(Date period:protectionPeriod) {
String date = DateTimeUtil.getDateByFormat(period, "yyyy-MM-dd");
if(resultList.containsKey(date)){
JSONObject res = resultList.get(date);
res.put("protection",1);
resultList.put(date,res);
}
}
return resultList;
}
public List<CfgSettings> listRoomSetting() {
Sort sort = Sort.by(Direction.ASC, "keys");
return settingDao.findAll(sort);
}
public HashSet<String> listRoomCriteriaAvailableRoom(AvailableRoomQueryRequest queryParas) {
HashSet<String> resultList = new HashSet<>();
List<String> selectDate = queryParas.getSelectDate();
Date checkinDate = DateTimeUtil.getDateFromString(String.valueOf(selectDate.getFirst()), "yyyy-MM-dd");
Date checkoutDate = DateTimeUtil.getDateFromString(String.valueOf(selectDate.get(1)), "yyyy-MM-dd");
String diffDate = DateTimeUtil.getDiffDate(checkinDate, checkoutDate, "day");
Long blockId = queryParas.getBlockId();
Long propertyId = queryParas.getPropertyId();
Long roomId = queryParas.getRoomId();
List<Long> roomIds = new ArrayList<Long>();
roomIds.add(roomId);
List<CfgRoomCriterias> criterias = criteriaDao.findByRoomIdNotInAndPropertyIdAndBookDateBetween(roomIds,propertyId,checkinDate,checkoutDate);
HashMap<String,List<String>> criteriaMap= new HashMap<>();
for(CfgRoomCriterias c:criterias) {
if(c.getIsWaitlist()==0) {
CfgAppChannel channel = new CfgAppChannel();
Set<CfgAppChannel> channels = c.getChannels();
for(CfgAppChannel a:channels) {
if(blockId.equals(a.getBlockId())) channel = a;
}
if(channel.getAvailable()>0) {
String roomName = c.getRoom().getName();
if(criteriaMap.containsKey(roomName)) {
List<String> roomList = criteriaMap.get(roomName);
roomList.add(roomName);
criteriaMap.put(roomName, roomList);
}else {
List<String> roomList = new ArrayList<>();
roomList.add(roomName);
criteriaMap.put(roomName, roomList);
}
}
}
}
criteriaMap.forEach((key, value) -> {
if((Integer.parseInt(diffDate)+1)==value.size()) {
resultList.add(key);
}
});
return resultList;
}
public List<Bookings> listIsExtendBooking(ExtendBookingQueryRequest queryParas) {
List<Bookings> bookingList = new ArrayList<>();
Date checkoutDate = DateTimeUtil.getDateFromString(queryParas.getCheckoutDate(), "yyyy-MM-dd");
Date checkinDate = DateTimeUtil.getDateFromString(queryParas.getCheckinDate(), "yyyy-MM-dd");
String playerId = queryParas.getPlayerId();
String userId = queryParas.getUserId();
String propertyId = queryParas.getPropertyId();
String roomId = queryParas.getRoomId();
bookingList = bookingDao.getExtendBooking(checkoutDate,playerId,userId,propertyId,roomId);
return bookingList;
}
public List<Bookings> getWaitlistBooking(WaitlistBookingQueryRequest queryParas) throws Exception {
List<Bookings> bookingList = new ArrayList<>();
Date checkoutDate = DateTimeUtil.getDateFromString(queryParas.getCheckoutDate(), "yyyy-MM-dd");
Date checkinDate = DateTimeUtil.getDateFromString(queryParas.getCheckinDate(), "yyyy-MM-dd");
String playerId = queryParas.getPlayerId();
String userId = queryParas.getUserId();
// String propertyId = String.valueOf(queryParas.get("propertyId"));
// String roomId = String.valueOf(queryParas.get("roomId"));
List<Bookings> dbBookingList = bookingDao.getWaitlistBooking(checkinDate,checkoutDate,playerId,userId);
List<BookingsView> waitlistResult = waitlistBookingService.getBookingsByPlayer(playerId);
for(Bookings b :dbBookingList) {
for(BookingsView bv:waitlistResult) {
if(b.getId().equals(bv.getId())) {
bookingList.add(b);
}
}
}
return bookingList;
}
public List<CfgBookingTypes> listAllBookingType() {
return bookingTypeDao.findAll();
}
}
@@ -0,0 +1,28 @@
package com.mgm.mcrm.appsetting.services;
import java.util.List;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import com.mgm.mcrm.appsetting.models.CfgSettings;
import com.mgm.mcrm.appsetting.repositories.SettingDao;
@Service
public class SettingService {
@Resource
private SettingDao settingDao;
public CfgSettings getSettingByKey(String key) {
CfgSettings setting = null;
setting = settingDao.getByKeys(key);
return setting;
}
public List<CfgSettings> getSysSettingsAll() {
List<CfgSettings> list = settingDao.findAll();
return list;
}
}
@@ -0,0 +1,45 @@
package com.mgm.mcrm.appsetting.services;
import java.util.List;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.Strings;
import org.springframework.stereotype.Service;
import com.mgm.mcrm.appsetting.models.SysSetting;
import com.mgm.mcrm.appsetting.repositories.SysSettingDao;
@Service
public class SysSettingService {
@Resource
private SysSettingDao sysSettingDao;
public SysSetting getSysSettingByKey(String key) {
return sysSettingDao.getBySettingKey(key);
}
public List<SysSetting> getSysSettingsAll() {
return sysSettingDao.findAll();
}
public SysSetting save(SysSetting obj) {
return sysSettingDao.save(obj);
}
public boolean isAPPMock() {
SysSetting sysSetting = sysSettingDao.getBySettingKey("APP_MOCK");
return Strings.CS.equals(sysSetting.getSettingValue(), "1");
}
public boolean isMockReplicate() {
SysSetting sysSetting = sysSettingDao.getBySettingKey("APP_MOCK_REPLICATE");
return Strings.CS.equals(sysSetting.getSettingValue(), "1");
}
public boolean isDBDbugLog() {
SysSetting sysSetting = sysSettingDao.getBySettingKey("DB_DEBUG_LOG");
return Strings.CS.equals(sysSetting.getSettingValue(), "1");
}
}
@@ -0,0 +1,408 @@
package com.mgm.mcrm.authorization.controllers;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import com.mgm.mcrm.authorization.dtos.*;
import com.mgm.mcrm.authorization.models.SysGroup;
import com.mgm.mcrm.authorization.models.SysRouterPermission;
import com.mgm.mcrm.authorization.models.Token;
import com.mgm.mcrm.authorization.services.*;
import com.mgm.mcrm.authorization.utils.JwtTokenUtil;
import com.mgm.mcrm.basesetting.team.models.CfgSections;
import com.mgm.mcrm.basesetting.team.repositories.SectionDao;
import com.mgm.mcrm.common.dtos.BaseApiResponse;
import com.mgm.mcrm.common.utils.*;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Base64Util;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import com.auth0.jwt.JWT;
import com.mgm.mcrm.common.constants.SysCommon;
import com.mgm.mcrm.common.constants.SysConstants;
import com.mgm.mcrm.authorization.repositories.SysGroupDao;
import com.mgm.mcrm.appsetting.models.CfgSettings;
import com.mgm.mcrm.common.dtos.mgm_api.CheckApproverResult;
import com.mgm.mcrm.common.dtos.mgm_api.UserInfoApiRecord;
import com.mgm.mcrm.appsetting.services.SettingService;
@Tag(name = "Authorization", description = "APIs for Authorization functions")
@RestController
@CrossOrigin(origins = "*")
@RequestMapping("/api")
public class MobileLoginController {
@Resource
private MgmUserService mgmUserService;
@Resource
private AuthorizationService authService;
@Resource
private UserTokenService userTokenService;
@Resource
private SettingService settingService;
@Resource
private SysGroupDao sysGroupDao;
@Resource
private SectionDao sectionDao;
@Resource
private SysGroupPermissionService sysGroupPermissionService;
// 该方法用于模拟sso登录,生产环境下不适用
@RequestMapping(value = "/app/sso/mock_user_sso_login", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public ResponseEntity<AccountLoginResponse> mockupUserLogin(HttpServletRequest request, HttpServletResponse response, @RequestBody(required=true) @Valid AccountLoginRequest accountLoginRequest) throws IOException {
AccountLoginResponse result = new AccountLoginResponse();
String userId = accountLoginRequest.getUserId();
String password = accountLoginRequest.getCredential();
String propertyCode = accountLoginRequest.getPropertyCode();
String accessIp = NetworkUtil.getClientIpAddr(request);
boolean isInternal = NetworkUtil.isMatchInternal(accessIp);
String remoteAddr = request.getRemoteAddr();
boolean allowIP = NetworkUtil.isRequestFromTrustedSource(request);
if(!allowIP) {
LogUtil.warn(MobileLoginController.class, "IP of ["+remoteAddr+"] is not valid proxy IP ");
response.sendError(401, "Invalid Forward IP");
}
if(!isInternal){
LogUtil.info(MobileLoginController.class, "[preHandle] getRealIp:" + accessIp);
CfgSettings macauIpSetting = settingService.getSettingByKey(SysConstants.MACAU_IP);
String isMacauIP = String.valueOf(NetworkUtil.isMacauIp(accessIp,macauIpSetting.getKeyValues()));
LogUtil.info(MobileLoginController.class, "[preHandle] MockTest isMacauIP:" + isMacauIP);
response.setHeader("MacauIP", isMacauIP);
}
response.setHeader("IsInternal",String.valueOf(isInternal));
int loginTag = authService.checkLoginByLoginIdAndPasswordAndIp(userId, password, accessIp);
if(loginTag>0) {
LoginUserInfo loginUser = new LoginUserInfo();
loginUser.setId(0L);
loginUser.setLoginId(userId);
Token accessToken = JwtTokenUtil.generateTokenByLoginUser(request.getRequestURI(),loginUser, SysConstants.MOBILE_TOKEN_TYPE,false);
userTokenService.saveToken(accessToken);
Token refreshToken = JwtTokenUtil.generateTokenByLoginUser(request.getRequestURI(),loginUser, SysConstants.MOBILE_TOKEN_TYPE,true);
userTokenService.saveToken(refreshToken);
result.setSuccess(true);
result.setData(accessToken.getToken());
result.setAccessToken(accessToken.getToken());
result.setRefreshToken(refreshToken.getToken());
} else if (loginTag == -4) {
result.setSuccess(false);
result.setCode("ERROR_IP_BANNED");
} else if(loginTag == -2) {
result.setSuccess(false);
result.setCode("ERROR_LOCKED");
// return ResponseEntity.status(HttpStatus.FORBIDDEN).body(result);
} else {
result.setSuccess(false);
}
LogUtil.info(MobileLoginController.class,"[checkLoginByLoginIdAndPasswordAndIp][Local account]userId="+ userId +",resultTag"+String.valueOf(loginTag));
return ResponseEntity.status(HttpStatus.OK).body(result);
}
@RequestMapping(value = "/app/sso/user_sso_login", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public ResponseEntity<SsoLoginResponse> userSsoLogin(HttpServletRequest request, HttpServletResponse response, @RequestBody(required=true) SsoLoginRequest ssoLoginRequest) throws IOException {
SsoLoginResponse result = new SsoLoginResponse();
LoginUserInfo loginUser= null;
String tokenData ="";
if(StringUtils.isNotBlank(ssoLoginRequest.getSamlResponse())) {
tokenData = ssoLoginRequest.getSamlResponse();
loginUser= ADFSUtil.parseADFSToken(tokenData);
loginUser.setGroupName(hasDBGroup(loginUser.getGroupName()));
}else if(StringUtils.isNotBlank(ssoLoginRequest.getIdToken())) {
tokenData = ssoLoginRequest.getIdToken();
loginUser= ADFSUtil.parseJWTToken(tokenData);
}
if(StringUtils.isBlank(tokenData)) {
result.setSuccess(false);
result.setMessage("Token data is empty.");
result.setLogMessage("Token data is empty.");
}else {
if(loginUser==null) {
result.setSuccess(false);
result.setMessage("SSO Login Failed.");
}else if(loginUser.getLoginId()==null){
result.setSuccess(false);
result.setMessage("Can not get login ID.");
}else {
String userId = loginUser.getLoginId().toLowerCase();
if(userId.contains("@")) {
String[] userIdArr = StringUtils.split(userId,"@");
userId = userIdArr[0];
}
if(userId.contains("dev")) {
userId = userId.replace("dev", "");
}
BaseApiResponse<UserInfoApiRecord> serviceResult = mgmUserService.findUserInfoByUserId(userId);
if(serviceResult.isSuccess()) {
UserInfoApiRecord userInfo = serviceResult.getData();
userInfo.setLoginTag(true);
//--get group permissions
List<SysRouterPermission> userPermissions = sysGroupPermissionService.getRouterPermissionsByGroupName(loginUser.getGroupName());
if(!userPermissions.isEmpty()) {
for(SysRouterPermission per:userPermissions) {
if(SysConstants.PERMISSION_APP_VIEW_BOOKING.equals(per.getId())) userInfo.setCanViewBooking(true);
if(SysConstants.PERMISSION_APP_NEW_BOOKING.equals(per.getId())) userInfo.setCanNewBooking(true);
if(SysConstants.PERMISSION_APP_TODO_LIST.equals(per.getId())) userInfo.setCanViewTodoList(true);
if(SysConstants.PERMISSION_APP_DASHBOARD.equals(per.getId())) userInfo.setCanViewDashboard(true);
if(SysConstants.PERMISSION_APP_APPROVAL.equals(per.getId())) userInfo.setCanViewApproval(true);
}
}
Token accessToken = JwtTokenUtil.generateTokenByLoginUser(request.getRequestURI(),loginUser, SysConstants.MOBILE_TOKEN_TYPE,false);
userTokenService.saveToken(accessToken);
Token refreshToken = JwtTokenUtil.generateTokenByLoginUser(request.getRequestURI(),loginUser, SysConstants.MOBILE_TOKEN_TYPE,true);
userTokenService.saveToken(refreshToken);
result.setSuccess(true);
result.setIdToken(tokenData);
result.setAccessToken(accessToken.getToken());
result.setRefreshToken(refreshToken.getToken());
result.setUserData(userInfo);
result.setClientId(EncryptUtil.sha256(Base64Util.encode("mcrm_" + userId)));
}else {
result.setSuccess(false);
result.setMessage(serviceResult.getMessage());
}
}
}
String accessIp = NetworkUtil.getClientIpAddr(request);
boolean isInternal = NetworkUtil.isMatchInternal(accessIp);
String remoteAddr = request.getRemoteAddr();
if(!isInternal){
LogUtil.info(MobileLoginController.class, "[preHandle] getRealIp:" + accessIp);
CfgSettings macauIpSetting = settingService.getSettingByKey(SysConstants.MACAU_IP);
String isMacauIP = String.valueOf(NetworkUtil.isMacauIp(accessIp,macauIpSetting.getKeyValues()));
LogUtil.info(MobileLoginController.class, "[preHandle] MockTest isMacauIP:" + isMacauIP);
response.setHeader("MacauIP", isMacauIP);
}
response.setHeader("IsInternal",String.valueOf(isInternal));
return ResponseEntity.status(HttpStatus.OK).body(result);
}
// 接入SSO的时候修改此方法
@RequestMapping(value = "/app/sso/get_sso_token_by_code", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public ResponseEntity<SsoLoginResponse> getTokenByCode(HttpServletRequest request, HttpServletResponse response, @RequestBody(required=true) SsoLoginRequest ssoLoginRequest) {
String code = ssoLoginRequest.getCode();
boolean mockSSO = ssoLoginRequest.isMockSSO();
String clientId = request.getHeader("ClientId");
boolean res = JwtTokenUtil.checkToken(code, clientId);
Token dbToken = userTokenService.getToken(code);
if(dbToken==null) {
LogUtil.error(MobileLoginController.class, "[checkToken] No DB Token");
res = false;
}
SsoLoginResponse result = new SsoLoginResponse();
if(!res) {
result.setSuccess(false);
result.setMessage("Invalid Token");
}
String ssoToken = "";
String userId = "";
if(mockSSO) {
ssoToken = code;
userId = JWT.decode(ssoToken).getClaim("login_id").asString();
}else {
ssoToken = ""; // 调用SSO API
userId = "";
}
BaseApiResponse<UserInfoApiRecord> serviceResult = mgmUserService.findUserInfoByUserId(userId);
if(serviceResult.isSuccess()) {
UserInfoApiRecord userInfo = serviceResult.getData();
userInfo.setLoginTag(true);
LoginUserInfo user = new LoginUserInfo();
CfgSections section = sectionDao.getByName(userInfo.getSection());
userInfo.setSectionId(section.getId());
user.setLoginId(userId);
user.setGroupName(userInfo.getGroupName());
userTokenService.clearTokenByUser(userId,SysConstants.MOBILE_TOKEN_TYPE);
Token accessToken = JwtTokenUtil.generateTokenByLoginUser(request.getRequestURI(),user, SysConstants.MOBILE_TOKEN_TYPE,false);
userTokenService.saveToken(accessToken);
Token refreshToken = JwtTokenUtil.generateTokenByLoginUser(request.getRequestURI(),user, SysConstants.MOBILE_TOKEN_TYPE,true);
userTokenService.saveToken(refreshToken);
result.setIdToken(ssoToken);
result.setAccessToken(accessToken.getToken());
result.setRefreshToken(refreshToken.getToken());
result.setUserData(userInfo);
result.setClientId(EncryptUtil.sha256(Base64Util.encode("mcrm_"+userId)));
result.setSuccess(true);
}else {
result.setSuccess(false);
result.setMessage(serviceResult.getMessage());
}
return ResponseEntity.status(HttpStatus.OK).body(result);
}
@RequestMapping(value = "/app/me", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public HashMap<String, Object> verifyToken(HttpServletRequest request, HttpServletResponse response) {
HashMap<String, Object> objReturn = new HashMap<String, Object>();
// 这里可以return一些信息,每次刷新页面或者跳转页面的时候重新拿一次某些信息。
objReturn.put("status", 200);
return objReturn;
}
@RequestMapping(value = "/app/refresh_token", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public ResponseEntity<RefreshTokenResponse> refreshToken(HttpServletRequest request, HttpServletResponse response) throws IOException {
String isReNew = request.getParameter("isRenewRefreshToken");
boolean isRenewRefreshToken = (!"false".equalsIgnoreCase(isReNew));
RefreshTokenResponse result = new RefreshTokenResponse();
LoginUserInfo loginUser = JwtTokenUtil.parseUserFromRequest(request);
if(loginUser!=null){
Token accessToken = JwtTokenUtil.generateTokenByLoginUser(request.getRequestURI(),loginUser,SysConstants.MOBILE_TOKEN_TYPE,false);
userTokenService.updateTokenByUniqueId(loginUser.getTokenUuid(),SysConstants.MOBILE_TOKEN_TYPE,accessToken);
result.setAccessToken(accessToken.getToken());
if(isRenewRefreshToken){
Token refreshToken = JwtTokenUtil.generateTokenByLoginUser(request.getRequestURI(),loginUser,SysConstants.MOBILE_TOKEN_TYPE,true);
userTokenService.saveToken(refreshToken);
result.setRefreshToken(refreshToken.getToken());
if(StringUtils.isNotBlank(loginUser.getTokenUuid())){
userTokenService.removeTokenByUniqueId(loginUser.getTokenUuid(),SysConstants.MOBILE_TOKEN_TYPE);
}
}
result.setSuccess(true);
return ResponseEntity.status(HttpStatus.OK).body(result);
}else{
result.setSuccess(false);
result.setCode("401");
result.setMessage("Unauthorized operation");
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(result);
}
}
@RequestMapping(value="/app/logout",method = RequestMethod.POST)
public BaseApiResponse<Integer> logout(HttpServletRequest request) {
LoginUserInfo loginUser = JwtTokenUtil.parseUserFromRequest(request);
int count = 0;
if(loginUser!=null){
count = userTokenService.clearTokenByUser(loginUser.getLoginId(),SysConstants.MOBILE_TOKEN_TYPE);
}
BaseApiResponse<Integer> result = new BaseApiResponse<>();
result.setSuccess(true);
result.setMessage("Logout successful");
result.setData(count);
return result;
}
@RequestMapping(value = "/web/user/lookup", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public ResponseEntity<BaseApiResponse<UserInfoApiRecord>> lookupUser(HttpServletRequest request, HttpServletResponse response,
@RequestBody UserLookupRequest params) throws Exception {
BaseApiResponse<UserInfoApiRecord> result = new BaseApiResponse<>();
String userId = params.getUserId();
if (StringUtils.isEmpty(userId)) {
response.sendError(422, "Miss parameter userId");
return null;
}
if(!StringUtils.isEmpty(userId)) {
userId = userId.replace("@mgm.mo", "");
}
BaseApiResponse<UserInfoApiRecord> serviceResult = mgmUserService.findUserInfoByUserId(userId);
if(serviceResult.isSuccess()) {
result.setSuccess(true);
result.setData(serviceResult.getData());
}else {
result.setSuccess(false);
result.setMessage(serviceResult.getMessage());
}
//--
return ResponseEntity.status(HttpStatus.OK).body(result);
}
@RequestMapping(value = "/web/user/lookup_name", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public ResponseEntity<BaseApiResponse<List<UserInfoApiRecord>>> lookupUserName(HttpServletRequest request, HttpServletResponse response,
@RequestBody UserLookupRequest params) throws Exception {
String userName = params.getUserName();
if (StringUtils.isEmpty(userName)) {
response.sendError(422, "Miss parameter userName");
return null;
}
BaseApiResponse<List<UserInfoApiRecord>> result = mgmUserService.findUserInfoByUserName(userName);
return ResponseEntity.status(HttpStatus.OK).body(result);
}
@RequestMapping(value = "/web/user/check_approver", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
public ResponseEntity<BaseApiResponse<CheckApproverResult>> checkApprover(HttpServletRequest request, HttpServletResponse response,
@RequestBody CheckApproverResult params) throws Exception {
BaseApiResponse<CheckApproverResult> result = new BaseApiResponse<>();
String userId = params.getUserId();
String userName = params.getUserName();
String roomType = params.getRoomType();
String property = params.getProperty();
if(!StringUtils.isEmpty(userId)) {
userId = userId.replace("@mgm.mo", "");
}
if ((StringUtils.isEmpty(userId)&&StringUtils.isEmpty(userName))||StringUtils.isEmpty(roomType)||StringUtils.isEmpty(property)) {
result.setSuccess(false);
result.setMessage("Miss parameter");
return ResponseEntity.status(HttpStatus.OK).body(result);
}
BaseApiResponse<CheckApproverResult> checkResult = mgmUserService.checkApprover(userId,userName,roomType,property);
if(SysCommon.mgmApiMockup) {
CheckApproverResult resultObj = new CheckApproverResult();
resultObj.setIsApprover("1");
resultObj.setProperty(property);
resultObj.setUserName("test");
resultObj.setUserId("80001");
resultObj.setRoomCategory(roomType);
resultObj.setStatusCode("OK");
checkResult.setSuccess(true);
if("80001".equals(userId)||"test".equals(userName)) {
}else {
resultObj.setUserId(null);
resultObj.setUserName(null);
resultObj.setIsApprover("0");
}
checkResult.setData(resultObj);
}
if(checkResult.isSuccess()) {
result.setSuccess(true);
result.setData(checkResult.getData());
}else {
result.setSuccess(false);
result.setMessage(checkResult.getMessage());
}
return ResponseEntity.status(HttpStatus.OK).body(result);
}
// ADFS登录时 判断返回的User Group是否存在DB中
public String hasDBGroup(String group) {
if (group == null || group.trim().isEmpty()) {
return "";
}
String[] groups = group.split(";");
StringBuilder dbGroupBuilder = new StringBuilder();
for (String groupName : groups) {
if (groupName == null || groupName.trim().isEmpty()) {
continue;
}
SysGroup sysGroup = sysGroupDao.findByDisplayName(groupName.trim());
if (sysGroup != null && sysGroup.getDisplayName() != null) {
if (!dbGroupBuilder.isEmpty()) {
dbGroupBuilder.append(";");
}
dbGroupBuilder.append(sysGroup.getDisplayName());
}
}
return dbGroupBuilder.toString();
}
}
@@ -0,0 +1,13 @@
package com.mgm.mcrm.authorization.dtos;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
@Data
public class AccountLoginRequest {
@NotBlank
private String userId;
@NotBlank
private String credential;
private String propertyCode;
}
@@ -0,0 +1,12 @@
package com.mgm.mcrm.authorization.dtos;
import com.mgm.mcrm.common.dtos.BaseApiResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class AccountLoginResponse extends BaseApiResponse<String> {
private String accessToken;
private String refreshToken;
}
@@ -0,0 +1,22 @@
package com.mgm.mcrm.authorization.dtos;
import java.sql.Date;
import java.util.List;
import com.mgm.mcrm.authorization.models.SysRouter;
import com.mgm.mcrm.authorization.models.SysRouterPermission;
import com.mgm.mcrm.authorization.models.SysUserSetting;
import com.mgm.mcrm.authorization.models.SysUserView;
import lombok.Data;
@Data
public class LoginInfo {
private SysUserView loginUser;
private String defaultRouter;
private String accessToken;
private Date lastPostTime;
private List<SysUserSetting> listUserSetting;
private List<SysRouter> listRouter;
private List<SysRouterPermission> listGroupPermission;
}
@@ -0,0 +1,12 @@
package com.mgm.mcrm.authorization.dtos;
import lombok.Data;
@Data
public class LoginUserInfo {
private Long id;
private String loginId;
private String displayName;
private String groupName;
private String tokenUuid;
}
@@ -0,0 +1,20 @@
package com.mgm.mcrm.authorization.dtos;
import com.mgm.mcrm.common.dtos.BaseApiResponse;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
@Schema(description = "Response info of refreshing App access token")
public class RefreshTokenResponse extends BaseApiResponse {
@Schema(description = "New API JWT token generated")
private String accessToken;
@Schema(description = "New Refresh JWT token generated")
private String refreshToken;
}
@@ -0,0 +1,11 @@
package com.mgm.mcrm.authorization.dtos;
import lombok.Data;
@Data
public class SsoLoginRequest {
private String samlResponse;
private String idToken;
private String code;
private boolean mockSSO=false;
}
@@ -0,0 +1,16 @@
package com.mgm.mcrm.authorization.dtos;
import com.mgm.mcrm.common.dtos.BaseApiResponse;
import com.mgm.mcrm.common.dtos.mgm_api.UserInfoApiRecord;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class SsoLoginResponse extends BaseApiResponse {
private String idToken;
private String accessToken;
private String refreshToken;
private UserInfoApiRecord userData;
private String clientId;
}
@@ -0,0 +1,9 @@
package com.mgm.mcrm.authorization.dtos;
import lombok.Data;
@Data
public class UserLookupRequest {
private String userName;
private String userId;
}
@@ -0,0 +1,183 @@
package com.mgm.mcrm.authorization.filters;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.mgm.mcrm.appsetting.models.CfgSettings;
import com.mgm.mcrm.appsetting.services.SettingService;
import com.mgm.mcrm.authorization.dtos.LoginUserInfo;
import com.mgm.mcrm.authorization.models.Token;
import com.mgm.mcrm.authorization.services.UserTokenService;
import com.mgm.mcrm.authorization.utils.JwtTokenUtil;
import com.mgm.mcrm.common.constants.SysCommon;
import com.mgm.mcrm.common.constants.SysConstants;
import com.mgm.mcrm.common.utils.EncryptUtil;
import com.mgm.mcrm.common.utils.LogUtil;
import com.mgm.mcrm.common.utils.NetworkUtil;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.NonNull;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Base64Util;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
public class JwtAuthFilter extends OncePerRequestFilter {
private final AntPathMatcher pathMatcher = new AntPathMatcher();
@Setter
private List<String> excludePatterns;
@Setter
private UserTokenService userTokenService;
@Setter
private SettingService settingService;
private final List<String> ignoreCheckInternalUrl = Arrays.asList(
"app/logout",
"app/me",
"save_confirm_log",
"refresh_token",
"write_log",
"get_list",
"mock_user_sso_login",
"sso/",
"get_setting_by_key"
);
@Override
protected void doFilterInternal(
@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull FilterChain filterChain
) throws ServletException, IOException{
boolean validatePass = true;
try {
String token = request.getHeader("Authorization");
if(StringUtils.isNotBlank(token) && token.startsWith("Bearer ")){
token = token.substring(7);
}
Token dbToken = userTokenService.getToken(token);
if(StringUtils.isNotBlank(token) && dbToken!=null) {
JWTVerifier jwtVerifier = JwtTokenUtil.getJwtVerifier();
try {
jwtVerifier.verify(token);
}
catch (SignatureVerificationException e) {
LogUtil.error(JwtAuthFilter.class, "[preHandle] SignatureVerificationException \nException Message:" + e.getMessage());
sendErrorResponse(response,400, e.getMessage());
validatePass=false;
}
catch (TokenExpiredException e) {
if(!request.getRequestURI().contains("refresh_token")) {
LogUtil.error(JwtAuthFilter.class, "[preHandle] TokenExpiredException \nException Message:" + e.getMessage());
sendErrorResponse(response,401, e.getMessage());
validatePass=false;
}
}
catch (JWTVerificationException e) {
LogUtil.error(JwtAuthFilter.class, "[preHandle] JWTVerificationException \nException Message:" + e.getMessage());
sendErrorResponse(response,403, e.getMessage());
validatePass=false;
}
catch (Exception e) {
LogUtil.error(JwtAuthFilter.class, "[preHandle] Exception \nException Message:" + e.getMessage());
sendErrorResponse(response,500, e.getMessage());
validatePass=false;
}
String clientId = request.getHeader("clientId");
if(clientId==null) {
clientId="";
}
LoginUserInfo user = JwtTokenUtil.parseUserFromToken(token);
if(user!=null) {
String encrypt = EncryptUtil.sha256(Base64Util.encode("mcrm_"+user.getLoginId()));
if(!clientId.equalsIgnoreCase(encrypt)) {
sendErrorResponse(response,500, "Invalid Token");
validatePass=false;
}
}else {
LogUtil.info(JwtAuthFilter.class, "[preHandle] user null");
sendErrorResponse(response,500, "Invalid Token");
validatePass=false;
}
}else if(!"OPTIONS".equalsIgnoreCase(request.getMethod())) {
LogUtil.error(JwtAuthFilter.class, "[preHandle] Exception Method: " + request.getMethod());
sendErrorResponse(response,401, "Invalid Token");
validatePass=false;
}
}catch(Exception ex) {
LogUtil.error(JwtAuthFilter.class, "[preHandle] Exception \nException Message:" + ex.getMessage());
sendErrorResponse(response,500, ex.getMessage());
validatePass=false;
}
if(!"OPTIONS".equalsIgnoreCase(request.getMethod()) && validatePass){
boolean allowIP = NetworkUtil.isRequestFromTrustedSource(request);
if(!allowIP) {
sendErrorResponse(response,401, "Invalid Internal IP");
validatePass=false;
}else{
boolean canAccessIP = true;
String accessIp = NetworkUtil.getClientIpAddr(request);
if("INVALID_IP".equalsIgnoreCase(accessIp)){
sendErrorResponse(response,401, "Invalid IP in forward headers");
validatePass = false;
}
boolean isInternal = NetworkUtil.isMatchInternal(accessIp);
if(!isInternal) {
String uri = request.getRequestURI();
boolean isIgnoreUrl = false;
for(String urlKey:ignoreCheckInternalUrl){
if(uri.contains(urlKey)){
isIgnoreUrl=true;
break;
}
}
if(!isIgnoreUrl){
LogUtil.info(JwtAuthFilter.class, "[preHandle] getRealIp:" + accessIp);
CfgSettings macauIpSetting = settingService.getSettingByKey(SysConstants.MACAU_IP);
String isMacauIP = String.valueOf(NetworkUtil.isMacauIp(accessIp,macauIpSetting.getKeyValues()));
LogUtil.info(JwtAuthFilter.class, "[preHandle] isMacauIP:" + isMacauIP);
response.setHeader("MacauIP", isMacauIP);
if("false".equals(isMacauIP))
canAccessIP = false;
LogUtil.info(JwtAuthFilter.class, "[preHandle] canAccessIP:" + canAccessIP);
}
}else {
response.setHeader("MacauIP", "");
}
response.setHeader("IsInternal",String.valueOf(isInternal));
if(!canAccessIP) {
validatePass=false;
}
}
}
if(validatePass){
filterChain.doFilter(request, response);
}
}
@Override
protected boolean shouldNotFilter(@NonNull HttpServletRequest request) {
if (excludePatterns == null) {
return false;
}
return excludePatterns.stream()
.anyMatch(pattern -> pathMatcher.match(pattern, request.getRequestURI()));
}
private void sendErrorResponse(HttpServletResponse response, int errorCode, String errorMessage) throws IOException {
response.setStatus(errorCode);
response.setContentType("application/text");
response.setCharacterEncoding("UTF-8");
response.getWriter().write(errorMessage);
}
}
@@ -0,0 +1,43 @@
package com.mgm.mcrm.authorization.models;
import java.io.Serializable;
import java.util.Date;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@Entity
@Table(name="sys_groups")
public class SysGroup implements Serializable {
//fields in table
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name="display_name")
private String displayName;
@Column(name="default_property")
private String defaultProperty;
@Column(name="status")
private Integer status;
@Column(name="created_at")
private Date createdAt;
@Column(name="created_by")
private String createdBy;
@Column(name="updated_at")
private Date updatedAt;
@Column(name="updated_by")
private String updatedBy;
}
@@ -0,0 +1,34 @@
package com.mgm.mcrm.authorization.models;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@Entity
@Table(name="sys_group_data_permissions")
public class SysGroupDataPermission {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "group_id")
private Long groupId;
@Column(name="data_id")
private String dataId;
@Column(name="data_type")
private String dataType;
@Column(name="permission_id")
private String permissionId;
}
@@ -0,0 +1,28 @@
package com.mgm.mcrm.authorization.models;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.IdClass;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@Entity
@Table(name="sys_group_permissions")
@IdClass(SysGroupPermissionKey.class)
public class SysGroupPermission {
//fields in table
@Id
@Column(name = "group_id")
private Long groupId;
@Id
@Column(name="permission_id")
private String permissionId;
}
@@ -0,0 +1,38 @@
package com.mgm.mcrm.authorization.models;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.io.Serial;
import java.io.Serializable;
import java.util.Objects;
@Getter
@Setter
@NoArgsConstructor
public class SysGroupPermissionKey implements Serializable{
@Serial
private static final long serialVersionUID = 6060166117433738173L;
private Long groupId ;
private String permissionId;
@Override
public boolean equals(Object o) {
if(o instanceof SysGroupPermissionKey)
{
SysGroupPermissionKey key = (SysGroupPermissionKey)o ;
if(Objects.equals(this.groupId, key.getGroupId()) && Objects.equals(this.permissionId, key.getPermissionId()))
{
return true ;
}
}
return false ;
}
@Override
public int hashCode() {
return 1;
}
}
@@ -0,0 +1,73 @@
package com.mgm.mcrm.authorization.models;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.persistence.Transient;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;
import com.fasterxml.jackson.annotation.JsonInclude;
@Getter
@Setter
@NoArgsConstructor
@Entity
@Table(name="sys_routers")
public class SysRouter {
//fields in table
@Id
@JsonInclude(JsonInclude.Include.NON_NULL)
@Column(name = "id")
private String id;
@JsonInclude(JsonInclude.Include.NON_NULL)
@Column(name="parent_id")
private String parentId;
@JsonInclude(JsonInclude.Include.NON_NULL)
@Column(name="heading")
private String heading;
@JsonInclude(JsonInclude.Include.NON_NULL)
@Column(name="section_title")
private String sectionTitle;
@Column(name="route")
private String route;
@JsonInclude(JsonInclude.Include.NON_NULL)
@Column(name="svg_icon")
private String svgIcon;
@JsonInclude(JsonInclude.Include.NON_NULL)
@Column(name="font_icon")
private String fontIcon;
@JsonInclude(JsonInclude.Include.NON_NULL)
@Column(name="sort_no")
private Integer sortNo;
@JsonInclude(JsonInclude.Include.NON_NULL)
@Column(name="status")
private Integer status;
@JsonInclude(JsonInclude.Include.NON_NULL)
@Column(name="created_at")
private Date createdAt;
@JsonInclude(JsonInclude.Include.NON_NULL)
@Column(name="created_by")
private String createdBy;
@JsonInclude(JsonInclude.Include.NON_NULL)
@Column(name="updated_at")
private Date updatedAt;
@JsonInclude(JsonInclude.Include.NON_NULL)
@Column(name="updated_by")
private String updatedBy;
@Transient
@JsonInclude(JsonInclude.Include.NON_NULL)
private List<SysRouter> sub;
}
@@ -0,0 +1,31 @@
package com.mgm.mcrm.authorization.models;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.persistence.Transient;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@Entity
@Table(name = "sys_router_permissions")
public class SysRouterPermission {
@Id
@Column(name = "id")
private String id;
@Column(name = "router_id")
private String routerId;
@Column(name = "permission_code")
private String permissionCode;
@Column(name = "permission_name")
private String permissionName;
@Transient
private boolean selected=false;
@Transient
private String dataPermissionTag;
}
@@ -0,0 +1,50 @@
package com.mgm.mcrm.authorization.models;
import java.util.Date;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.persistence.Transient;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@Entity
@Table(name="sys_users")
public class SysUser {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name="login_id")
private String loginId;
@Column(name="display_name")
private String displayName;
@Column(name="password")
private String password;
@Column(name="category")
private Integer category;
@Column(name="status")
private Integer status;
@Column(name="try_times")
private Integer tryTimes;
@Column(name="created_at")
private Date createdAt;
@Column(name="created_by")
private String createdBy;
@Column(name="updated_at")
private Date updatedAt;
@Column(name="updated_by")
private String updatedBy;
@Transient
private String token;
}
@@ -0,0 +1,37 @@
package com.mgm.mcrm.authorization.models;
import java.io.Serializable;
import java.util.Date;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.IdClass;
import jakarta.persistence.Table;
import jakarta.persistence.Transient;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;
@Getter
@Setter
@NoArgsConstructor
@Entity
@Table(name="sys_user_settings")
@IdClass(SysUserSettingKey.class)
public class SysUserSetting {
@Id
@Column(name="user_id")
private Long userId;
@Id
@Column(name="setting_key")
private String settingKey;
@Column(name="setting_value")
private String settingValue;
}
@@ -0,0 +1,40 @@
package com.mgm.mcrm.authorization.models;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.io.Serial;
import java.io.Serializable;
import java.util.Objects;
@Getter
@Setter
@NoArgsConstructor
public class SysUserSettingKey implements Serializable{
@Serial
private static final long serialVersionUID = 6060166117433738173L;
private Long userId ;
private String settingKey;
@Override
public boolean equals(Object o) {
if(o instanceof SysUserSettingKey)
{
SysUserSettingKey key = (SysUserSettingKey)o ;
if(Objects.equals(this.userId, key.getUserId()) && Objects.equals(this.settingKey, key.getSettingKey()))
{
return true ;
}
}
return false ;
}
@Override
public int hashCode() {
return 1;
}
}
@@ -0,0 +1,57 @@
package com.mgm.mcrm.authorization.models;
import java.io.Serializable;
import java.util.Date;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.persistence.Transient;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@Entity
@Table(name="view_sys_user_group")
public class SysUserView implements Serializable{
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name="login_id")
private String loginId;
@Column(name="display_name")
private String displayName;
@Column(name="password")
private String password;
@Column(name="category")
private Integer category;
@Column(name="status")
private Integer status;
@Column(name="try_times")
private Integer tryTimes;
@Column(name="created_at")
private Date createdAt;
@Column(name="created_by")
private String createdBy;
@Column(name="updated_at")
private Date updatedAt;
@Column(name="updated_by")
private String updatedBy;
@Column(name="group_id")
private Long groupId;
@Column(name="group_name")
private String groupName;
@Column(name="default_property")
private String defaultProperty;
@Transient
private String token;
}
@@ -0,0 +1,37 @@
package com.mgm.mcrm.authorization.models;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.time.LocalDateTime;
@Getter
@Setter
@NoArgsConstructor
@Entity
@Table(name="token")
public class Token {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name="token")
private String token;
@Column(name="created_at")
private LocalDateTime createdAt;
@Column(name="created_by")
private String createdBy;
@Column(name="updated_at")
private LocalDateTime updatedAt;
@Column(name="updated_by")
private String updatedBy;
@Column(name = "token_type")
private Integer tokenType;
@Column(name = "uuid")
private String uuid;
@Column(name = "expire_time")
private LocalDateTime expireTime;
}
@@ -0,0 +1,23 @@
package com.mgm.mcrm.authorization.repositories;
import java.util.List;
import com.mgm.mcrm.authorization.models.SysGroup;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;
public interface SysGroupDao extends JpaRepository<SysGroup, Long> {
SysGroup findByDisplayName(String displayName);
List<SysGroup> findAll(Specification<SysGroup> spec,Sort sort);
List<SysGroup> findAll(Specification<SysGroup> spec);
Page<SysGroup> findAll(Specification<SysGroup> spec, Pageable pageable);
}
@@ -0,0 +1,22 @@
package com.mgm.mcrm.authorization.repositories;
import java.util.List;
import com.mgm.mcrm.authorization.models.SysGroupDataPermission;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
public interface SysGroupDataPermissionDao extends JpaRepository<SysGroupDataPermission, String> {
List<SysGroupDataPermission> findAll(Specification<SysGroupDataPermission> spec,Sort sort);
List<SysGroupDataPermission> findAll(Specification<SysGroupDataPermission> spec);
@Query(value = "select data_id from sys_group_data_permissions d" +
" where group_id in (select id from sys_groups where upper(display_name) in (?1)) "
+ " and permission_id=?2 and data_type=?3 ",nativeQuery=true)
List<String> queryAccessDataByGroupNameAndType(List<String> groupNameList, String routerId, String dataType);
}
@@ -0,0 +1,20 @@
package com.mgm.mcrm.authorization.repositories;
import java.util.List;
import com.mgm.mcrm.authorization.models.SysGroupPermission;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
public interface SysGroupPermissionDao extends JpaRepository<SysGroupPermission, String> {
List<SysGroupPermission> findAll(Specification<SysGroupPermission> spec,Sort sort);
List<SysGroupPermission> findAll(Specification<SysGroupPermission> spec);
@Query(value="select * from sys_group_permissions where group_id=?1",nativeQuery=true)
List<SysGroupPermission> getAllByGroupId(long groupId);
}
@@ -0,0 +1,22 @@
package com.mgm.mcrm.authorization.repositories;
import java.util.List;
import com.mgm.mcrm.authorization.models.SysRouter;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;
public interface SysRouterDao extends JpaRepository<SysRouter, String> {
List<SysRouter> findAll(Specification<SysRouter> spec,Sort sort);
List<SysRouter> findAll(Specification<SysRouter> spec);
Page<Object> findAll(Specification<SysRouter> spec, Pageable pageable);
}
@@ -0,0 +1,31 @@
package com.mgm.mcrm.authorization.repositories;
import java.util.List;
import com.mgm.mcrm.authorization.models.SysRouter;
import com.mgm.mcrm.authorization.models.SysRouterPermission;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
public interface SysRouterPermissionDao extends JpaRepository<SysRouterPermission, String> {
List<SysRouterPermission> findAll(Specification<SysRouterPermission> spec, Sort sort);
List<SysRouterPermission> findAll(Specification<SysRouterPermission> spec);
Page<SysRouterPermission> findAll(Specification<SysRouter> spec, Pageable pageable);
@Query("""
select rp
from SysRouterPermission rp
join SysGroupPermission grp on rp.id = grp.permissionId
join SysGroup g on g.id = grp.groupId
where g.displayName in (?1)
""")
List<SysRouterPermission> queryPermssionByGroupNameList(List<String> groupNameList);
}
@@ -0,0 +1,33 @@
package com.mgm.mcrm.authorization.repositories;
import java.util.List;
import com.mgm.mcrm.authorization.models.SysUser;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;
public interface SysUserDao extends JpaRepository<SysUser, String> {
SysUser findById(long id);
List<SysUser> findAll(Specification<SysUser> spec,Sort sort);
List<SysUser> findAll(Specification<SysUser> spec);
Page<SysUser> findAll(Specification<SysUser> spec, Pageable pageable);
@Transactional
@Modifying
@Query(value = " delete from sys_users where ID=?1 ",nativeQuery=true)
int deleteById(long id);
@Query(value="select * from sys_users where upper(login_id) =?1",nativeQuery=true)
SysUser getByLoginId(String loginId);
@Query(value = "select count(1) as user_cnt from sys_users where upper(login_id) =?1 and password=?2 ",nativeQuery=true)
int countSysUserByLoginIdAndPassword(String loginId, String password);
}
@@ -0,0 +1,13 @@
package com.mgm.mcrm.authorization.repositories;
import java.util.List;
import com.mgm.mcrm.authorization.models.SysUserSetting;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
public interface SysUserSettingDao extends JpaRepository<SysUserSetting, String> {
}
@@ -0,0 +1,25 @@
package com.mgm.mcrm.authorization.repositories;
import java.util.List;
import com.mgm.mcrm.authorization.models.SysUserView;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
public interface SysUserViewDao extends JpaRepository<SysUserView, String> {
SysUserView findById(long id);
List<SysUserView> findAll(Specification<SysUserView> spec,Sort sort);
List<SysUserView> findAll(Specification<SysUserView> spec);
Page<SysUserView> findAll(Specification<SysUserView> spec, Pageable pageable);
@Query(value="select * from view_sys_user_group where upper(login_id) =?1",nativeQuery=true)
SysUserView getByLoginId(String loginId);
}
@@ -0,0 +1,37 @@
package com.mgm.mcrm.authorization.repositories;
import com.mgm.mcrm.authorization.models.Token;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;
public interface TokenDao extends JpaRepository<Token, String> {
Token findById(long id);
@Deprecated
Token findByToken(String token);
Token findByUuid(String uuid);
Token findByUuidAndTokenType(String uuid, int tokenType);
@Deprecated
@Transactional
@Modifying
@Query(value = " delete from token where token=?1 ",nativeQuery=true)
int deleteByToken(String token);
@Transactional
@Modifying
@Query(value = " delete from token where uuid=?1 and token_type=?2 ",nativeQuery=true)
int deleteByUuidAndTokenType(String uuid, int tokenType);
@Transactional
@Modifying
@Query(value = " delete from token where created_by=?1 and token_type=?2 ",nativeQuery=true)
int deleteByUserIdAndTokenType(String userId, int tokenType);
}
@@ -0,0 +1,165 @@
package com.mgm.mcrm.authorization.services;
import java.util.*;
import com.google.gson.Gson;
import com.mgm.mcrm.authorization.models.SysRouterPermission;
import com.mgm.mcrm.authorization.models.SysUser;
import com.mgm.mcrm.authorization.repositories.SysGroupDataPermissionDao;
import com.mgm.mcrm.authorization.repositories.SysGroupPermissionDao;
import com.mgm.mcrm.authorization.repositories.SysRouterPermissionDao;
import com.mgm.mcrm.booking.services.BookingService;
import com.mgm.mcrm.logging.services.SysLogLoginIpService;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import com.mgm.mcrm.logging.models.SysLogLoginIp;
import com.mgm.mcrm.appsetting.models.CfgSettings;
import com.mgm.mcrm.appsetting.services.SettingService;
import com.mgm.mcrm.common.utils.LogUtil;
import com.mgm.mcrm.common.constants.SysCommon;
import com.mgm.mcrm.authorization.repositories.SysUserDao;
@Service
public class AuthorizationService {
@Resource
private SysUserDao sysUserDao;
@Resource
private SysGroupDataPermissionDao sysGroupDataDao;
@Resource
private SysGroupPermissionDao sysGroupPermissionDao;
@Resource
private SysRouterPermissionDao routerPermissionDao;
@Resource
private SettingService settingService;
@Resource
private SysLogLoginIpService sysLogLoginIpService;
// -4=ip has been banned, -3=disabled, -2=locked, -1 or 0=incorrect loginId or password, 1=success
public int checkLoginByLoginIdAndPasswordAndIp(String loginId, String password, String clientIp) {
// IP 层级预检查 (已封禁直接拦截)
if (sysLogLoginIpService.isBanned(clientIp)) {
return -4;
}
// 获取基础配置
int maxIpTries = Integer.parseInt(settingService.getSettingByKey("TRY_USERNAME_TIMES").getKeyValues());
int banMins = Integer.parseInt(settingService.getSettingByKey("RETRY_USERNAME_AFTER_MINS").getKeyValues());
int maxPwdTries = Integer.parseInt(settingService.getSettingByKey("TRY_PASSWORD_TIMES").getKeyValues());
SysLogLoginIp sysLogLoginIp = sysLogLoginIpService.findTodayRecordByIp(clientIp);
if (sysLogLoginIp == null) {
sysLogLoginIp = new SysLogLoginIp();
sysLogLoginIp.setIp(clientIp);
sysLogLoginIp.setTryTimes(0);
sysLogLoginIp.setLastLoginTimes(new Date());
}
// 用户是否存在校验
SysUser loginUser = sysUserDao.getByLoginId(loginId);
if (loginUser == null) {
// 用户不存在,记录 IP 尝试次数
return handleIpFailure(sysLogLoginIp, maxIpTries, banMins);
}
// 用户状态检查
if (loginUser.getStatus() == 2) return -2; // Locked
if (loginUser.getStatus() == 0) return -3; // Disabled
if (SysCommon.appDebugLog)
LogUtil.info(AuthorizationService.class,
"[checkLoginByLoginIdAndPassword][Local account] Begin check local user, loginId=" + loginId);
// 执行密码校验
int checkPassed = sysUserDao.countSysUserByLoginIdAndPassword(loginId.toUpperCase(), password);
if (checkPassed == 1) {
// 登录成功:重置计数
loginUser.setTryTimes(0);
sysUserDao.save(loginUser);
sysLogLoginIp.setTryTimes(0);
sysLogLoginIp.setLastLoginTimes(new Date());
sysLogLoginIpService.save(sysLogLoginIp);
if (SysCommon.appDebugLog)
LogUtil.info(AuthorizationService.class,
"[checkLoginByLoginIdAndPassword][Local account] End check local user, result=" + checkPassed);
return 1;
} else {
// 登录失败:更新计数
int currentIpTries = (sysLogLoginIp.getTryTimes() == null ? 0 : sysLogLoginIp.getTryTimes()) + 1;
int currentUserTries = (loginUser.getTryTimes() == null ? 0 : loginUser.getTryTimes()) + 1;
sysLogLoginIp.setTryTimes(currentIpTries);
sysLogLoginIp.setLastLoginTimes(new Date());
loginUser.setTryTimes(currentUserTries);
int finalResult = -1; // 默认返回密码错误
// 检查是否触发 IP 封禁
if (currentIpTries >= maxIpTries) {
applyBan(sysLogLoginIp, banMins);
finalResult = -4;
}
// 检查是否触发 用户 锁定
if (currentUserTries >= maxPwdTries) {
loginUser.setStatus(2);
loginUser.setTryTimes(0);
finalResult = -2;
}
String failMessge = "";
if (finalResult == -1) {
failMessge = "incorrect password, ";
} else if (finalResult == -4) {
failMessge = "ip has been banned, ";
} else if (finalResult == -2) {
failMessge = "user has been banned, ";
}
sysLogLoginIpService.save(sysLogLoginIp);
sysUserDao.save(loginUser);
LogUtil.warn(AuthorizationService.class,
"[checkLoginByLoginIdAndPassword][Local account] End check local user, " + failMessge + "loginId=" + loginId + ", result=" + finalResult);
return finalResult;
}
}
/**
* 封装的私有方法:处理 IP 失败逻辑
*/
private int handleIpFailure(SysLogLoginIp ipLog, int maxTries, int banMins) {
int tries = (ipLog.getTryTimes() == null ? 0 : ipLog.getTryTimes()) + 1;
ipLog.setTryTimes(tries);
ipLog.setLastLoginTimes(new Date());
if (tries >= maxTries) {
applyBan(ipLog, banMins);
sysLogLoginIpService.save(ipLog);
return -4;
}
sysLogLoginIpService.save(ipLog);
return -1;
}
/**
* 封装的私有方法:执行封禁
*/
private void applyBan(SysLogLoginIp ipLog, int banMins) {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.MINUTE, banMins);
ipLog.setBanUntil(cal.getTime());
ipLog.setTryTimes(0); // 重置以便解封后计数
}
}
@@ -0,0 +1,246 @@
package com.mgm.mcrm.authorization.services;
import java.util.ArrayList;
import java.util.List;
import com.mgm.mcrm.authorization.models.SysGroupPermission;
import com.mgm.mcrm.authorization.models.SysUserView;
import com.mgm.mcrm.common.constants.SysConstants;
import com.mgm.mcrm.common.dtos.BaseApiResponse;
import com.mgm.mcrm.common.services.MGMApiService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.JSONObject;
import com.mgm.mcrm.common.constants.SysCommon;
import com.mgm.mcrm.basesetting.property.repositories.BlockDao;
import com.mgm.mcrm.basesetting.team.repositories.DepartmentDao;
import com.mgm.mcrm.basesetting.team.repositories.DivisionDao;
import com.mgm.mcrm.basesetting.property.repositories.PropertyDao;
import com.mgm.mcrm.basesetting.team.repositories.SectionDao;
import com.mgm.mcrm.basesetting.team.repositories.TeamStructureDao;
import com.mgm.mcrm.authorization.repositories.SysGroupPermissionDao;
import com.mgm.mcrm.authorization.repositories.SysUserViewDao;
import com.mgm.mcrm.basesetting.property.models.CfgBlocks;
import com.mgm.mcrm.basesetting.team.models.CfgDepartments;
import com.mgm.mcrm.basesetting.team.models.CfgDivisions;
import com.mgm.mcrm.basesetting.property.models.CfgProperties;
import com.mgm.mcrm.basesetting.team.models.CfgSections;
import com.mgm.mcrm.basesetting.team.models.CfgTeamStructure;
import com.mgm.mcrm.common.dtos.mgm_api.CheckApproverResult;
import com.mgm.mcrm.common.dtos.mgm_api.UserInfoApiRecord;
import com.mgm.mcrm.common.dtos.mgm_api.UserInfoApiResult;
import com.mgm.mcrm.common.dtos.http_util.HttpResponseResult;
@Service
public class MgmUserService {
@Resource
private MGMApiService mgmApiService;
@Resource
private PropertyDao propertyDao;
@Resource
private BlockDao blockDao;
@Resource
private DivisionDao divisionDao;
@Resource
private DepartmentDao departmentDao;
@Resource
private SectionDao sectionDao;
@Resource
private TeamStructureDao teamStructureDao;
@Resource
private SysUserViewDao sysUserViewDao;
@Resource
private SysGroupPermissionDao sysGroupPermissionDao;
public BaseApiResponse<UserInfoApiRecord> findUserInfoByUserId(String userId) {
BaseApiResponse<UserInfoApiRecord> result = new BaseApiResponse<>();
try {
HttpResponseResult httpResult = mgmApiService.invokeGetUserInfo(userId,"");
if(httpResult.getStatusCode()==200) {
try {
UserInfoApiResult resultObj = JSONObject.parseObject(httpResult.getResponseContent(),UserInfoApiResult.class,Feature.SupportNonPublicField,Feature.IgnoreNotMatch);
if(resultObj!=null && resultObj.getStatusCode()!=null) {
String resultCode = resultObj.getStatusCode();
if("OK".equals(resultCode)) {
List<UserInfoApiRecord> recrods = resultObj.getRecords();
if(!recrods.isEmpty()) {
UserInfoApiRecord user = recrods.getFirst();
if(!"NULL".equals(user.getUserId())) {
this.supplementInfoId(userId,user);
user.setStatusCode(resultObj.getStatusCode());
user.setStatusDescription(resultObj.getStatusDescription());
result.setSuccess(true);
result.setData(user);
}else {
result.setSuccess(false);
result.setMessage("User not found");
}
}else {
result.setSuccess(false);
result.setMessage("User not found");
}
}else {
result.setSuccess(false);
result.setMessage("UserInfo API return error:["+resultCode+"] "+resultObj.getStatusDescription());
}
}else {
result.setSuccess(false);
result.setMessage("Invalid return data");
}
}catch(Exception err) {
result.setSuccess(false);
result.setMessage("Parse return data failed:"+err.getMessage());
}
}else {
result.setSuccess(false);
result.setMessage("Invoke get user info failed:["+httpResult.getStatusCode()+"] "+httpResult.getErrorMessage());
}
}catch(Exception err) {
result.setSuccess(false);
result.setMessage("Invoke get user info API error:"+err.getMessage());
}
return result;
}
public BaseApiResponse<List<UserInfoApiRecord>> findUserInfoByUserName(String userName) {
BaseApiResponse<List<UserInfoApiRecord>> result = new BaseApiResponse<>();
String userId = SysCommon.mgmApiMockup?"80001":"";
try {
HttpResponseResult httpResult = mgmApiService.invokeGetUserInfo(userId,userName);
if(httpResult.getStatusCode()==200) {
try {
UserInfoApiResult resultObj = JSONObject.parseObject(httpResult.getResponseContent(),UserInfoApiResult.class,Feature.SupportNonPublicField,Feature.IgnoreNotMatch);
if(resultObj!=null && resultObj.getStatusCode()!=null) {
String resultCode = resultObj.getStatusCode();
if("OK".equals(resultCode)) {
List<UserInfoApiRecord> records = resultObj.getRecords();
List<UserInfoApiRecord> getRecords = new ArrayList<UserInfoApiRecord>();
for(UserInfoApiRecord rec : records) {
if(!"NULL".equals(rec.getUserId())) {
this.supplementInfoId(rec.getUserId(),rec);
getRecords.add(rec);
}
}
result.setSuccess(true);
result.setData(getRecords);
}else {
result.setSuccess(false);
result.setMessage("UserInfo API return error:["+resultCode+"] "+resultObj.getStatusDescription());
}
}else {
result.setSuccess(false);
result.setMessage("Invalid return data");
}
}catch(Exception err) {
result.setSuccess(false);
result.setMessage("Parse return data failed:"+err.getMessage());
}
}else {
result.setSuccess(false);
result.setMessage("Invoke get user info failed:["+httpResult.getStatusCode()+"] "+httpResult.getErrorMessage());
}
}catch(Exception err) {
result.setSuccess(false);
result.setMessage("Invoke get user info API error:"+err.getMessage());
}
return result;
}
public BaseApiResponse<CheckApproverResult> checkApprover(String userId,String userName,String roomType,String property) {
BaseApiResponse<CheckApproverResult> result = new BaseApiResponse<>();
try {
HttpResponseResult httpResult = mgmApiService.invokeCheckApprover(userId,userName,roomType,property);
if(httpResult.getStatusCode()==200) {
try {
CheckApproverResult resultObj = JSONObject.parseObject(httpResult.getResponseContent(),CheckApproverResult.class,Feature.SupportNonPublicField,Feature.IgnoreNotMatch);
if(resultObj!=null && resultObj.getStatusCode()!=null) {
String resultCode = resultObj.getStatusCode();
if("OK".equals(resultCode)) {
if(!"NULL".equals(resultObj.getUserId())) {
result.setSuccess(true);
result.setData(resultObj);
}else {
result.setSuccess(false);
result.setMessage("Approver not found");
}
}else {
result.setSuccess(false);
result.setMessage("CheckApprover API return error:["+resultCode+"] "+resultObj.getStatusDescription());
}
}else {
result.setSuccess(false);
result.setMessage("Invalid return data");
}
}catch(Exception err) {
result.setSuccess(false);
result.setMessage("Parse return data failed:"+err.getMessage());
}
}else {
result.setSuccess(false);
result.setMessage("Invoke get approver failed:["+httpResult.getStatusCode()+"] "+httpResult.getErrorMessage());
}
}catch(Exception err) {
result.setSuccess(false);
result.setMessage("Invoke get approver API error:"+err.getMessage());
}
return result;
}
private UserInfoApiRecord supplementInfoId(String userId,UserInfoApiRecord info) {
// 待完善,有可能需要一层一层获得property,division,department,team
CfgProperties property = propertyDao.getByName(info.getProperty());
if(property!=null) {
info.setPropertyId(property.getId());
}
CfgBlocks block = blockDao.getByName(info.getBlock());
if(block!=null) {
info.setBlockId(block.getId());
}
CfgDivisions division = divisionDao.getByName(info.getDivision());
if(division!=null) {
info.setDivisionId(division.getId());
}
CfgDepartments department = departmentDao.getByName(info.getDepartment());
if(department!=null) {
info.setDepartmentId(department.getId());
}
CfgSections section = sectionDao.getByName(info.getSection());
if(section!=null) {
info.setSectionId(section.getId());
}
CfgTeamStructure team = teamStructureDao.getByDivisionIdAndDepartmentIdAndSectionId(info.getDivisionId(),info.getDepartmentId(),info.getSectionId());
if(team!=null) {
info.setTeamStructureId(team.getId());
}
SysUserView userGroup = sysUserViewDao.getByLoginId(userId);
if(userGroup!=null) {
if(userGroup.getGroupId()!=null) {
info.setGroupName(userGroup.getGroupName());
List<SysGroupPermission> permission = sysGroupPermissionDao.getAllByGroupId(userGroup.getGroupId());
if(!permission.isEmpty()) {
for(SysGroupPermission per:permission) {
if(SysConstants.PERMISSION_APP_VIEW_BOOKING.equals(per.getPermissionId())) info.setCanViewBooking(true);
if(SysConstants.PERMISSION_APP_NEW_BOOKING.equals(per.getPermissionId())) info.setCanNewBooking(true);
if(SysConstants.PERMISSION_APP_TODO_LIST.equals(per.getPermissionId())) info.setCanViewTodoList(true);
if(SysConstants.PERMISSION_APP_DASHBOARD.equals(per.getPermissionId())) info.setCanViewDashboard(true);
if(SysConstants.PERMISSION_APP_APPROVAL.equals(per.getPermissionId())) info.setCanViewApproval(true);
}
}
}
}
return info;
}
}
@@ -0,0 +1,90 @@
package com.mgm.mcrm.authorization.services;
import com.google.gson.Gson;
import com.mgm.mcrm.authorization.models.SysGroupPermission;
import com.mgm.mcrm.authorization.models.SysRouterPermission;
import com.mgm.mcrm.authorization.repositories.SysGroupDataPermissionDao;
import com.mgm.mcrm.authorization.repositories.SysGroupPermissionDao;
import com.mgm.mcrm.authorization.repositories.SysRouterPermissionDao;
import com.mgm.mcrm.booking.services.BookingService;
import com.mgm.mcrm.common.utils.LogUtil;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Strings;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class SysGroupPermissionService {
@Resource
private SysGroupPermissionDao sysGroupPermissionDao;
@Resource
private SysRouterPermissionDao routerPermissionDao;
@Resource
private SysGroupDataPermissionDao sysGroupDataDao;
public List<SysGroupPermission> getGroupPermissionsByGroupId(long groupId){
return sysGroupPermissionDao.getAllByGroupId(groupId);
}
public List<Long> getGroupAccessRoomIds(String routerId, String groupName) {
Gson gson = new Gson();
List<Long> propertyIds = new ArrayList<>();
String[] names = groupName.split(";");
List<String> groupNameList = new ArrayList<>();
for(String nameVal:names) {
groupNameList.add(nameVal.trim().toUpperCase());
}
LogUtil.info(BookingService.class,
"[getGroupAccessRoomIds] groupNameList " + gson.toJson(groupNameList));
if(!groupNameList.isEmpty()) {
List<String> dataIds =sysGroupDataDao.queryAccessDataByGroupNameAndType(groupNameList, routerId, "ROOM");
if(dataIds!=null) {
for(String dataId:dataIds) {
try {
Long idVal = Long.parseLong(dataId);
propertyIds.add(idVal);
}catch(Exception ignored) {
}
}
}
}
if(propertyIds.isEmpty()) {
propertyIds.add(-1L);
}
return propertyIds;
}
public List<SysRouterPermission> getRouterPermissionsByGroupName(String groupName) {
List<SysRouterPermission> groupPermissions = new ArrayList<>();
if(StringUtils.isNotBlank(groupName)) {
List<String> groupNameList = new ArrayList<>();
String[] names = groupName.split(";");
for(String nameVal:names) {
groupNameList.add(nameVal.trim().toUpperCase());
}
if(!groupNameList.isEmpty()) {
groupPermissions = getRouterPermissionsByGroupNameList(groupNameList);
}
}
return groupPermissions;
}
public boolean checkGroupPermission(String groupName,String routerPermissionsId) {
List<SysRouterPermission> userPermissions = this.getRouterPermissionsByGroupName(groupName);
if(!userPermissions.isEmpty()) {
for(SysRouterPermission per:userPermissions) {
if(Strings.CS.equals(per.getId(), routerPermissionsId) ) return true;
}
}
return false;
}
private List<SysRouterPermission> getRouterPermissionsByGroupNameList(List<String> groupNameList) {
return routerPermissionDao.queryPermssionByGroupNameList(groupNameList);
}
}
@@ -0,0 +1,89 @@
package com.mgm.mcrm.authorization.services;
import com.auth0.jwt.JWT;
import com.mgm.mcrm.authorization.models.Token;
import com.mgm.mcrm.authorization.repositories.TokenDao;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
@Service
@RequiredArgsConstructor
public class UserTokenService {
private final TokenDao tokenDao;
@Transactional
public Token saveToken(Token token){
if(token!=null){
if(token.getCreatedAt()==null){
token.setCreatedAt(LocalDateTime.now());
}
tokenDao.save(token);
}
return token;
}
public Token getToken(String token) {
Token result=null;
try {
String uuid = JWT.decode(token).getId();
if (StringUtils.isNotBlank(uuid)) {
result = tokenDao.findByUuid(uuid);
}
}catch(Exception ignored){
}
return result;
}
@Transactional
public Token updateTokenByUniqueId(String tokenUuid, int tokenType, Token newToken) {
if(StringUtils.isBlank(tokenUuid) || newToken==null){
return saveToken(newToken);
}
Token dbToken = tokenDao.findByUuidAndTokenType(tokenUuid, tokenType);
if(dbToken==null){
return saveToken(newToken);
}
Token newDbToken = new Token();
newDbToken.setUuid(newToken.getUuid());
newDbToken.setToken(newToken.getToken());
newDbToken.setTokenType(newToken.getTokenType());
newDbToken.setExpireTime(newToken.getExpireTime());
newDbToken.setCreatedAt(LocalDateTime.now());
newDbToken.setUpdatedBy(newToken.getCreatedBy());
newDbToken.setUpdatedBy(newToken.getCreatedBy());
newDbToken.setUpdatedAt(LocalDateTime.now());
newDbToken.setTokenType(tokenType);
return tokenDao.save(newDbToken);
}
public int deleteToken(String token) {
try{
if (StringUtils.isBlank(token)) return 0;
String uuid = JWT.decode(token).getId();
return tokenDao.deleteByUuidAndTokenType(uuid, 1);
} catch (Exception e) {
return 0;
}
}
public int clearTokenByUser(String userId, int tokenType){
if(StringUtils.isNotBlank(userId)){
return tokenDao.deleteByUserIdAndTokenType(userId,tokenType);
}
return 0;
}
public void removeTokenByUniqueId(String tokenUuid,int tokenType) {
if(StringUtils.isNotBlank(tokenUuid)){
tokenDao.deleteByUuidAndTokenType(tokenUuid, tokenType);
}
}
}
@@ -0,0 +1,142 @@
package com.mgm.mcrm.authorization.utils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.mgm.mcrm.authorization.dtos.LoginUserInfo;
import com.mgm.mcrm.authorization.models.Token;
import com.mgm.mcrm.authorization.services.MgmUserService;
import com.mgm.mcrm.common.constants.SysCommon;
import com.mgm.mcrm.common.utils.LogUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.UUID;
public class JwtTokenUtil {
@Setter
@Getter
private static String secretKey;
@Setter
@Getter
private static int accessTokenExpiration=5;
@Setter
@Getter
private static int appSessionExpiration=30;
@Setter
@Getter
private static int cmsSessionExpiration=30;
private static JWTVerifier verifier=null;
public static JWTVerifier getJwtVerifier(){
if(verifier==null){
verifier = JWT.require(Algorithm.HMAC256(secretKey)).build();
}
return verifier;
}
public static Token generateTokenByLoginUser(String issueSource, LoginUserInfo user, int tokenType, boolean isRefreshToken) {
int tokeExpiration = isRefreshToken?
(tokenType==1?appSessionExpiration:cmsSessionExpiration)
:accessTokenExpiration;
Instant now = Instant.now();
Instant expDate = now.plus(Duration.ofMinutes(tokeExpiration));
String uuid = UUID.randomUUID().toString().replace("-","");
String tokenString = JWT.create()
.withIssuer(issueSource)
.withIssuedAt(now).withNotBefore(now).withExpiresAt(expDate).withJWTId(uuid)
.withClaim("login_id", user.getLoginId())
.withClaim("group_name", user.getGroupName())
.withClaim("last_post_time", now)
.withSubject(String.valueOf(user.getLoginId()))
.sign(Algorithm.HMAC256(secretKey));
Token token = new Token();
token.setUuid(uuid);
token.setTokenType(tokenType);
token.setToken(tokenString);
token.setExpireTime(LocalDateTime.ofInstant(expDate, ZoneId.systemDefault()));
token.setCreatedBy(user.getLoginId());
token.setCreatedAt(LocalDateTime.now());
return token;
}
public static LoginUserInfo parseUserFromRequest(HttpServletRequest request) {
LoginUserInfo loginUser = null;
String token = request.getHeader("Authorization");
if(StringUtils.isNotBlank(token)) {
try {
if(StringUtils.isNotBlank(token) && token.startsWith("Bearer ")){
token = token.substring(7);
}
loginUser = parseUserFromToken(token);
}catch(Exception err) {
LogUtil.error(SysCommon.class, "Parse Token failed:"+err.getMessage());
}
}
return loginUser;
}
public static LoginUserInfo parseUserFromToken(String tokenContent) {
LoginUserInfo loginUser = null;
if(StringUtils.isNotBlank(tokenContent)) {
try {
DecodedJWT decodeData = JWT.decode(tokenContent);
loginUser = new LoginUserInfo();
String userId = decodeData.getSubject();
if(StringUtils.isNotBlank(userId)) {
loginUser.setId(Long.valueOf(userId));
}else {
loginUser.setId(-1L);
}
loginUser.setLoginId(decodeData.getClaim("login_id").asString());
loginUser.setGroupName(decodeData.getClaim("user_group").asString());
loginUser.setTokenUuid(decodeData.getId());
}catch(Exception err) {
LogUtil.error(SysCommon.class, "Parse Token failed:"+err.getMessage());
loginUser =null;
}
}
return loginUser;
}
public static boolean checkToken(String token,String clientId) {
if(token!=null) {
// 验证 token
JWTVerifier jwtVerifier = getJwtVerifier();
try {
jwtVerifier.verify(token);
}
catch (SignatureVerificationException e) {
LogUtil.error(MgmUserService.class, "[checkToken] SignatureVerificationException \nException Message:" + e.getMessage());
return false;
}
catch (JWTVerificationException e) {
LogUtil.error(MgmUserService.class, "[checkToken] JWTVerificationException \nException Message:" + e.getMessage());
return false;
}
catch (Exception e) {
LogUtil.error(MgmUserService.class, "[checkToken] Exception \nException Message:" + e.getMessage());
return false;
}
return true;
}
return false;
}
}
@@ -0,0 +1,30 @@
package com.mgm.mcrm.basesetting.agebucket.models;
import java.io.Serializable;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Data;
@Data
@Entity
@Table(name="sys_agebucket")
public class SysAgebucket implements Serializable {
//fields in table
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name="code")
private String code;
@Column(name="dl_agebucket_id")
private String dlAgeBucketId;
@Column(name = "dl_property_id")
private String dlPropertyId;
}

Some files were not shown because too many files have changed in this diff Show More