feat: initialize loyalty-mcp-server module with foundational DTOs, criteria, enums, and MCP tool infrastructure
This commit is contained in:
@@ -3,7 +3,11 @@ package dev.sonpx.loyalty.mcp;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
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 static void main(String[] args) {
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
package dev.sonpx.loyalty.mcp.client.api;
|
||||
|
||||
import dev.sonpx.loyalty.mcp.client.model.MemberTier;
|
||||
import org.springframework.web.service.annotation.GetExchange;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.web.service.annotation.GetExchange;
|
||||
|
||||
public interface MemberTierApiClient {
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
package dev.sonpx.loyalty.mcp.client.api;
|
||||
|
||||
import dev.sonpx.loyalty.mcp.client.model.PointPool;
|
||||
import org.springframework.web.service.annotation.GetExchange;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.web.service.annotation.GetExchange;
|
||||
|
||||
public interface PointPoolApiClient {
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package dev.sonpx.loyalty.mcp.client.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@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.JsonIgnoreProperties;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@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.JsonValue;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@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.MemberTierApiClient;
|
||||
import dev.sonpx.loyalty.mcp.client.api.PointPoolApiClient;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -28,7 +27,6 @@ public class ApiClientConfig {
|
||||
private String coreBaseUrl;
|
||||
|
||||
|
||||
|
||||
@Bean
|
||||
public RestClient loyaltyRestClient(OAuth2AuthorizedClientManager authorizedClientManager) {
|
||||
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.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@Component
|
||||
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.MemberTierApiClient;
|
||||
import dev.sonpx.loyalty.mcp.client.api.PointPoolApiClient;
|
||||
|
||||
import dev.sonpx.loyalty.mcp.tool.LoyaltyAgentTools;
|
||||
import dev.sonpx.loyalty.mcp.tool.reward.CampaignRuleTools;
|
||||
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.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.oauth2.client.AuthorizedClientServiceOAuth2AuthorizedClientManager;
|
||||
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.*;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
|
||||
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;
|
||||
|
||||
import dev.sonpx.loyalty.mcp.draft.model.DraftSession;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Consumer;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
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.CampaignRuleDto;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class CampaignDraft {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
package dev.sonpx.loyalty.mcp.draft.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.Instant;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class DraftSession {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package dev.sonpx.loyalty.mcp.draft.model;
|
||||
|
||||
import lombok.Data;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
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 ExtractNoCounter {
|
||||
INCLUDE("I"),
|
||||
EXCLUDE("E");
|
||||
|
||||
@JsonValue
|
||||
private final String code;
|
||||
|
||||
@JsonCreator
|
||||
public static ExtractNoCounter 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/08
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum LateValuePosting {
|
||||
UPDATE_LATE_VALUE("L"),
|
||||
UPDATE_CURRENT_BUCKET("C");
|
||||
|
||||
@JsonValue
|
||||
private final String code;
|
||||
|
||||
@JsonCreator
|
||||
public static LateValuePosting 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