feat: initialize loyalty-mcp-server module with foundational DTOs, criteria, enums, and MCP tool infrastructure
This commit is contained in:
21
.codegraph/.gitignore
vendored
21
.codegraph/.gitignore
vendored
@@ -1,16 +1,5 @@
|
|||||||
# CodeGraph data files
|
# CodeGraph data files — local to each machine, not for committing.
|
||||||
# These are local to each machine and should not be committed
|
# Ignore everything in .codegraph/ except this file itself, so transient
|
||||||
|
# files (the database, daemon.pid, sockets, logs) never show up in git.
|
||||||
# Database
|
*
|
||||||
*.db
|
!.gitignore
|
||||||
*.db-wal
|
|
||||||
*.db-shm
|
|
||||||
|
|
||||||
# Cache
|
|
||||||
cache/
|
|
||||||
|
|
||||||
# Logs
|
|
||||||
*.log
|
|
||||||
|
|
||||||
# Hook markers
|
|
||||||
.dirty
|
|
||||||
|
|||||||
@@ -21,6 +21,11 @@
|
|||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.ai</groupId>
|
<groupId>org.springframework.ai</groupId>
|
||||||
<artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
|
<artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
|
||||||
|
|||||||
@@ -3,7 +3,11 @@ package dev.sonpx.loyalty.mcp;
|
|||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication(excludeName = {
|
||||||
|
"org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration",
|
||||||
|
"org.springframework.boot.hibernate.autoconfigure.HibernateJpaAutoConfiguration",
|
||||||
|
"org.springframework.boot.devtools.autoconfigure.DevToolsDataSourceAutoConfiguration"
|
||||||
|
})
|
||||||
public class McpServerApplication {
|
public class McpServerApplication {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
package dev.sonpx.loyalty.mcp.client.api;
|
package dev.sonpx.loyalty.mcp.client.api;
|
||||||
|
|
||||||
import dev.sonpx.loyalty.mcp.client.model.MemberTier;
|
import dev.sonpx.loyalty.mcp.client.model.MemberTier;
|
||||||
import org.springframework.web.service.annotation.GetExchange;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import org.springframework.web.service.annotation.GetExchange;
|
||||||
|
|
||||||
public interface MemberTierApiClient {
|
public interface MemberTierApiClient {
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
package dev.sonpx.loyalty.mcp.client.api;
|
package dev.sonpx.loyalty.mcp.client.api;
|
||||||
|
|
||||||
import dev.sonpx.loyalty.mcp.client.model.PointPool;
|
import dev.sonpx.loyalty.mcp.client.model.PointPool;
|
||||||
import org.springframework.web.service.annotation.GetExchange;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import org.springframework.web.service.annotation.GetExchange;
|
||||||
|
|
||||||
public interface PointPoolApiClient {
|
public interface PointPoolApiClient {
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package dev.sonpx.loyalty.mcp.client.model;
|
package dev.sonpx.loyalty.mcp.client.model;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
|||||||
@@ -2,10 +2,9 @@ package dev.sonpx.loyalty.mcp.client.model.reward;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonAnySetter;
|
import com.fasterxml.jackson.annotation.JsonAnySetter;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
|||||||
@@ -2,10 +2,9 @@ package dev.sonpx.loyalty.mcp.client.model.reward;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.annotation.JsonValue;
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package dev.sonpx.loyalty.mcp.config;
|
|||||||
import dev.sonpx.loyalty.mcp.client.api.CampaignApiClient;
|
import dev.sonpx.loyalty.mcp.client.api.CampaignApiClient;
|
||||||
import dev.sonpx.loyalty.mcp.client.api.MemberTierApiClient;
|
import dev.sonpx.loyalty.mcp.client.api.MemberTierApiClient;
|
||||||
import dev.sonpx.loyalty.mcp.client.api.PointPoolApiClient;
|
import dev.sonpx.loyalty.mcp.client.api.PointPoolApiClient;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
@@ -28,7 +27,6 @@ public class ApiClientConfig {
|
|||||||
private String coreBaseUrl;
|
private String coreBaseUrl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public RestClient loyaltyRestClient(OAuth2AuthorizedClientManager authorizedClientManager) {
|
public RestClient loyaltyRestClient(OAuth2AuthorizedClientManager authorizedClientManager) {
|
||||||
return RestClient.builder()
|
return RestClient.builder()
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package dev.sonpx.loyalty.mcp.config;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by SonPhung on Sunday, 19-Jul-2026
|
||||||
|
**/
|
||||||
|
@Configuration
|
||||||
|
public class AppConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ObjectMapper objectMapper() {
|
||||||
|
return new ObjectMapper();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,11 +4,10 @@ import jakarta.servlet.FilterChain;
|
|||||||
import jakarta.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class AsyncTimeoutFilter extends OncePerRequestFilter {
|
public class AsyncTimeoutFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package dev.sonpx.loyalty.mcp.config;
|
||||||
|
|
||||||
|
import static org.springframework.security.oauth2.client.web.client.RequestAttributeClientRegistrationIdResolver.clientRegistrationId;
|
||||||
|
import static org.springframework.security.oauth2.client.web.client.RequestAttributePrincipalResolver.principal;
|
||||||
|
|
||||||
|
import dev.sonpx.loyalty.mcp.reward.client.RewardClient;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
|
||||||
|
import org.springframework.security.oauth2.client.web.client.OAuth2ClientHttpRequestInterceptor;
|
||||||
|
import org.springframework.security.oauth2.client.web.client.RequestAttributeClientRegistrationIdResolver;
|
||||||
|
import org.springframework.security.oauth2.client.web.client.RequestAttributePrincipalResolver;
|
||||||
|
import org.springframework.web.client.RestClient;
|
||||||
|
import org.springframework.web.client.support.RestClientAdapter;
|
||||||
|
import org.springframework.web.service.invoker.HttpServiceProxyFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by SonPhung on Sunday, 19-Jul-2026
|
||||||
|
**/
|
||||||
|
@Configuration
|
||||||
|
public class ClientConfig {
|
||||||
|
|
||||||
|
@Value("${loyalty.core.base-url}")
|
||||||
|
private String coreBaseUrl;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RestClient rewardReClient(OAuth2AuthorizedClientManager authorizedClientManager) {
|
||||||
|
OAuth2ClientHttpRequestInterceptor oauth2Interceptor =
|
||||||
|
new OAuth2ClientHttpRequestInterceptor(authorizedClientManager);
|
||||||
|
oauth2Interceptor.setClientRegistrationIdResolver(new RequestAttributeClientRegistrationIdResolver());
|
||||||
|
oauth2Interceptor.setPrincipalResolver(new RequestAttributePrincipalResolver());
|
||||||
|
|
||||||
|
return RestClient.builder()
|
||||||
|
.baseUrl(coreBaseUrl + "/svc/reward")
|
||||||
|
.requestInterceptor((request, body, execution) -> {
|
||||||
|
clientRegistrationId("keycloak").accept(request.getAttributes());
|
||||||
|
principal("loyalty-service").accept(request.getAttributes());
|
||||||
|
return oauth2Interceptor.intercept(request, body, execution);
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public HttpServiceProxyFactory httpServiceProxyFactory(RestClient rewardReClient) {
|
||||||
|
return HttpServiceProxyFactory.builderFor(RestClientAdapter.create(rewardReClient))
|
||||||
|
.customArgumentResolver(new PageableArgumentResolver())
|
||||||
|
.customArgumentResolver(new PojoArgumentResolver())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RewardClient rewardClient(HttpServiceProxyFactory httpServiceProxyFactory) {
|
||||||
|
return httpServiceProxyFactory.createClient(RewardClient.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,6 @@ package dev.sonpx.loyalty.mcp.config;
|
|||||||
import dev.sonpx.loyalty.mcp.client.api.CampaignApiClient;
|
import dev.sonpx.loyalty.mcp.client.api.CampaignApiClient;
|
||||||
import dev.sonpx.loyalty.mcp.client.api.MemberTierApiClient;
|
import dev.sonpx.loyalty.mcp.client.api.MemberTierApiClient;
|
||||||
import dev.sonpx.loyalty.mcp.client.api.PointPoolApiClient;
|
import dev.sonpx.loyalty.mcp.client.api.PointPoolApiClient;
|
||||||
|
|
||||||
import dev.sonpx.loyalty.mcp.tool.LoyaltyAgentTools;
|
import dev.sonpx.loyalty.mcp.tool.LoyaltyAgentTools;
|
||||||
import dev.sonpx.loyalty.mcp.tool.reward.CampaignRuleTools;
|
import dev.sonpx.loyalty.mcp.tool.reward.CampaignRuleTools;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package dev.sonpx.loyalty.mcp.config;
|
||||||
|
|
||||||
|
import org.springframework.core.MethodParameter;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.data.domain.Sort;
|
||||||
|
import org.springframework.web.service.invoker.HttpRequestValues;
|
||||||
|
import org.springframework.web.service.invoker.HttpServiceArgumentResolver;
|
||||||
|
|
||||||
|
public class PageableArgumentResolver implements HttpServiceArgumentResolver {
|
||||||
|
@Override
|
||||||
|
public boolean resolve(Object argument, MethodParameter parameter, HttpRequestValues.Builder requestValues) {
|
||||||
|
if (!Pageable.class.isAssignableFrom(parameter.getParameterType())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argument instanceof Pageable pageable) {
|
||||||
|
if (pageable.isPaged()) {
|
||||||
|
requestValues.addRequestParameter("page", String.valueOf(pageable.getPageNumber()));
|
||||||
|
requestValues.addRequestParameter("size", String.valueOf(pageable.getPageSize()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Sort sort = pageable.getSort();
|
||||||
|
if (sort.isSorted()) {
|
||||||
|
for (Sort.Order order : sort) {
|
||||||
|
requestValues.addRequestParameter("sort", order.getProperty() + "," + order.getDirection().name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package dev.sonpx.loyalty.mcp.config;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.springframework.core.MethodParameter;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.service.invoker.HttpRequestValues;
|
||||||
|
import org.springframework.web.service.invoker.HttpServiceArgumentResolver;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class PojoArgumentResolver implements HttpServiceArgumentResolver {
|
||||||
|
private final ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
public PojoArgumentResolver() {
|
||||||
|
this.objectMapper = new ObjectMapper();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean resolve(Object argument, MethodParameter parameter, HttpRequestValues.Builder requestValues) {
|
||||||
|
// Skip if parameter is annotated with typical HTTP interface annotations
|
||||||
|
if (parameter.hasParameterAnnotation(RequestParam.class) ||
|
||||||
|
parameter.hasParameterAnnotation(RequestBody.class) ||
|
||||||
|
parameter.hasParameterAnnotation(PathVariable.class)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip basic types and Pageable
|
||||||
|
if (parameter.getParameterType().isPrimitive() ||
|
||||||
|
parameter.getParameterType().getName().startsWith("java.lang") ||
|
||||||
|
Pageable.class.isAssignableFrom(parameter.getParameterType())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argument == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> map = objectMapper.convertValue(argument, new TypeReference<>() {});
|
||||||
|
flattenMap("", map, requestValues);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void flattenMap(String prefix, Map<String, Object> map, HttpRequestValues.Builder requestValues) {
|
||||||
|
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
||||||
|
String key = prefix.isEmpty() ? entry.getKey() : prefix + "." + entry.getKey();
|
||||||
|
Object value = entry.getValue();
|
||||||
|
if (value instanceof Map) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String, Object> nestedMap = (Map<String, Object>) value;
|
||||||
|
flattenMap(key, nestedMap, requestValues);
|
||||||
|
} else if (value instanceof Iterable<?> iterable) {
|
||||||
|
for (Object item : iterable) {
|
||||||
|
if (item != null) {
|
||||||
|
requestValues.addRequestParameter(key, String.valueOf(item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (value != null) {
|
||||||
|
requestValues.addRequestParameter(key, String.valueOf(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,11 +4,7 @@ import org.springframework.context.annotation.Bean;
|
|||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.oauth2.client.AuthorizedClientServiceOAuth2AuthorizedClientManager;
|
import org.springframework.security.oauth2.client.*;
|
||||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
|
|
||||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider;
|
|
||||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProviderBuilder;
|
|
||||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
|
|
||||||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
|
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.criteria;
|
||||||
|
|
||||||
|
|
||||||
|
import dev.sonpx.loyalty.mcp.filter.RangeFilter;
|
||||||
|
import dev.sonpx.loyalty.mcp.filter.StringFilter;
|
||||||
|
import java.net.URLDecoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.time.Instant;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author AnhDT Created on 2025/05/23
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public abstract class AbstractFwCriteria implements FwCriteria {
|
||||||
|
|
||||||
|
protected StringFilter status;
|
||||||
|
protected RangeFilter<Instant> lastUpdateDate;
|
||||||
|
|
||||||
|
// for search text
|
||||||
|
protected String search;
|
||||||
|
protected String searchComponent;
|
||||||
|
|
||||||
|
//Handle URL-encoded search text (e.g. "%20", "%23") received from UI
|
||||||
|
//e.g: search=tìm%20kiếm -> tìm kiếm
|
||||||
|
public void setSearch(String search) {
|
||||||
|
try {
|
||||||
|
this.search = search == null ? null : URLDecoder.decode(search, StandardCharsets.UTF_8);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
this.search = search;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract String[] getColumns();
|
||||||
|
|
||||||
|
protected abstract String[] getComponentColumns();
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.criteria;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by SonPhung on Tuesday, 10-Oct-2023
|
||||||
|
*/
|
||||||
|
@JsonIgnoreProperties(value = {"columns", "columnsComponent"})
|
||||||
|
public interface FwCriteria {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,13 +1,12 @@
|
|||||||
package dev.sonpx.loyalty.mcp.draft;
|
package dev.sonpx.loyalty.mcp.draft;
|
||||||
|
|
||||||
import dev.sonpx.loyalty.mcp.draft.model.DraftSession;
|
import dev.sonpx.loyalty.mcp.draft.model.DraftSession;
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class DraftSessionManager {
|
public class DraftSessionManager {
|
||||||
|
|||||||
@@ -2,10 +2,9 @@ package dev.sonpx.loyalty.mcp.draft.model;
|
|||||||
|
|
||||||
import dev.sonpx.loyalty.mcp.client.model.reward.CampaignDto;
|
import dev.sonpx.loyalty.mcp.client.model.reward.CampaignDto;
|
||||||
import dev.sonpx.loyalty.mcp.client.model.reward.CampaignRuleDto;
|
import dev.sonpx.loyalty.mcp.client.model.reward.CampaignRuleDto;
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class CampaignDraft {
|
public class CampaignDraft {
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
package dev.sonpx.loyalty.mcp.draft.model;
|
package dev.sonpx.loyalty.mcp.draft.model;
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class DraftSession {
|
public class DraftSession {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package dev.sonpx.loyalty.mcp.draft.model;
|
package dev.sonpx.loyalty.mcp.draft.model;
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class PoolDraft {
|
public class PoolDraft {
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum AttributeDataType {
|
||||||
|
STRING("STRING"),
|
||||||
|
NUMBER("NUMBER"),
|
||||||
|
DATE("DATE"),
|
||||||
|
BOOLEAN("BOOLEAN"),
|
||||||
|
TIME("TIME");
|
||||||
|
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
public static AttributeDataType fromCode(String code) {
|
||||||
|
return Arrays.stream(AttributeDataType.values())
|
||||||
|
.filter(o -> code.equals(o.getCode()))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Phudao
|
||||||
|
* Created on 2024/01/12
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum AttributeEntityType {
|
||||||
|
CLIENT("CLIENT"),
|
||||||
|
PRODUCT_ACCOUNT("PRODUCT_ACCOUNT"),
|
||||||
|
CARD("CARD"),
|
||||||
|
CORPORATION("CORPORATION"),
|
||||||
|
CHAIN("CHAIN"),
|
||||||
|
STORE("STORE"),
|
||||||
|
// TRANSACTIONS("TRANSACTIONS"),
|
||||||
|
CAMPAIGN("CAMPAIGN"),
|
||||||
|
ITEM("ITEM");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static AttributeEntityType fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(e -> e.code.equalsIgnoreCase(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum AttributeType {
|
||||||
|
CUSTOM("CUSTOM"),
|
||||||
|
DYNAMIC("DYNAMIC"),
|
||||||
|
STATIC("STATIC");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static AttributeType fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(e -> e.code.equalsIgnoreCase(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package dev.sonpx.loyalty.mcp.enums;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public final class CodeEnumLookup {
|
||||||
|
|
||||||
|
private CodeEnumLookup() {}
|
||||||
|
|
||||||
|
public static <T extends Enum> T resolve(String source, Class<T> targetType) {
|
||||||
|
if (source == null || source.isBlank()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String normalized = source.trim();
|
||||||
|
for (T constant : targetType.getEnumConstants()) {
|
||||||
|
if (constant.name().equalsIgnoreCase(normalized)
|
||||||
|
|| codeOf(constant).map(code -> code.equalsIgnoreCase(normalized)).orElse(false)) {
|
||||||
|
return constant;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalArgumentException("Unsupported " + targetType.getSimpleName() + " value: " + source);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String codeOfEnum(Enum<?> constant) {
|
||||||
|
return codeOf(constant).orElseGet(constant::name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Optional<String> codeOf(Object constant) {
|
||||||
|
if (constant instanceof EnumBase enumBase) {
|
||||||
|
return Optional.ofNullable(enumBase.getCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Method getCode = constant.getClass().getMethod("getCode");
|
||||||
|
Object code = getCode.invoke(constant);
|
||||||
|
return code instanceof String value ? Optional.of(value) : Optional.empty();
|
||||||
|
} catch (ReflectiveOperationException ex) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum CounterBucket {
|
||||||
|
CURRENT_BUCKET("CB"),
|
||||||
|
PREVIOUS_BUCKET("PB"),
|
||||||
|
PERIOD_BEFORE_LAST("PBL");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static CounterBucket fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(e -> e.code.equalsIgnoreCase(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum CounterEntity {
|
||||||
|
CUSTOMER("CU"),
|
||||||
|
ACCOUNT("AC"),
|
||||||
|
CARD("CA"),
|
||||||
|
MERCHANT("ME"),
|
||||||
|
SYSTEM("SY");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static CounterEntity fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(e -> e.code.equalsIgnoreCase(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by SonPhung on Wednesday, 20-Dec-2023
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum CounterPeriod {
|
||||||
|
AOD_ANNIVERSARY("AA"),
|
||||||
|
DAY_COUNTER("DC"),
|
||||||
|
DAYS_FROM_AOD("DFA"),
|
||||||
|
DAYS_FROM_COD("DFC"),
|
||||||
|
FIXED_DATE("FD"),
|
||||||
|
HALF_YEAR("HY"),
|
||||||
|
MONTHS_FROM_AOD("MFA"),
|
||||||
|
MONTHS_COUNTER("MC"),
|
||||||
|
NON_EXPIRE("NE"),
|
||||||
|
QUARTER_COUNTER("QC"),
|
||||||
|
QUARTER_FROM_AOD("QFA"),
|
||||||
|
WEEK_COUNTER("WC"),
|
||||||
|
YEAR_COUNTER("YC"),
|
||||||
|
STATEMENT_CYCLE("SC");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static CounterPeriod fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(e -> e.code.equalsIgnoreCase(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author AnhDT Created on 2025/11/17
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum DerivedType {
|
||||||
|
STRING("STRING", AttributeDataType.STRING),
|
||||||
|
INT("INT", AttributeDataType.NUMBER),
|
||||||
|
DECIMAL("DECIMAL", AttributeDataType.NUMBER),
|
||||||
|
DATE("DATE", AttributeDataType.DATE),
|
||||||
|
TIME("TIME", AttributeDataType.TIME),
|
||||||
|
BOOLEAN("BOOLEAN", AttributeDataType.BOOLEAN),
|
||||||
|
SEGMENT("SEGMENT", null),
|
||||||
|
AUDIENCE("AUDIENCE", null);
|
||||||
|
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
private final AttributeDataType baseType;
|
||||||
|
|
||||||
|
public static DerivedType fromCode(String code) {
|
||||||
|
return Arrays.stream(DerivedType.values())
|
||||||
|
.filter(o -> code.equals(o.getCode()))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DerivedType fromBaseType(AttributeDataType baseType) {
|
||||||
|
return Arrays.stream(DerivedType.values())
|
||||||
|
.filter(o -> baseType.equals(o.getBaseType()))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isAudienceType(String code) {
|
||||||
|
return DerivedType.AUDIENCE.code.equalsIgnoreCase(code) || DerivedType.SEGMENT.code.equalsIgnoreCase(code);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by SonPhung on Wednesday, 20-Dec-2023
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum EntityLevel {
|
||||||
|
CUSTOMER("CU"),
|
||||||
|
ACCOUNT("AC"),
|
||||||
|
CARD("CA"),
|
||||||
|
LOYALTY_ACCOUNT("LA");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static EntityLevel fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(e -> e.code.equalsIgnoreCase(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums;
|
||||||
|
|
||||||
|
public interface EnumBase {
|
||||||
|
String getCode();
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum ExpiryPolicy {
|
||||||
|
FIXED_DATE("FD"),
|
||||||
|
NO_EXPIRY("NE"),
|
||||||
|
ANNUAL_RECURRING_DATE("ARD"),
|
||||||
|
N_MONTHS_FROM_MONTH_OF_EARNING("MF"),
|
||||||
|
N_QUARTERS_FROM_QUARTER_OF_EARNING("QF"),
|
||||||
|
N_YEARS_FROM_YEAR_OF_EARNING("YF"),
|
||||||
|
SEMI_ANNUAL_OR_MID_AND_END_YEAR("SP"),
|
||||||
|
ANNIVERSARY_OF_MEMBERSHIP("AOM");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static ExpiryPolicy fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(e -> e.code.equalsIgnoreCase(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum FileStoreType {
|
||||||
|
S3("s3"), // For S3 or S3-compatible storage
|
||||||
|
FILE("file"); // For local file system storage
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static FileStoreType fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(e -> e.code.equalsIgnoreCase(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by SonPhung on Tuesday, 08-Apr-2025
|
||||||
|
*/
|
||||||
|
public interface IErrorCode {
|
||||||
|
String getCode();
|
||||||
|
|
||||||
|
String name();
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by SonPhung on Monday, 27-Nov-2023
|
||||||
|
*/
|
||||||
|
public enum IdentifierType {
|
||||||
|
MOBILE,
|
||||||
|
CARD,
|
||||||
|
EMAIL,
|
||||||
|
CIF,
|
||||||
|
PAID,
|
||||||
|
PSN,
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public enum ImageSourceType {
|
||||||
|
UPLOAD("UPLOAD"),
|
||||||
|
|
||||||
|
URL("URL");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static ImageSourceType fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(e -> e.code.equalsIgnoreCase(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.LocalTime;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Optional;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public enum JobParamDataType {
|
||||||
|
STRING(String.class),
|
||||||
|
LONG(Long.class),
|
||||||
|
INTEGER(Integer.class),
|
||||||
|
DOUBLE(Double.class),
|
||||||
|
FLOAT(Float.class),
|
||||||
|
DATE(Date.class),
|
||||||
|
LOCAL_DATE(LocalDate.class), // yyyy-MM-dd
|
||||||
|
LOCAL_TIME(LocalTime.class),
|
||||||
|
LOCAL_DATE_TIME(LocalDateTime.class); // yyyy-MM-dd'T'HH:mm:ss
|
||||||
|
|
||||||
|
private final Class<?> type;
|
||||||
|
|
||||||
|
JobParamDataType(Class<?> type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean supports(Object value) {
|
||||||
|
return type.isInstance(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Optional<JobParamDataType> resolveType(Object value) {
|
||||||
|
if (value == null) return Optional.empty();
|
||||||
|
return Arrays.stream(values()).filter(t -> t.supports(value)).findFirst();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums;
|
||||||
|
|
||||||
|
public interface MetaEntityType {
|
||||||
|
String getCode();
|
||||||
|
|
||||||
|
String getServiceId();
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author AnhDT
|
||||||
|
* Created on 2024/06/26
|
||||||
|
*/
|
||||||
|
public enum PeriodAction {
|
||||||
|
CURRENT,
|
||||||
|
LAST,
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author AnhDT
|
||||||
|
* Created on 2024/06/26
|
||||||
|
*/
|
||||||
|
public enum PeriodType {
|
||||||
|
YEAR,
|
||||||
|
QUARTER,
|
||||||
|
MONTH,
|
||||||
|
WEEK,
|
||||||
|
DAY,
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum RecordStatus implements EnumBase {
|
||||||
|
|
||||||
|
/** Record is active and eligible for processing. DB code: {@code "A"}. */
|
||||||
|
ACTIVE("A"),
|
||||||
|
|
||||||
|
/** Record is logically inactive but retained. DB code: {@code "I"}. */
|
||||||
|
INACTIVE("I"),
|
||||||
|
|
||||||
|
/** Record is marked for deletion. DB code: {@code "D"}. */
|
||||||
|
DELETE("D");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static RecordStatus fromCode(String code) {
|
||||||
|
if (code == null) return null;
|
||||||
|
for (RecordStatus s : values()) {
|
||||||
|
if (s.code.equalsIgnoreCase(code)) return s;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author AnhDT
|
||||||
|
* Created on 2024/06/26
|
||||||
|
* {@link #LAST_7_DAYS},
|
||||||
|
* {@link #LAST_30_DAYS},
|
||||||
|
* {@link #LAST_3_MONTHS},
|
||||||
|
* {@link #LAST_6_MONTHS}
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum StatisticPeriod {
|
||||||
|
TODAY("TODAY"),
|
||||||
|
LAST_7_DAYS("L7D"),
|
||||||
|
LAST_30_DAYS("L30D"),
|
||||||
|
LAST_3_MONTHS("L3M"),
|
||||||
|
LAST_6_MONTHS("L6M");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static StatisticPeriod fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(e -> e.code.equalsIgnoreCase(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAny(StatisticPeriod... periods) {
|
||||||
|
return List.of(periods).contains(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums.schedule;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import dev.sonpx.loyalty.mcp.enums.EnumBase;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum DayOfMonth implements EnumBase {
|
||||||
|
DAY01("1"),
|
||||||
|
DAY02("2"),
|
||||||
|
DAY03("3"),
|
||||||
|
DAY04("4"),
|
||||||
|
DAY05("5"),
|
||||||
|
DAY06("6"),
|
||||||
|
DAY07("7"),
|
||||||
|
DAY08("8"),
|
||||||
|
DAY09("9"),
|
||||||
|
DAY10("10"),
|
||||||
|
DAY11("11"),
|
||||||
|
DAY12("12"),
|
||||||
|
DAY13("13"),
|
||||||
|
DAY14("14"),
|
||||||
|
DAY15("15"),
|
||||||
|
DAY16("16"),
|
||||||
|
DAY17("17"),
|
||||||
|
DAY18("18"),
|
||||||
|
DAY19("19"),
|
||||||
|
DAY20("20"),
|
||||||
|
DAY21("21"),
|
||||||
|
DAY22("22"),
|
||||||
|
DAY23("23"),
|
||||||
|
DAY24("24"),
|
||||||
|
DAY25("25"),
|
||||||
|
DAY26("26"),
|
||||||
|
DAY27("27"),
|
||||||
|
DAY28("28"),
|
||||||
|
DAY29("29"),
|
||||||
|
DAY30("30"),
|
||||||
|
DAY31("31");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static DayOfMonth fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(day -> day.getCode().equals(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums.schedule;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import dev.sonpx.loyalty.mcp.enums.EnumBase;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum DayOfWeek implements EnumBase {
|
||||||
|
MONDAY("1"),
|
||||||
|
TUESDAY("2"),
|
||||||
|
WEDNESDAY("3"),
|
||||||
|
THURSDAY("4"),
|
||||||
|
FRIDAY("5"),
|
||||||
|
SATURDAY("6"),
|
||||||
|
SUNDAY("7");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static DayOfWeek fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(day -> day.getCode().equals(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums.schedule;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import dev.sonpx.loyalty.mcp.enums.EnumBase;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum MonthOfYear implements EnumBase {
|
||||||
|
JANUARY("1"),
|
||||||
|
FEBRUARY("2"),
|
||||||
|
MARCH("3"),
|
||||||
|
APRIL("4"),
|
||||||
|
MAY("5"),
|
||||||
|
JUNE("6"),
|
||||||
|
JULY("7"),
|
||||||
|
AUGUST("8"),
|
||||||
|
SEPTEMBER("9"),
|
||||||
|
OCTOBER("10"),
|
||||||
|
NOVEMBER("11"),
|
||||||
|
DECEMBER("12");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static MonthOfYear fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(month -> month.getCode().equals(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums.schedule;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import dev.sonpx.loyalty.mcp.enums.EnumBase;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum PeriodicType implements EnumBase {
|
||||||
|
DAY("D"),
|
||||||
|
WEEK("W"),
|
||||||
|
MONTH("M"),
|
||||||
|
YEAR("Y");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static PeriodicType fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(periodicType -> periodicType.getCode().equals(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums.schedule;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import dev.sonpx.loyalty.mcp.enums.EnumBase;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum ScheduleMonthType implements EnumBase {
|
||||||
|
DAY_OF_MONTH("DOM"),
|
||||||
|
DAY_OF_WEEK("DOW");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static ScheduleMonthType fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(monthType -> monthType.getCode().equals(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums.schedule;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import dev.sonpx.loyalty.mcp.enums.EnumBase;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum ScheduleRecurrenceType implements EnumBase {
|
||||||
|
ONE_TIME("O"),
|
||||||
|
RECURRING("R");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static ScheduleRecurrenceType fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(scheduleType -> scheduleType.getCode().equals(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums.schedule;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import dev.sonpx.loyalty.mcp.enums.EnumBase;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum TriggerMethod implements EnumBase {
|
||||||
|
SCHEDULE("S"),
|
||||||
|
EVENT("E");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static TriggerMethod fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(triggerMethod -> triggerMethod.getCode().equals(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.enums.schedule;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import dev.sonpx.loyalty.mcp.enums.EnumBase;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum WeekOfMonth implements EnumBase {
|
||||||
|
FIRST("1"),
|
||||||
|
SECOND("2"),
|
||||||
|
THIRD("3"),
|
||||||
|
FOURTH("4"),
|
||||||
|
FIFTH("5"),
|
||||||
|
LAST("L");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static WeekOfMonth fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(week -> week.getCode().equals(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.filter;
|
||||||
|
|
||||||
|
public class BooleanFilter extends Filter<Boolean> {}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.filter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author AnhDT Created on 2025/12/11
|
||||||
|
*/
|
||||||
|
public class DoubleFilter extends RangeFilter<Double> {}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.filter;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle for filtering with basic operators (equals, notEquals, specified, in, notIn)
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@EqualsAndHashCode
|
||||||
|
public class Filter<T> implements Serializable {
|
||||||
|
|
||||||
|
private T equals;
|
||||||
|
private T notEquals;
|
||||||
|
private Boolean specified;
|
||||||
|
private List<T> in;
|
||||||
|
private List<T> notIn;
|
||||||
|
|
||||||
|
public Filter(Filter<T> filter) {
|
||||||
|
this.equals = filter.equals;
|
||||||
|
this.notEquals = filter.notEquals;
|
||||||
|
this.specified = filter.specified;
|
||||||
|
this.in = filter.in == null ? null : new ArrayList<>(filter.in);
|
||||||
|
this.notIn = filter.notIn == null ? null : new ArrayList<>(filter.notIn);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Filter<T> setEquals(T equals) {
|
||||||
|
this.equals = equals;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Filter<T> setNotEquals(T notEquals) {
|
||||||
|
this.notEquals = notEquals;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Filter<T> setSpecified(Boolean specified) {
|
||||||
|
this.specified = specified;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Filter<T> setIn(List<T> in) {
|
||||||
|
this.in = in;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Filter<T> setNotIn(List<T> notIn) {
|
||||||
|
this.notIn = notIn;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.filter;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author AnhDT Created on 2025/12/11
|
||||||
|
*/
|
||||||
|
public class InstantFilter extends RangeFilter<Instant> {}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.filter;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle for filtering String type with contains, doesNotContain
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class ListContainsFilter extends Filter<String> {
|
||||||
|
|
||||||
|
private String containsList;
|
||||||
|
|
||||||
|
private String doesNotContainList;
|
||||||
|
|
||||||
|
public ListContainsFilter setContainsList(String contains) {
|
||||||
|
this.containsList = contains;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListContainsFilter setDoesNotContainList(String doesNotContain) {
|
||||||
|
this.doesNotContainList = doesNotContain;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.filter;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author AnhDT Created on 2025/12/11
|
||||||
|
*/
|
||||||
|
public class LocalDateFilter extends RangeFilter<LocalDate> {}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.filter;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author AnhDT Created on 2025/12/11
|
||||||
|
*/
|
||||||
|
public class LocalDateTimeFilter extends RangeFilter<LocalDateTime> {}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.filter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author AnhDT Created on 2025/12/11
|
||||||
|
*/
|
||||||
|
public class LongFilter extends RangeFilter<Long> {}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.filter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by SonPhung on Monday, 09-Oct-2023
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
public class OlsFilterSpec {
|
||||||
|
|
||||||
|
private Filter<?> filter;
|
||||||
|
private String column;
|
||||||
|
private String param;
|
||||||
|
private List<String> columns;
|
||||||
|
|
||||||
|
public boolean searchFilter() {
|
||||||
|
return !CollectionUtils.isEmpty(columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static OlsFilterSpec of(Filter<?> filter, String column, String param) {
|
||||||
|
return OlsFilterSpec.builder()
|
||||||
|
.filter(filter)
|
||||||
|
.column(column)
|
||||||
|
.param(param)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static OlsFilterSpec of(Filter<?> filter, String param, String... columns) {
|
||||||
|
return OlsFilterSpec.builder()
|
||||||
|
.filter(filter)
|
||||||
|
.columns(Arrays.stream(columns).toList())
|
||||||
|
.param(param)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.filter;
|
||||||
|
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle for filtering comparable types with range options
|
||||||
|
* Include types: Integer, Long, Float, Double, BigDecimal, Instant, LocalDate
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class RangeFilter<T extends Comparable<? super T>> extends Filter<T> {
|
||||||
|
|
||||||
|
private T greaterThan;
|
||||||
|
private T lessThan;
|
||||||
|
private T greaterThanOrEqual;
|
||||||
|
private T lessThanOrEqual;
|
||||||
|
|
||||||
|
public RangeFilter(RangeFilter<T> filter) {
|
||||||
|
super(filter);
|
||||||
|
this.greaterThan = filter.greaterThan;
|
||||||
|
this.lessThan = filter.lessThan;
|
||||||
|
this.greaterThanOrEqual = filter.greaterThanOrEqual;
|
||||||
|
this.lessThanOrEqual = filter.lessThanOrEqual;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RangeFilter<T> setGreaterThan(T greaterThan) {
|
||||||
|
this.greaterThan = greaterThan;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RangeFilter<T> setLessThan(T lessThan) {
|
||||||
|
this.lessThan = lessThan;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RangeFilter<T> setGreaterThanOrEqual(T greaterThanOrEqual) {
|
||||||
|
this.greaterThanOrEqual = greaterThanOrEqual;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RangeFilter<T> setLessThanOrEqual(T lessThanOrEqual) {
|
||||||
|
this.lessThanOrEqual = lessThanOrEqual;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.filter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String filter alias for ReferenceData request params such as field.code.equals.
|
||||||
|
*/
|
||||||
|
public class ReferenceDataStringFilter extends StringFilter {
|
||||||
|
|
||||||
|
public StringFilter getCode() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.filter;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle for filtering String type with contains, doesNotContain
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class StringFilter extends Filter<String> {
|
||||||
|
|
||||||
|
private String contains;
|
||||||
|
|
||||||
|
private String doesNotContain;
|
||||||
|
|
||||||
|
public StringFilter setContains(String contains) {
|
||||||
|
this.contains = contains;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringFilter setDoesNotContain(String doesNotContain) {
|
||||||
|
this.doesNotContain = doesNotContain;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.model;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by tuanngo on Wed, 10/01/2024
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class AttributeData extends ReferenceData {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private String attributeType;
|
||||||
|
|
||||||
|
private String dataType;
|
||||||
|
|
||||||
|
private String semanticType;
|
||||||
|
|
||||||
|
private boolean attributeValuePredefined;
|
||||||
|
|
||||||
|
private boolean notFound;
|
||||||
|
|
||||||
|
public AttributeData(String code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by tuanngo on Wed, 2025-09-10
|
||||||
|
*/
|
||||||
|
public record ProcessResult(String code, String message, String targetId) {
|
||||||
|
public static ProcessResult of(String code, String message) {
|
||||||
|
return new ProcessResult(code, message, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ProcessResult of(String code, String message, String targetId) {
|
||||||
|
return new ProcessResult(code, message, targetId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by tuanngo on Tue, 2025-04-16
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class ReferenceData implements Serializable {
|
||||||
|
|
||||||
|
protected String code;
|
||||||
|
protected String description;
|
||||||
|
protected boolean notFound;
|
||||||
|
protected String recordStatus;
|
||||||
|
protected Map<String, Object> attributes = new HashMap<>();
|
||||||
|
|
||||||
|
public ReferenceData(String code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReferenceData(String code, String description) {
|
||||||
|
this.code = code;
|
||||||
|
this.description = description;
|
||||||
|
this.notFound = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReferenceData(String code, String description, Boolean notFound) {
|
||||||
|
this.code = code;
|
||||||
|
this.description = description;
|
||||||
|
this.notFound = notFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReferenceData(String code, String description, boolean notFound, String recordStatus) {
|
||||||
|
this.code = code;
|
||||||
|
this.description = description;
|
||||||
|
this.notFound = notFound;
|
||||||
|
this.recordStatus = recordStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReferenceData(String code, String description, Map<String, Object> attributes) {
|
||||||
|
this.code = code;
|
||||||
|
this.description = description;
|
||||||
|
this.attributes = attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAttribute(String key, Object value) {
|
||||||
|
this.attributes.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
ReferenceData that = (ReferenceData) o;
|
||||||
|
return Objects.equals(code, that.code) && Objects.equals(description, that.description);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(code, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ReferenceData{" + "code='" + code + '\'' + ", notFound=" + notFound + '}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.model.valueobject;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.ToString;
|
||||||
|
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||||
|
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract generic class for value objects.
|
||||||
|
* Provides automatic generation of getter, equals, hashCode, and toString methods
|
||||||
|
* for the 'value' field using Lombok annotations.
|
||||||
|
*
|
||||||
|
* @param <T> the type of the value this class holds
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
public abstract class BaseValue<T> {
|
||||||
|
|
||||||
|
protected T value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new BaseValue object with the specified value.
|
||||||
|
* @param value the value to set
|
||||||
|
*/
|
||||||
|
public BaseValue(T value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNull() {
|
||||||
|
return value == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNotNull() {
|
||||||
|
return value != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
|
||||||
|
if (!(o instanceof BaseValue<?> baseValue)) return false;
|
||||||
|
|
||||||
|
return new EqualsBuilder().append(getValue(), baseValue.getValue()).isEquals();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return new HashCodeBuilder(17, 37).append(getValue()).toHashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.model.valueobject;
|
||||||
|
|
||||||
|
public class BooleanValue extends BaseValue<Boolean> {
|
||||||
|
|
||||||
|
public static final BooleanValue FALSE = new BooleanValue(false);
|
||||||
|
|
||||||
|
BooleanValue(Boolean value) {
|
||||||
|
super(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEqualTo(BooleanValue compareValue) {
|
||||||
|
return this.value.equals(compareValue.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BooleanValue of(Object value) {
|
||||||
|
BooleanValue falseValue = BooleanValue.FALSE;
|
||||||
|
if (value instanceof Boolean bool) {
|
||||||
|
return new BooleanValue(bool);
|
||||||
|
} else if (value instanceof String string) {
|
||||||
|
try {
|
||||||
|
return BooleanValue.of(Boolean.valueOf(string));
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return falseValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,307 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.model.valueobject;
|
||||||
|
|
||||||
|
import java.time.DayOfWeek;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Map;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Getter
|
||||||
|
public class DateTimeValue extends BaseValue<LocalDateTime> {
|
||||||
|
|
||||||
|
private int quarter = 0;
|
||||||
|
|
||||||
|
public static final DateTimeValue NULL = new DateTimeValue(null);
|
||||||
|
|
||||||
|
public static final DateTimeValue NOW = new DateTimeValue(LocalDateTime.now());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mapping of weekday abbreviations to DayOfWeek enums, used by onWeekdays().
|
||||||
|
* Example: "Mon" -> DayOfWeek.MONDAY
|
||||||
|
*/
|
||||||
|
public static final Map<String, DayOfWeek> DAY_OF_WEEK = Map.ofEntries(
|
||||||
|
Map.entry("Mon", DayOfWeek.MONDAY),
|
||||||
|
Map.entry("Tue", DayOfWeek.TUESDAY),
|
||||||
|
Map.entry("Wed", DayOfWeek.WEDNESDAY),
|
||||||
|
Map.entry("Thu", DayOfWeek.THURSDAY),
|
||||||
|
Map.entry("Fri", DayOfWeek.FRIDAY),
|
||||||
|
Map.entry("Sat", DayOfWeek.SATURDAY),
|
||||||
|
Map.entry("Sun", DayOfWeek.SUNDAY));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum representing units of time for plus() and minus() operations.
|
||||||
|
*/
|
||||||
|
public enum TimeUnit {
|
||||||
|
DAY,
|
||||||
|
WEEK,
|
||||||
|
MONTH,
|
||||||
|
QUARTER,
|
||||||
|
YEAR,
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum TimeOffset {
|
||||||
|
AGO,
|
||||||
|
AWAY,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private constructor to enforce use of factory method of().
|
||||||
|
* @param value the LocalDateTime to wrap
|
||||||
|
*/
|
||||||
|
private DateTimeValue(LocalDateTime value) {
|
||||||
|
super(value);
|
||||||
|
setQuarter();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a DateTimeValue from various input types.
|
||||||
|
* - LocalDateTime: Converts to start of day
|
||||||
|
* - LocalDate: Converts to start of day LocalDateTime
|
||||||
|
* - String: Parses ISO ("yyyy-MM-dd") or "dd/MM/yyyy" formats
|
||||||
|
* - Null or invalid: Returns NULL_VALUE
|
||||||
|
*
|
||||||
|
* @param value the input to convert
|
||||||
|
* @return a new DateTimeValue instance
|
||||||
|
*/
|
||||||
|
public static DateTimeValue of(Object value) {
|
||||||
|
return switch (value) {
|
||||||
|
case LocalDateTime dateTime -> toStartOfDay(dateTime);
|
||||||
|
case LocalDate localDate -> new DateTimeValue(localDate.atStartOfDay());
|
||||||
|
case String datetimePattern -> parseString(datetimePattern);
|
||||||
|
case null, default -> NULL;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DateTimeValue parseString(String datetimePattern) {
|
||||||
|
if (StringUtils.isBlank(datetimePattern)) {
|
||||||
|
return DateTimeValue.NULL;
|
||||||
|
}
|
||||||
|
LocalDateTime localDateTime = LocalDate.parse(datetimePattern).atStartOfDay();
|
||||||
|
return new DateTimeValue(localDateTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DateTimeValue toStartOfDay(LocalDateTime localDateTime) {
|
||||||
|
return new DateTimeValue(localDateTime.toLocalDate().atStartOfDay());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this date falls on any of the specified weekdays.
|
||||||
|
* Example: onWeekdays("Mon", "Fri") returns true if date is a Monday or Friday.
|
||||||
|
*
|
||||||
|
* @param days weekday abbreviations (e.g., "Mon", "Tue")
|
||||||
|
* @return true if the date matches any specified weekday, false if null or no match
|
||||||
|
*/
|
||||||
|
public boolean onWeekdays(String... days) {
|
||||||
|
if (isNull()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Arrays.stream(days)
|
||||||
|
.map(DAY_OF_WEEK::get)
|
||||||
|
.anyMatch(dayOfWeek -> dayOfWeek != null && dayOfWeek.equals(value.getDayOfWeek()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a specified quantity of time to this DateTimeValue.
|
||||||
|
* Example: plus(3, TimeUnit. MONTH) adds 3 months.
|
||||||
|
*
|
||||||
|
* @param quantity the amount to add (positive or negative)
|
||||||
|
* @param unit the time unit to apply
|
||||||
|
* @return a new DateTimeValue with the adjusted time
|
||||||
|
* @throws IllegalStateException if this instance is null
|
||||||
|
*/
|
||||||
|
public DateTimeValue plus(long quantity, TimeUnit unit) {
|
||||||
|
if (isNull()) {
|
||||||
|
throw new IllegalStateException("Cannot modify a null DateTimeValue");
|
||||||
|
}
|
||||||
|
if (quantity == 0) {
|
||||||
|
return this; // No change
|
||||||
|
}
|
||||||
|
return switch (unit) {
|
||||||
|
case DAY -> DateTimeValue.of(value.plusDays(quantity));
|
||||||
|
case MONTH -> DateTimeValue.of(value.plusMonths(quantity));
|
||||||
|
case QUARTER -> DateTimeValue.of(value.plusMonths(quantity * 3));
|
||||||
|
case YEAR -> DateTimeValue.of(value.plusYears(quantity));
|
||||||
|
case WEEK -> DateTimeValue.of(value.plusWeeks(quantity));
|
||||||
|
default -> NULL;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subtracts a specified amount of time from this DateTimeValue.
|
||||||
|
* Example: minus(2, TimeUnit.DAY) subtracts 2 days.
|
||||||
|
*
|
||||||
|
* @param amount the amount to subtract (positive; negative values add time)
|
||||||
|
* @param unit the time unit to apply
|
||||||
|
* @return a new DateTimeValue with the adjusted time
|
||||||
|
* @throws IllegalStateException if this instance is null
|
||||||
|
*/
|
||||||
|
public DateTimeValue minus(long amount, TimeUnit unit) {
|
||||||
|
if (isNull()) {
|
||||||
|
throw new IllegalStateException("Cannot modify a null DateTimeValue");
|
||||||
|
}
|
||||||
|
if (amount == 0) {
|
||||||
|
return this; // No change
|
||||||
|
}
|
||||||
|
return switch (unit) {
|
||||||
|
case DAY -> DateTimeValue.of(value.minusDays(amount));
|
||||||
|
case MONTH -> DateTimeValue.of(value.minusMonths(amount));
|
||||||
|
case QUARTER -> DateTimeValue.of(value.minusMonths(amount * 3));
|
||||||
|
case YEAR -> DateTimeValue.of(value.minusYears(amount));
|
||||||
|
case WEEK -> DateTimeValue.of(value.minusWeeks(amount));
|
||||||
|
default -> NULL;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this DateTimeValue is empty (null).
|
||||||
|
*
|
||||||
|
* @return true if null, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this DateTimeValue is not empty (not null).
|
||||||
|
*
|
||||||
|
* @return true if not null, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean isNotEmpty() {
|
||||||
|
return !isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this DateTimeValue equals another, ignoring time of day.
|
||||||
|
* Example: "2025-03-02" equals "2025-03-02".
|
||||||
|
*
|
||||||
|
* @param compareValue the DateTimeValue to compare with
|
||||||
|
* @return true if equal, false if either is null or not equal
|
||||||
|
*/
|
||||||
|
public boolean isEquals(DateTimeValue compareValue) {
|
||||||
|
if (isNull()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return this.value.isEqual(compareValue.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this DateTimeValue is not equal to another.
|
||||||
|
*
|
||||||
|
* @param compareValue the DateTimeValue to compare with
|
||||||
|
* @return true if not equal, false if either is null or equal
|
||||||
|
*/
|
||||||
|
public boolean isNotEquals(DateTimeValue compareValue) {
|
||||||
|
return !isEquals(compareValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this DateTimeValue is on or after another.
|
||||||
|
* Example: "2025-03-02" isOnOrAfter "2025-03-01" returns true.
|
||||||
|
*
|
||||||
|
* @param compareValue the DateTimeValue to compare with
|
||||||
|
* @return true if on or after, false if either is null or before
|
||||||
|
*/
|
||||||
|
public boolean isOnOrAfter(DateTimeValue compareValue) {
|
||||||
|
return value.isAfter(compareValue.value) || value.isEqual(compareValue.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this DateTimeValue is on or before another.
|
||||||
|
* Example: "2025-03-02" isOnOrBefore "2025-03-03" returns true.
|
||||||
|
*
|
||||||
|
* @param compareValue the DateTimeValue to compare with
|
||||||
|
* @return true if on or before, false if either is null or after
|
||||||
|
*/
|
||||||
|
public boolean isOnOrBefore(DateTimeValue compareValue) {
|
||||||
|
return value.isBefore(compareValue.value) || value.isEqual(compareValue.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this DateTimeValue falls between two others (inclusive).
|
||||||
|
* @param from the start of the range
|
||||||
|
* @param to the end of the range
|
||||||
|
* @return true if within range, false if null or outside range
|
||||||
|
*/
|
||||||
|
public boolean isBetween(DateTimeValue from, DateTimeValue to) {
|
||||||
|
return isOnOrAfter(from) && isOnOrBefore(to);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean quarterAndYearEquals(DateTimeValue compareValue) {
|
||||||
|
if (isNull()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return this.quarter == compareValue.quarter && this.value.getYear() == compareValue.value.getYear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean quarterAndYearNotEquals(DateTimeValue compareValue) {
|
||||||
|
return !quarterAndYearEquals(compareValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setQuarter() {
|
||||||
|
if (!isNull()) {
|
||||||
|
this.quarter = (this.value.getMonthValue() - 1) / 3 + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a date component falls within a specified range.
|
||||||
|
* Example: isInRangeWith(1, 31, TimeUnit.DAY) checks if day is between 1 and 31.
|
||||||
|
*
|
||||||
|
* @param start the start of the range
|
||||||
|
* @param end the end of the range
|
||||||
|
* @param timeUnit the unit to check (DAY, MONTH, YEAR)
|
||||||
|
* @return true if within range, false if null or outside range
|
||||||
|
*/
|
||||||
|
public boolean isInRangeWith(Integer start, Integer end, TimeUnit timeUnit) {
|
||||||
|
return switch (timeUnit) {
|
||||||
|
case DAY -> value.getDayOfMonth() >= start && value.getDayOfMonth() <= end;
|
||||||
|
case MONTH -> value.getMonthValue() >= start && value.getMonthValue() <= end;
|
||||||
|
case YEAR -> value.getYear() >= start && value.getYear() <= end;
|
||||||
|
case QUARTER -> quarter >= start && quarter <= end;
|
||||||
|
default -> false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the difference between this DateTimeValue and another in the specified time unit.
|
||||||
|
* Returns the number of days, months, or years between the two dates, with positive values indicating
|
||||||
|
* this date is after the compared date, and negative values indicating it is before. Only DAY, MONTH,
|
||||||
|
* and YEAR units are supported; other units throw an exception.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* DateTimeValue start = DateTimeValue.of("2025-01-01");
|
||||||
|
* DateTimeValue end = DateTimeValue.of("2025-03-02");
|
||||||
|
* Long days = start.differenceInUnits(end, TimeUnit.DAY); // Returns 60 (Jan 1 to Mar 2)
|
||||||
|
* Long months = start.differenceInUnits(end, TimeUnit.MONTH); // Returns 2 (Jan to Mar)
|
||||||
|
* Long years = end.differenceInUnits(start, TimeUnit.YEAR); // Returns 0 (same year)
|
||||||
|
*
|
||||||
|
* Notes:
|
||||||
|
* - Time components are ignored since DateTimeValue normalizes to start of day.
|
||||||
|
* - Returns null if this instance is null; assumes compareValue is non-null (may throw NPE if not).
|
||||||
|
* - Throws UnsupportedOperationException for WEEK or QUARTER units, as they are not implemented.
|
||||||
|
* - The result is signed: positive if this date is after compareValue, negative if before.
|
||||||
|
*
|
||||||
|
* @param compareValue the DateTimeValue to compare against (non-null expected)
|
||||||
|
* @param unit the time unit to measure the difference in (DAY, MONTH, or YEAR)
|
||||||
|
* @return the difference as a Long (positive or negative), or null if this instance is null
|
||||||
|
* @throws UnsupportedOperationException if unit is not DAY, MONTH, or YEAR
|
||||||
|
* @throws NullPointerException if compareValue or its value is null
|
||||||
|
*/
|
||||||
|
public Long differenceInUnits(DateTimeValue compareValue, TimeUnit unit) {
|
||||||
|
if (isNull()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return switch (unit) {
|
||||||
|
case DAY -> ChronoUnit.DAYS.between(value, compareValue.value);
|
||||||
|
case MONTH -> ChronoUnit.MONTHS.between(value, compareValue.value);
|
||||||
|
case YEAR -> ChronoUnit.YEARS.between(value, compareValue.value);
|
||||||
|
case null, default -> throw new UnsupportedOperationException("Not supported");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,163 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.model.valueobject;
|
||||||
|
|
||||||
|
public class NumberValue extends BaseValue<Double> {
|
||||||
|
|
||||||
|
private static final double EPSILON = 1e-9;
|
||||||
|
public static NumberValue ZERO = new NumberValue(0.0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new NumberValue object with the specified value.
|
||||||
|
*
|
||||||
|
* @param value the value to set
|
||||||
|
*/
|
||||||
|
NumberValue(Double value) {
|
||||||
|
super(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a NumberValue instance from an object.
|
||||||
|
*
|
||||||
|
* @param value an object that could be a Number or String.
|
||||||
|
* @return a NumberValue instance representing the specified value.
|
||||||
|
*/
|
||||||
|
public static NumberValue of(Object value) {
|
||||||
|
if (value instanceof Number number) {
|
||||||
|
return new NumberValue(number.doubleValue());
|
||||||
|
} else if (value instanceof String string) {
|
||||||
|
return new NumberValue(Double.parseDouble(string));
|
||||||
|
}
|
||||||
|
return new NumberValue(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current NumberValue equals another NumberValue.
|
||||||
|
*
|
||||||
|
* @param compareValue the NumberValue to compare with.
|
||||||
|
* @return true if the current NumberValue is equal to compareValue, otherwise false.
|
||||||
|
*/
|
||||||
|
public boolean equals(NumberValue compareValue) {
|
||||||
|
if (this.isNull()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Math.abs(this.value - compareValue.value) < EPSILON;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current NumberValue is not equal to another NumberValue.
|
||||||
|
*
|
||||||
|
* @param compareValue the NumberValue to compare with.
|
||||||
|
* @return true if the current NumberValue is not equal to compareValue, otherwise false.
|
||||||
|
*/
|
||||||
|
public boolean notEquals(NumberValue compareValue) {
|
||||||
|
if (this.isNull()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return !equals(compareValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current NumberValue is less than another NumberValue.
|
||||||
|
*
|
||||||
|
* @param compareValue the NumberValue to compare with.
|
||||||
|
* @return true if the current NumberValue is less than compareValue, otherwise false.
|
||||||
|
*/
|
||||||
|
public boolean lessThan(NumberValue compareValue) {
|
||||||
|
if (this.isNull()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return this.value < compareValue.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current NumberValue is less than or equal to another NumberValue.
|
||||||
|
*
|
||||||
|
* @param compareValue the NumberValue to compare with.
|
||||||
|
* @return true if the current NumberValue is less than or equal to compareValue, otherwise false.
|
||||||
|
*/
|
||||||
|
public boolean lessThanOrEqual(NumberValue compareValue) {
|
||||||
|
if (this.isNull()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return this.value < compareValue.value || equals(compareValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current NumberValue is greater than another NumberValue.
|
||||||
|
*
|
||||||
|
* @param compareValue the NumberValue to compare with.
|
||||||
|
* @return true if the current NumberValue is greater than compareValue, otherwise false.
|
||||||
|
*/
|
||||||
|
public boolean greaterThan(NumberValue compareValue) {
|
||||||
|
if (this.isNull()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return this.value > compareValue.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current NumberValue is greater than or equal to another NumberValue.
|
||||||
|
*
|
||||||
|
* @param compareValue the NumberValue to compare with.
|
||||||
|
* @return true if the current NumberValue is greater than or equal to compareValue, otherwise false.
|
||||||
|
*/
|
||||||
|
public boolean greaterThanOrEqual(NumberValue compareValue) {
|
||||||
|
if (this.isNull()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return this.value > compareValue.value || equals(compareValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current NumberValue is between two other NumberValues.
|
||||||
|
*
|
||||||
|
* @param start the starting NumberValue (inclusive).
|
||||||
|
* @param end the ending NumberValue (inclusive).
|
||||||
|
* @return true if the current NumberValue is between start and end, otherwise false.
|
||||||
|
*/
|
||||||
|
public boolean between(NumberValue start, NumberValue end) {
|
||||||
|
if (this.isNull()) {
|
||||||
|
return false;
|
||||||
|
} else if (start.isNull()) {
|
||||||
|
return lessThanOrEqual(end);
|
||||||
|
} else if (end.isNull()) {
|
||||||
|
return greaterThanOrEqual(start);
|
||||||
|
}
|
||||||
|
return this.greaterThanOrEqual(start) && this.lessThanOrEqual(end);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long toLong() {
|
||||||
|
if (this.isNull()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return this.value.longValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public NumberValue min(NumberValue with) {
|
||||||
|
return new NumberValue(Math.min(this.value, with.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public NumberValue max(NumberValue with) {
|
||||||
|
return new NumberValue(Math.max(this.value, with.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public NumberValue add(NumberValue with) {
|
||||||
|
return new NumberValue(this.value + with.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NumberValue subtract(NumberValue with) {
|
||||||
|
return new NumberValue(this.value - with.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NumberValue multiply(NumberValue with) {
|
||||||
|
return new NumberValue(this.value * with.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NumberValue divide(NumberValue with) {
|
||||||
|
return new NumberValue(this.value / with.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NumberValue percent(Integer value) {
|
||||||
|
return new NumberValue((this.value * value) / 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,250 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.model.valueobject;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.regex.PatternSyntaxException;
|
||||||
|
import lombok.ToString;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.commons.lang3.Strings;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@ToString
|
||||||
|
public class StringValue extends BaseValue<String> {
|
||||||
|
|
||||||
|
public static final StringValue EMPTY = new StringValue("");
|
||||||
|
public static final String PIPE_DELIMITED = "|";
|
||||||
|
|
||||||
|
private StringValue(String value) {
|
||||||
|
super(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a StringValue instance from an object.
|
||||||
|
*
|
||||||
|
* @param value the value to convert (String, EnumBase, or other objects).
|
||||||
|
* @return a StringValue instance or EMPTY if the value is null.
|
||||||
|
*/
|
||||||
|
public static StringValue of(Object value) {
|
||||||
|
if (value == null) {
|
||||||
|
return EMPTY;
|
||||||
|
} else if (value instanceof String string) {
|
||||||
|
return new StringValue(string.toLowerCase().trim());
|
||||||
|
}
|
||||||
|
return EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a glob pattern to a regex pattern.
|
||||||
|
*
|
||||||
|
* @param glob the glob pattern to convert.
|
||||||
|
* @return a regex pattern equivalent to the glob.
|
||||||
|
*/
|
||||||
|
public static String createRegexFromGlob(String glob) {
|
||||||
|
StringBuilder out = new StringBuilder();
|
||||||
|
for (int i = 0; i < glob.length(); ++i) {
|
||||||
|
final char c = glob.charAt(i);
|
||||||
|
switch (c) {
|
||||||
|
case '*':
|
||||||
|
out.append(".*");
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
out.append('.');
|
||||||
|
break;
|
||||||
|
case '.':
|
||||||
|
out.append("\\.");
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
out.append("\\\\");
|
||||||
|
break;
|
||||||
|
case '|':
|
||||||
|
out.append("\\|");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
out.append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "^" + out + "$";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current StringValue equals another StringValue.
|
||||||
|
*
|
||||||
|
* @param valueCompare the StringValue to compare with.
|
||||||
|
* @return true if both values are equal, otherwise false.
|
||||||
|
*/
|
||||||
|
public boolean equals(StringValue valueCompare) {
|
||||||
|
return Strings.CI.equals(this.value, valueCompare.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current StringValue is not equal to another StringValue.
|
||||||
|
*
|
||||||
|
* @param valueCompare the StringValue to compare with.
|
||||||
|
* @return true if both values are not equal, otherwise false.
|
||||||
|
*/
|
||||||
|
public boolean notEquals(StringValue valueCompare) {
|
||||||
|
return !equals(valueCompare);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current StringValue is empty or null.
|
||||||
|
*
|
||||||
|
* @return true if the current StringValue is empty or null, otherwise false.
|
||||||
|
*/
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return StringUtils.isBlank(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current StringValue is not empty.
|
||||||
|
*
|
||||||
|
* @return true if the current StringValue is not empty, otherwise false.
|
||||||
|
*/
|
||||||
|
public boolean isNotEmpty() {
|
||||||
|
return StringUtils.isNotEmpty(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current StringValue contains another StringValue.
|
||||||
|
*
|
||||||
|
* @param valueCompares the StringValue to check.
|
||||||
|
* @return true if the current StringValue contains valueCompare, otherwise false.
|
||||||
|
*/
|
||||||
|
public boolean contains(StringValue... valueCompares) {
|
||||||
|
for (StringValue valueCompare : valueCompares) {
|
||||||
|
if (regularExpression(valueCompare)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current StringValue does not contain another StringValue.
|
||||||
|
*
|
||||||
|
* @param valueCompares the StringValue to check.
|
||||||
|
* @return true if the current StringValue does not contain valueCompare, otherwise false.
|
||||||
|
*/
|
||||||
|
public boolean doesNotContains(StringValue... valueCompares) {
|
||||||
|
return !contains(valueCompares);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current StringValue begins with another StringValue.
|
||||||
|
*
|
||||||
|
* @param valueCompares the StringValue to check.
|
||||||
|
* @return true if the current StringValue begins with valueCompare, otherwise false.
|
||||||
|
*/
|
||||||
|
public boolean beginsWith(StringValue... valueCompares) {
|
||||||
|
for (StringValue valueCompare : valueCompares) {
|
||||||
|
if (Strings.CI.startsWith(this.value, valueCompare.getValue())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current StringValue ends with another StringValue.
|
||||||
|
*
|
||||||
|
* @param filterValues the StringValue to check.
|
||||||
|
* @return true if the current StringValue ends with valueCompare, otherwise false.
|
||||||
|
*/
|
||||||
|
public boolean endsWith(StringValue... filterValues) {
|
||||||
|
for (StringValue valueCompare : filterValues) {
|
||||||
|
boolean isEndWith = Strings.CI.endsWith(this.value, valueCompare.getValue());
|
||||||
|
if (isEndWith) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current StringValue does not begin with another StringValue.
|
||||||
|
*
|
||||||
|
* @param valueCompares the StringValue to check.
|
||||||
|
* @return true if the current StringValue does not begin with valueCompare, otherwise false.
|
||||||
|
*/
|
||||||
|
public boolean doesNotBeginWith(StringValue... valueCompares) {
|
||||||
|
for (StringValue valueCompare : valueCompares) {
|
||||||
|
boolean hasStartsWith = Strings.CI.startsWith(this.value, valueCompare.getValue());
|
||||||
|
if (hasStartsWith) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current StringValue does not end with another StringValue.
|
||||||
|
*
|
||||||
|
* @param filterValues the StringValue to check.
|
||||||
|
* @return true if the current StringValue does not end with valueCompare, otherwise false.
|
||||||
|
*/
|
||||||
|
public boolean doesNotEndsWith(StringValue... filterValues) {
|
||||||
|
for (StringValue valueCompare : filterValues) {
|
||||||
|
if (Strings.CI.endsWith(this.value, valueCompare.getValue())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current StringValue matches a regular expression pattern.
|
||||||
|
*
|
||||||
|
* @param valueCompare the StringValue pattern to match.
|
||||||
|
* @return true if the current StringValue matches valueCompare, otherwise false.
|
||||||
|
*/
|
||||||
|
public boolean regularExpression(StringValue valueCompare) {
|
||||||
|
String regex = createRegexFromGlob(valueCompare.value);
|
||||||
|
try {
|
||||||
|
// Java Escape Characters: Replace newline and tab characters with spaces
|
||||||
|
value = value.replaceAll("[\\n\\t\\r]", " ");
|
||||||
|
return value.matches(regex);
|
||||||
|
} catch (PatternSyntaxException patternSyntaxException) {
|
||||||
|
log.warn("Invalid regular expression: {}", regex);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current StringValue is in a list of StringValues.
|
||||||
|
*
|
||||||
|
* @param filterValues the list of StringValues to check.
|
||||||
|
* @return true if the current StringValue is in valueCompare, otherwise false.
|
||||||
|
*/
|
||||||
|
public boolean in(StringValue... filterValues) {
|
||||||
|
if (filterValues == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
boolean isMatched = false;
|
||||||
|
|
||||||
|
for (StringValue filterValue : filterValues) {
|
||||||
|
if (equals(filterValue)) {
|
||||||
|
isMatched = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return isMatched;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current StringValue is not in a list of StringValues.
|
||||||
|
*
|
||||||
|
* @param valueCompare the list of StringValues to check.
|
||||||
|
* @return true if the current StringValue is not in valueCompare, otherwise false.
|
||||||
|
*/
|
||||||
|
public boolean notIn(StringValue... valueCompare) {
|
||||||
|
return !in(valueCompare);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StringValue[] split(Object object) {
|
||||||
|
if (object instanceof String string) {
|
||||||
|
return Arrays.stream(string.split("\\|")).map(StringValue::of).toArray(StringValue[]::new);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.model.valueobject;
|
||||||
|
|
||||||
|
import java.time.*;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.time.format.DateTimeParseException;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class TimeValue extends BaseValue<LocalTime> {
|
||||||
|
|
||||||
|
public static ZoneId SYSTEM_ZONE = ZoneId.systemDefault();
|
||||||
|
|
||||||
|
private static final TimeValue NULL = new TimeValue(null);
|
||||||
|
private static final int DEFAULT_SECONDS = 0;
|
||||||
|
private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");
|
||||||
|
|
||||||
|
private TimeValue(LocalTime value) {
|
||||||
|
super(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a TimeValue instance from an object.
|
||||||
|
*
|
||||||
|
* @param object an object that could be a LocalTime, LocalDateTime, LocalDate, or String.
|
||||||
|
* @return a TimeValue instance representing the specified value, or an NULL instance if not applicable.
|
||||||
|
*/
|
||||||
|
public static TimeValue of(Object object) {
|
||||||
|
if (object instanceof LocalTime localTime) {
|
||||||
|
return new TimeValue(localTime.withSecond(DEFAULT_SECONDS));
|
||||||
|
} else if (object instanceof LocalDateTime localDateTime) {
|
||||||
|
return new TimeValue(localDateTime.toLocalTime().withSecond(DEFAULT_SECONDS));
|
||||||
|
} else if (object instanceof LocalDate localDate) {
|
||||||
|
return new TimeValue(localDate.atStartOfDay().toLocalTime().withSecond(DEFAULT_SECONDS));
|
||||||
|
} else if (object instanceof String string) {
|
||||||
|
return parseString(string).orElse(NULL);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a time string into an Optional TimeValue using a specific formatter.
|
||||||
|
*
|
||||||
|
* @param string the time string to parse.
|
||||||
|
* @return an Optional containing a TimeValue if parsing is successful, otherwise an empty Optional.
|
||||||
|
*/
|
||||||
|
private static Optional<TimeValue> parseString(String string) {
|
||||||
|
try {
|
||||||
|
LocalTime time = LocalTime.parse(string, TIME_FORMATTER);
|
||||||
|
return Optional.of(new TimeValue(time.withSecond(DEFAULT_SECONDS)));
|
||||||
|
} catch (DateTimeParseException e) {
|
||||||
|
try {
|
||||||
|
ZonedDateTime utcDateTime = ZonedDateTime.parse(string);
|
||||||
|
ZonedDateTime serverDateTime = utcDateTime.withZoneSameInstant(SYSTEM_ZONE);
|
||||||
|
return Optional.of(new TimeValue(serverDateTime.toLocalTime().withSecond(DEFAULT_SECONDS)));
|
||||||
|
} catch (DateTimeParseException ignored) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current TimeValue is on or before another TimeValue.
|
||||||
|
*
|
||||||
|
* @param compareValue the TimeValue to compare with.
|
||||||
|
* @return true if the current TimeValue is on or before compareValue, otherwise false.
|
||||||
|
*/
|
||||||
|
public boolean isOnOrBefore(TimeValue compareValue) {
|
||||||
|
if (isNull()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return this.value.isBefore(compareValue.value) || this.value.equals(compareValue.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current TimeValue is on or after another TimeValue.
|
||||||
|
*
|
||||||
|
* @param compareValue the TimeValue to compare with.
|
||||||
|
* @return true if the current TimeValue is on or after compareValue, otherwise false.
|
||||||
|
*/
|
||||||
|
public boolean isOnOrAfter(TimeValue compareValue) {
|
||||||
|
if (isNull()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return this.value.isAfter(compareValue.value) || this.value.equals(compareValue.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current TimeValue is between two other TimeValues.
|
||||||
|
*
|
||||||
|
* @param start the starting TimeValue (inclusive).
|
||||||
|
* @param end the ending TimeValue (inclusive).
|
||||||
|
* @return true if the current TimeValue is between start and end, otherwise false.
|
||||||
|
*/
|
||||||
|
public boolean isBetween(TimeValue start, TimeValue end) {
|
||||||
|
if (isNull()) {
|
||||||
|
return false;
|
||||||
|
} else if (start.isNull()) {
|
||||||
|
return this.isOnOrBefore(end);
|
||||||
|
} else if (end.isNull()) {
|
||||||
|
return this.isOnOrAfter(start);
|
||||||
|
}
|
||||||
|
return this.isOnOrAfter(start) && this.isOnOrBefore(end);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package dev.sonpx.loyalty.mcp.reward.client;
|
||||||
|
|
||||||
|
import dev.sonpx.loyalty.mcp.reward.criteria.CampaignCriteria;
|
||||||
|
import dev.sonpx.loyalty.mcp.reward.model.CampaignDto;
|
||||||
|
import java.util.List;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.service.annotation.GetExchange;
|
||||||
|
import org.springframework.web.service.annotation.HttpExchange;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by SonPhung on Sunday, 19-Jul-2026
|
||||||
|
**/
|
||||||
|
@HttpExchange
|
||||||
|
public interface RewardClient {
|
||||||
|
|
||||||
|
@GetExchange("/api/campaign/csr/list")
|
||||||
|
ResponseEntity<List<CampaignDto>> getAll(CampaignCriteria criteria, Pageable pageable);
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.reward.criteria;
|
||||||
|
|
||||||
|
|
||||||
|
import dev.sonpx.loyalty.mcp.criteria.AbstractFwCriteria;
|
||||||
|
import dev.sonpx.loyalty.mcp.filter.StringFilter;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author AnhDT
|
||||||
|
* Created on 2023/10/25
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class CampaignCriteria extends AbstractFwCriteria {
|
||||||
|
|
||||||
|
private StringFilter campaignId;
|
||||||
|
private StringFilter ownerName;
|
||||||
|
private StringFilter name;
|
||||||
|
private StringFilter description;
|
||||||
|
private StringFilter campaignType;
|
||||||
|
|
||||||
|
// for search text and component
|
||||||
|
private String[] componentColumns = {"campaign_id", "name"};
|
||||||
|
private String[] columns = {"description"};
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.reward.criteria;
|
||||||
|
|
||||||
|
|
||||||
|
import dev.sonpx.loyalty.mcp.criteria.AbstractFwCriteria;
|
||||||
|
import dev.sonpx.loyalty.mcp.filter.LocalDateTimeFilter;
|
||||||
|
import dev.sonpx.loyalty.mcp.filter.StringFilter;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author AnhDT
|
||||||
|
* Created on 2023/10/31
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class CampaignRuleCriteria extends AbstractFwCriteria {
|
||||||
|
|
||||||
|
private StringFilter campaignId;
|
||||||
|
private StringFilter ruleId;
|
||||||
|
private StringFilter ruleName;
|
||||||
|
private StringFilter description;
|
||||||
|
private LocalDateTimeFilter effectiveFrom;
|
||||||
|
private LocalDateTimeFilter effectiveTo;
|
||||||
|
private StringFilter ruleType;
|
||||||
|
private StringFilter poolId;
|
||||||
|
|
||||||
|
// for search text and component
|
||||||
|
private String[] componentColumns = {"rule_id", "rule_name"};
|
||||||
|
private String[] columns = {"campaign_id", "description"};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.reward.criteria;
|
||||||
|
|
||||||
|
|
||||||
|
import dev.sonpx.loyalty.mcp.criteria.AbstractFwCriteria;
|
||||||
|
import dev.sonpx.loyalty.mcp.filter.StringFilter;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author AnhDT Created on 2025/05/22
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ComponentCriteria extends AbstractFwCriteria {
|
||||||
|
|
||||||
|
private StringFilter key;
|
||||||
|
private StringFilter code;
|
||||||
|
private StringFilter name;
|
||||||
|
|
||||||
|
// for search text
|
||||||
|
private String[] componentColumns = {"code", "name"};
|
||||||
|
private String[] columns = {};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.reward.criteria;
|
||||||
|
|
||||||
|
|
||||||
|
import dev.sonpx.loyalty.mcp.criteria.AbstractFwCriteria;
|
||||||
|
import dev.sonpx.loyalty.mcp.filter.LocalDateFilter;
|
||||||
|
import dev.sonpx.loyalty.mcp.filter.LongFilter;
|
||||||
|
import dev.sonpx.loyalty.mcp.filter.StringFilter;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author AnhDT
|
||||||
|
* Created on 2023/10/31
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class CounterDefinitionCriteria extends AbstractFwCriteria {
|
||||||
|
|
||||||
|
private StringFilter counterId;
|
||||||
|
private StringFilter counterName;
|
||||||
|
private LocalDateFilter effectiveFrom;
|
||||||
|
private LocalDateFilter effectiveTo;
|
||||||
|
private StringFilter entity;
|
||||||
|
private StringFilter bucketPeriodUnit;
|
||||||
|
private LongFilter bucketPeriodDuration;
|
||||||
|
private StringFilter whatToCount;
|
||||||
|
private StringFilter resetType;
|
||||||
|
private LocalDateFilter firstStartDate;
|
||||||
|
private StringFilter stateCounter;
|
||||||
|
private StringFilter lateValuePosting;
|
||||||
|
|
||||||
|
// for search text
|
||||||
|
private String[] componentColumns = {"counter_id", "counter_name"};
|
||||||
|
private String[] columns = {"entity", "what_to_count"};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.reward.criteria;
|
||||||
|
|
||||||
|
|
||||||
|
import dev.sonpx.loyalty.mcp.criteria.AbstractFwCriteria;
|
||||||
|
import dev.sonpx.loyalty.mcp.filter.DoubleFilter;
|
||||||
|
import dev.sonpx.loyalty.mcp.filter.StringFilter;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author AnhDT
|
||||||
|
* Created on 2023/12/12
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class CurrencyRateCriteria extends AbstractFwCriteria {
|
||||||
|
|
||||||
|
private StringFilter pcrCode;
|
||||||
|
private StringFilter effectiveFrom;
|
||||||
|
private StringFilter effectiveTo;
|
||||||
|
private DoubleFilter buyRate;
|
||||||
|
private DoubleFilter sellRate;
|
||||||
|
|
||||||
|
// for search text
|
||||||
|
private String[] componentColumns = {"pcr_code"};
|
||||||
|
private String[] columns = {};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.reward.criteria;
|
||||||
|
|
||||||
|
|
||||||
|
import dev.sonpx.loyalty.mcp.criteria.AbstractFwCriteria;
|
||||||
|
import dev.sonpx.loyalty.mcp.filter.LocalDateFilter;
|
||||||
|
import dev.sonpx.loyalty.mcp.filter.StringFilter;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class DeductionSequencesCriteria extends AbstractFwCriteria {
|
||||||
|
private StringFilter sequenceId;
|
||||||
|
private StringFilter sequenceName;
|
||||||
|
private StringFilter description;
|
||||||
|
private LocalDateFilter effectiveFrom;
|
||||||
|
private LocalDateFilter effectiveTo;
|
||||||
|
private StringFilter isDefault;
|
||||||
|
|
||||||
|
// for search and component
|
||||||
|
private String[] componentColumns = {"sequence_id", "sequence_name"};
|
||||||
|
private String[] columns = {"description", "effective_from", "effective_to", "is_default"};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.reward.criteria;
|
||||||
|
|
||||||
|
|
||||||
|
import dev.sonpx.loyalty.mcp.criteria.AbstractFwCriteria;
|
||||||
|
import dev.sonpx.loyalty.mcp.filter.StringFilter;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author AnhDT
|
||||||
|
* Created on 2023/10/31
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class EventMaintenanceCriteria extends AbstractFwCriteria {
|
||||||
|
|
||||||
|
private StringFilter eventId;
|
||||||
|
private StringFilter description;
|
||||||
|
|
||||||
|
// for search text
|
||||||
|
private String[] componentColumns = {"event_id", "description"};
|
||||||
|
private String[] columns = {};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.reward.criteria;
|
||||||
|
|
||||||
|
|
||||||
|
import dev.sonpx.loyalty.mcp.criteria.AbstractFwCriteria;
|
||||||
|
import dev.sonpx.loyalty.mcp.filter.StringFilter;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author AnhDT
|
||||||
|
* Created on 2023/12/06
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class PoolConversionRateCriteria extends AbstractFwCriteria {
|
||||||
|
|
||||||
|
private StringFilter code;
|
||||||
|
private StringFilter description;
|
||||||
|
|
||||||
|
// for search text
|
||||||
|
private String[] componentColumns = {"code", "description"};
|
||||||
|
private String[] columns = {};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.reward.criteria;
|
||||||
|
|
||||||
|
|
||||||
|
import dev.sonpx.loyalty.mcp.criteria.AbstractFwCriteria;
|
||||||
|
import dev.sonpx.loyalty.mcp.filter.StringFilter;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author AnhDT
|
||||||
|
* Created on 2023/10/25
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class PoolDefinitionCriteria extends AbstractFwCriteria {
|
||||||
|
|
||||||
|
private StringFilter poolId;
|
||||||
|
private StringFilter poolName;
|
||||||
|
private StringFilter poolType;
|
||||||
|
private StringFilter entityLevel;
|
||||||
|
private StringFilter expiryPolicy;
|
||||||
|
private StringFilter atgGroupId;
|
||||||
|
|
||||||
|
// for search and component
|
||||||
|
private String[] componentColumns = {"pool_id", "pool_name"};
|
||||||
|
private String[] columns = {"description"};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.reward.criteria;
|
||||||
|
|
||||||
|
|
||||||
|
import dev.sonpx.loyalty.mcp.criteria.AbstractFwCriteria;
|
||||||
|
import dev.sonpx.loyalty.mcp.filter.StringFilter;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author AnhDT
|
||||||
|
* Created on 2023/10/25
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class StatementOutputPoolCriteria extends AbstractFwCriteria {
|
||||||
|
|
||||||
|
private StringFilter poolId;
|
||||||
|
private StringFilter entityLevel;
|
||||||
|
|
||||||
|
// for search text
|
||||||
|
private String[] componentColumns = {"pool_id"};
|
||||||
|
private String[] columns = {"entity_level"};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.reward.criteria;
|
||||||
|
|
||||||
|
|
||||||
|
import dev.sonpx.loyalty.mcp.criteria.AbstractFwCriteria;
|
||||||
|
import dev.sonpx.loyalty.mcp.filter.StringFilter;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author AnhDT
|
||||||
|
* Created on 2023/10/31
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class TransactionCategoryCriteria extends AbstractFwCriteria {
|
||||||
|
|
||||||
|
private StringFilter code;
|
||||||
|
private StringFilter name;
|
||||||
|
private StringFilter description;
|
||||||
|
|
||||||
|
// for search text and component
|
||||||
|
private String[] componentColumns = {"code", "name"};
|
||||||
|
private String[] columns = {};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.reward.criteria;
|
||||||
|
|
||||||
|
|
||||||
|
import dev.sonpx.loyalty.mcp.criteria.AbstractFwCriteria;
|
||||||
|
import dev.sonpx.loyalty.mcp.filter.BooleanFilter;
|
||||||
|
import dev.sonpx.loyalty.mcp.filter.StringFilter;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author AnhDT
|
||||||
|
* Created on 2023/10/25
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class TransactionCodeCriteria extends AbstractFwCriteria {
|
||||||
|
|
||||||
|
private StringFilter code;
|
||||||
|
private StringFilter description;
|
||||||
|
private BooleanFilter reversalInd;
|
||||||
|
|
||||||
|
// for search text and component
|
||||||
|
private String[] componentColumns = {"code", "description"};
|
||||||
|
private String[] columns = {"reversal_ind"};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.reward.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author AnhDT
|
||||||
|
* Created on 2024/01/08
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum AlertChannel {
|
||||||
|
EMAIL("E");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static AlertChannel fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(e -> e.code.equalsIgnoreCase(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.reward.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author AnhDT
|
||||||
|
* Created on 2024/01/05
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum AmountToUseType {
|
||||||
|
GROSS_AMOUNT("GA"),
|
||||||
|
NETT_AMOUNT("NA");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static AmountToUseType fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(e -> e.code.equalsIgnoreCase(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.reward.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author AnhDT
|
||||||
|
* Created on 2024/03/11
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum AmountToUseViewType {
|
||||||
|
CODE(null, null),
|
||||||
|
ATTRIBUTE("A", "Attribute"),
|
||||||
|
COUNTER("C", "Counter");
|
||||||
|
|
||||||
|
private final String code;
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static AmountToUseViewType fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(e -> e.code.equalsIgnoreCase(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.reward.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by SonPhung on Friday, 10-Nov-2023
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum AwardBasisType {
|
||||||
|
APPLY_EACH_TIER("AAF"),
|
||||||
|
APPLY_HIGHEST_TIER("AHT");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static AwardBasisType fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(e -> e.code.equalsIgnoreCase(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.reward.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by SonPhung on Friday, 10-Nov-2023
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum AwardFactorType {
|
||||||
|
PERCENT("GA"),
|
||||||
|
POOL_UNIT("NA");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static AwardFactorType fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(e -> e.code.equalsIgnoreCase(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.reward.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by SonPhung on Friday, 10-Nov-2023
|
||||||
|
* This sets the cap on the sum of Result from the formulas set up in Rule.
|
||||||
|
* If the Result from Rule exceeds this cap, then this cap is used as the Result.
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum AwardLimitType {
|
||||||
|
NO_MORE_THAN("NM"),
|
||||||
|
AT_LEAST("AL");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static AwardLimitType fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(e -> e.code.equalsIgnoreCase(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.reward.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author AnhDT
|
||||||
|
* Created on 2024/01/05
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum BaseDateType {
|
||||||
|
POST_DATE("PD"),
|
||||||
|
TRANSACTION_DATE("TD");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static BaseDateType fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(e -> e.code.equalsIgnoreCase(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.reward.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author AnhDT
|
||||||
|
* Created on 2024/01/02
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum CampaignType {
|
||||||
|
BASE("B"),
|
||||||
|
TACTICAL("T");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static CampaignType fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(e -> e.code.equalsIgnoreCase(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.reward.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by SonPhung on Friday, 10-Nov-2023
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum CapAwardType {
|
||||||
|
TRACKED_IN_COUNTER("C"),
|
||||||
|
PER_TRANSACTION("T");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static CapAwardType fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(e -> e.code.equalsIgnoreCase(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.reward.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by SonPhung on Wednesday, 20-Dec-2023
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum CounterCountType {
|
||||||
|
GROSS_AMOUNT("GA"),
|
||||||
|
NET_AMOUNT("NA"),
|
||||||
|
POINT("P"),
|
||||||
|
POINT_VALUE("PV"),
|
||||||
|
TRANSACTION_FREQUENCY("TF");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static CounterCountType fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(e -> e.code.equalsIgnoreCase(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.reward.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by SonPhung on Wednesday, 20-Dec-2023
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum CounterResetType {
|
||||||
|
RESET_TO_REMAINDER("R"),
|
||||||
|
RESET_TO_ZERO("Z");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static CounterResetType fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(e -> e.code.equalsIgnoreCase(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.reward.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by SonPhung on Wednesday, 20-Dec-2023
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum CounterUpdateType {
|
||||||
|
ON_AWARD("A"),
|
||||||
|
ON_EXTRACT("E"),
|
||||||
|
NEVER("N");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static CounterUpdateType fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(e -> e.code.equalsIgnoreCase(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.reward.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum DeductionPriorityType {
|
||||||
|
START_DATE("STA"),
|
||||||
|
EXPIRY_DATE("EXP"),
|
||||||
|
CONTRIBUTOR("CON");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static DeductionPriorityType fromCode(String code) {
|
||||||
|
return Arrays.stream(DeductionPriorityType.values())
|
||||||
|
.filter(o -> o.getCode().equals(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.reward.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author AnhDT
|
||||||
|
* Created on 2024/01/09
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum EventFrequencyType {
|
||||||
|
ONCE("O"),
|
||||||
|
MONTHLY("M"),
|
||||||
|
ANNUALLY("A");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static EventFrequencyType fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(e -> e.code.equalsIgnoreCase(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
package dev.sonpx.loyalty.mcp.reward.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
// exc_blocked_card
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum ExtractBlockedCard {
|
||||||
|
INCLUDE("I"),
|
||||||
|
EXCLUDE("E");
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static ExtractBlockedCard fromCode(String code) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(e -> e.code.equalsIgnoreCase(code))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user