diff --git a/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/config/RestClientConfig.java b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/config/RestClientConfig.java index 1d0f781..141ca38 100644 --- a/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/config/RestClientConfig.java +++ b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/config/RestClientConfig.java @@ -88,4 +88,24 @@ public class RestClientConfig { public CampaignRuleClient campaignRuleClient(HttpServiceProxyFactory rewardHttpServiceProxyFactory) { return rewardHttpServiceProxyFactory.createClient(CampaignRuleClient.class); } + + @Bean + public dev.sonpx.loyalty.mcp.reward.client.PoolDefinitionClient poolDefinitionClient(HttpServiceProxyFactory rewardHttpServiceProxyFactory) { + return rewardHttpServiceProxyFactory.createClient(dev.sonpx.loyalty.mcp.reward.client.PoolDefinitionClient.class); + } + + @Bean + public dev.sonpx.loyalty.mcp.reward.client.CounterDefinitionClient counterDefinitionClient(HttpServiceProxyFactory rewardHttpServiceProxyFactory) { + return rewardHttpServiceProxyFactory.createClient(dev.sonpx.loyalty.mcp.reward.client.CounterDefinitionClient.class); + } + + @Bean + public dev.sonpx.loyalty.mcp.reward.client.DeductionSequenceClient deductionSequenceClient(HttpServiceProxyFactory rewardHttpServiceProxyFactory) { + return rewardHttpServiceProxyFactory.createClient(dev.sonpx.loyalty.mcp.reward.client.DeductionSequenceClient.class); + } + + @Bean + public dev.sonpx.loyalty.mcp.reward.client.TransactionCodeClient transactionCodeClient(HttpServiceProxyFactory rewardHttpServiceProxyFactory) { + return rewardHttpServiceProxyFactory.createClient(dev.sonpx.loyalty.mcp.reward.client.TransactionCodeClient.class); + } } diff --git a/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/reward/client/CampaignRuleClient.java b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/reward/client/CampaignRuleClient.java index e9709b0..0a0cc68 100644 --- a/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/reward/client/CampaignRuleClient.java +++ b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/reward/client/CampaignRuleClient.java @@ -40,4 +40,13 @@ public interface CampaignRuleClient { @PostExchange("/api/campaign-rule/csr/create") OperationResult create(@Valid @RequestBody CampaignRule dto); + + @GetExchange("/api/campaign-rule/find-matching-rules") + List findMatchingRules( + @RequestParam("ruleType") String ruleType, + @RequestParam("transactionCode") String transactionCode, + @RequestParam("transactionDate") String transactionDate, + @RequestParam("postDate") String postDate, + @RequestParam("languageCode") String languageCode + ); } diff --git a/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/reward/client/CounterDefinitionClient.java b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/reward/client/CounterDefinitionClient.java new file mode 100644 index 0000000..517530a --- /dev/null +++ b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/reward/client/CounterDefinitionClient.java @@ -0,0 +1,18 @@ +package dev.sonpx.loyalty.mcp.reward.client; + +import dev.sonpx.loyalty.mcp.reward.model.CounterDefinition; +import java.util.List; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.service.annotation.GetExchange; +import org.springframework.web.service.annotation.HttpExchange; + +@HttpExchange +public interface CounterDefinitionClient { + + @GetExchange("/api/counter-definition/counter-id/{counterId}") + CounterDefinition findById(@PathVariable("counterId") String counterId); + + @GetExchange("/api/counter-definition/list-by-ids") + List findActiveByIds(@RequestParam("idList") List idList); +} diff --git a/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/reward/client/DeductionSequenceClient.java b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/reward/client/DeductionSequenceClient.java new file mode 100644 index 0000000..bfad351 --- /dev/null +++ b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/reward/client/DeductionSequenceClient.java @@ -0,0 +1,16 @@ +package dev.sonpx.loyalty.mcp.reward.client; + +import dev.sonpx.loyalty.mcp.reward.model.DeductionSequences; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.service.annotation.GetExchange; +import org.springframework.web.service.annotation.HttpExchange; + +@HttpExchange +public interface DeductionSequenceClient { + + @GetExchange("/api/deduction-seq/find-deduction-seq-by-id") + DeductionSequences findById(@RequestParam("deductionSeqId") String deductionSeqId); + + @GetExchange("/api/deduction-seq/find-default") + DeductionSequences findDefault(); +} diff --git a/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/reward/client/PoolDefinitionClient.java b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/reward/client/PoolDefinitionClient.java new file mode 100644 index 0000000..5dd5cf6 --- /dev/null +++ b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/reward/client/PoolDefinitionClient.java @@ -0,0 +1,18 @@ +package dev.sonpx.loyalty.mcp.reward.client; + +import dev.sonpx.loyalty.mcp.reward.model.PoolDefinition; +import java.util.List; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.service.annotation.GetExchange; +import org.springframework.web.service.annotation.HttpExchange; + +@HttpExchange +public interface PoolDefinitionClient { + + @GetExchange("/api/pool-definition/{poolId}") + PoolDefinition findById(@PathVariable("poolId") String poolId); + + @GetExchange("/api/pool-definition/list-by-ids") + List findActiveByIds(@RequestParam("idList") List idList); +} diff --git a/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/reward/client/TransactionCodeClient.java b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/reward/client/TransactionCodeClient.java new file mode 100644 index 0000000..0c18188 --- /dev/null +++ b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/reward/client/TransactionCodeClient.java @@ -0,0 +1,20 @@ +package dev.sonpx.loyalty.mcp.reward.client; + +import dev.sonpx.loyalty.mcp.reward.model.TransactionCode; +import java.util.List; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.service.annotation.GetExchange; +import org.springframework.web.service.annotation.HttpExchange; + +@HttpExchange +public interface TransactionCodeClient { + + @GetExchange("/api/transaction-code") + TransactionCode findByCode(@RequestParam("transactionCode") String transactionCode); + + @GetExchange("/api/transaction-code/list-by-codes") + List findByCodes(@RequestParam("transactionCodes") List transactionCodes); + + @GetExchange("/api/transaction-code/exists") + Boolean exists(@RequestParam("transactionCode") String transactionCode); +} diff --git a/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/service/CampaignRuleService.java b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/service/CampaignRuleService.java index dc4f6f5..918df02 100644 --- a/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/service/CampaignRuleService.java +++ b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/service/CampaignRuleService.java @@ -162,5 +162,17 @@ public class CampaignRuleService { - Nếu lỗi: thông báo lỗi rõ ràng, giải thích nguyên nhân, gợi ý cách khắc phục. """); } + + public Result> findMatchingRules(String ruleType, String transactionCode, String transactionDate, String postDate, String languageCode) { + List rules = campaignRuleClient.findMatchingRules(ruleType, transactionCode, transactionDate, postDate, languageCode); + if (rules != null) { + rules.forEach(this::sanitizeFormulas); + } + return Result.of(rules, """ + Trả lời tự nhiên bằng tiếng Việt. Hiển thị danh sách các rule/thể lệ khớp với thông tin giao dịch, + mỗi rule ghi: Tên, Mã Rule, Loại, Thời gian hiệu lực. + Tóm tắt ngắn gọn cấu hình thưởng nếu có. Không dùng markdown table. + """); + } } diff --git a/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/service/CounterDefinitionService.java b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/service/CounterDefinitionService.java new file mode 100644 index 0000000..e896488 --- /dev/null +++ b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/service/CounterDefinitionService.java @@ -0,0 +1,37 @@ +package dev.sonpx.loyalty.mcp.service; + +import dev.sonpx.loyalty.mcp.model.Result; +import dev.sonpx.loyalty.mcp.reward.client.CounterDefinitionClient; +import dev.sonpx.loyalty.mcp.reward.model.CounterDefinition; +import java.util.Arrays; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Service +@Slf4j +@RequiredArgsConstructor +public class CounterDefinitionService { + + private final CounterDefinitionClient counterDefinitionClient; + + public Result findById(String counterId) { + CounterDefinition counter = counterDefinitionClient.findById(counterId); + return Result.of(counter, """ + Trả lời tự nhiên bằng tiếng Việt. Trình bày chi tiết thông tin Counter một cách rõ ràng: + - Thông tin cơ bản: Tên Counter, Mã Counter, Loại Counter. + - Chu kỳ, Giới hạn Counter. + Dùng bullet list hoặc dạng key-value dễ đọc. + """); + } + + public Result> findActiveByIds(String ids) { + List idList = Arrays.asList(ids.split(",\\s*")); + List counters = counterDefinitionClient.findActiveByIds(idList); + return Result.of(counters, """ + Trả lời tự nhiên bằng tiếng Việt. Hiển thị danh sách các Counter, mỗi Counter ghi: Tên, Mã, Loại. + Không dùng markdown table. + """); + } +} diff --git a/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/service/DeductionSequenceService.java b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/service/DeductionSequenceService.java new file mode 100644 index 0000000..4210843 --- /dev/null +++ b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/service/DeductionSequenceService.java @@ -0,0 +1,33 @@ +package dev.sonpx.loyalty.mcp.service; + +import dev.sonpx.loyalty.mcp.model.Result; +import dev.sonpx.loyalty.mcp.reward.client.DeductionSequenceClient; +import dev.sonpx.loyalty.mcp.reward.model.DeductionSequences; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Service +@Slf4j +@RequiredArgsConstructor +public class DeductionSequenceService { + + private final DeductionSequenceClient deductionSequenceClient; + + public Result findById(String deductionSeqId) { + DeductionSequences seq = deductionSequenceClient.findById(deductionSeqId); + return Result.of(seq, """ + Trả lời tự nhiên bằng tiếng Việt. Trình bày chi tiết cấu hình Deduction Sequence: + - Tên Sequence, Mã Sequence. + - Các Pool được liên kết và thứ tự trừ điểm. + Dùng bullet list dễ đọc. + """); + } + + public Result findDefault() { + DeductionSequences seq = deductionSequenceClient.findDefault(); + return Result.of(seq, """ + Trả lời tự nhiên bằng tiếng Việt. Trình bày thông tin Deduction Sequence mặc định. + """); + } +} diff --git a/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/service/PoolDefinitionService.java b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/service/PoolDefinitionService.java new file mode 100644 index 0000000..4c3ee29 --- /dev/null +++ b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/service/PoolDefinitionService.java @@ -0,0 +1,38 @@ +package dev.sonpx.loyalty.mcp.service; + +import dev.sonpx.loyalty.mcp.model.Result; +import dev.sonpx.loyalty.mcp.reward.client.PoolDefinitionClient; +import dev.sonpx.loyalty.mcp.reward.model.PoolDefinition; +import java.util.Arrays; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Service +@Slf4j +@RequiredArgsConstructor +public class PoolDefinitionService { + + private final PoolDefinitionClient poolDefinitionClient; + + public Result findById(String poolId) { + PoolDefinition pool = poolDefinitionClient.findById(poolId); + return Result.of(pool, """ + Trả lời tự nhiên bằng tiếng Việt. Trình bày chi tiết thông tin Point Pool một cách rõ ràng: + - Thông tin cơ bản: Tên Pool, Mã Pool, Đơn vị tiền tệ. + - Loại Pool, Cấp độ Pool (Entity Level). + - Nhóm Pool (Pool Group), Tài khoản kế toán (GL Account). + Dùng bullet list hoặc dạng key-value dễ đọc. + """); + } + + public Result> findActiveByIds(String ids) { + List idList = Arrays.asList(ids.split(",\\s*")); + List pools = poolDefinitionClient.findActiveByIds(idList); + return Result.of(pools, """ + Trả lời tự nhiên bằng tiếng Việt. Hiển thị danh sách các Pool, mỗi pool ghi: Tên, Mã, Loại Pool. + Không dùng markdown table. + """); + } +} diff --git a/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/service/TransactionCodeService.java b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/service/TransactionCodeService.java new file mode 100644 index 0000000..fd07e1e --- /dev/null +++ b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/service/TransactionCodeService.java @@ -0,0 +1,44 @@ +package dev.sonpx.loyalty.mcp.service; + +import dev.sonpx.loyalty.mcp.model.Result; +import dev.sonpx.loyalty.mcp.reward.client.TransactionCodeClient; +import dev.sonpx.loyalty.mcp.reward.model.TransactionCode; +import java.util.Arrays; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Service +@Slf4j +@RequiredArgsConstructor +public class TransactionCodeService { + + private final TransactionCodeClient transactionCodeClient; + + public Result findByCode(String code) { + TransactionCode txn = transactionCodeClient.findByCode(code); + return Result.of(txn, """ + Trả lời tự nhiên bằng tiếng Việt. Trình bày chi tiết thông tin Transaction Code: + - Tên Giao dịch, Mã Giao dịch, Nhóm/Loại. + - Loại tiền tệ, Cấu hình khác nếu có. + Dùng bullet list dễ đọc. + """); + } + + public Result> findByCodes(String codes) { + List codeList = Arrays.asList(codes.split(",\\s*")); + List txnList = transactionCodeClient.findByCodes(codeList); + return Result.of(txnList, """ + Trả lời tự nhiên bằng tiếng Việt. Hiển thị danh sách các Transaction Code. + Không dùng markdown table. + """); + } + + public Result exists(String code) { + Boolean isExist = transactionCodeClient.exists(code); + return Result.of(isExist, """ + Trả lời tự nhiên bằng tiếng Việt. Nếu exists=true thì báo mã giao dịch có tồn tại, nếu false thì không tồn tại. + """); + } +} diff --git a/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/tool/CampaignRuleTools.java b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/tool/CampaignRuleTools.java index 056e32a..ed56589 100644 --- a/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/tool/CampaignRuleTools.java +++ b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/tool/CampaignRuleTools.java @@ -65,4 +65,9 @@ public class CampaignRuleTools { public Result> createRule(CampaignRule dto) { return campaignRuleService.create(dto); } + + @McpTool(description = "Tìm kiếm các rule/thể lệ khớp với một giao dịch cụ thể. Yêu cầu truyền vào loại rule, mã giao dịch (transaction code), ngày giao dịch, ngày post và ngôn ngữ (ví dụ: 'vi' hoặc 'en'). Ngày tháng format yyyy-MM-dd'T'HH:mm:ss") + public Result> findMatchingRules(String ruleType, String transactionCode, String transactionDate, String postDate, String languageCode) { + return campaignRuleService.findMatchingRules(ruleType, transactionCode, transactionDate, postDate, languageCode); + } } diff --git a/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/tool/CounterDefinitionTools.java b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/tool/CounterDefinitionTools.java new file mode 100644 index 0000000..ad12bd4 --- /dev/null +++ b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/tool/CounterDefinitionTools.java @@ -0,0 +1,26 @@ +package dev.sonpx.loyalty.mcp.tool; + +import dev.sonpx.loyalty.mcp.model.Result; +import dev.sonpx.loyalty.mcp.reward.model.CounterDefinition; +import dev.sonpx.loyalty.mcp.service.CounterDefinitionService; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.ai.mcp.annotation.McpTool; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class CounterDefinitionTools { + + private final CounterDefinitionService counterDefinitionService; + + @McpTool(description = "Lấy thông tin chi tiết một Counter theo ID.") + public Result getCounterDefinitionById(String counterId) { + return counterDefinitionService.findById(counterId); + } + + @McpTool(description = "Lấy thông tin nhiều Counter theo danh sách ID, phân tách bằng dấu phẩy.") + public Result> getCounterDefinitionsByIds(String ids) { + return counterDefinitionService.findActiveByIds(ids); + } +} diff --git a/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/tool/DeductionSequenceTools.java b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/tool/DeductionSequenceTools.java new file mode 100644 index 0000000..a94c6ce --- /dev/null +++ b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/tool/DeductionSequenceTools.java @@ -0,0 +1,25 @@ +package dev.sonpx.loyalty.mcp.tool; + +import dev.sonpx.loyalty.mcp.model.Result; +import dev.sonpx.loyalty.mcp.reward.model.DeductionSequences; +import dev.sonpx.loyalty.mcp.service.DeductionSequenceService; +import lombok.RequiredArgsConstructor; +import org.springframework.ai.mcp.annotation.McpTool; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class DeductionSequenceTools { + + private final DeductionSequenceService deductionSequenceService; + + @McpTool(description = "Lấy thông tin cấu hình trừ điểm (Deduction Sequence) theo ID.") + public Result getDeductionSequenceById(String deductionSeqId) { + return deductionSequenceService.findById(deductionSeqId); + } + + @McpTool(description = "Lấy thông tin cấu hình trừ điểm (Deduction Sequence) mặc định của hệ thống.") + public Result getDefaultDeductionSequence() { + return deductionSequenceService.findDefault(); + } +} diff --git a/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/tool/PoolDefinitionTools.java b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/tool/PoolDefinitionTools.java new file mode 100644 index 0000000..e0ff8d0 --- /dev/null +++ b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/tool/PoolDefinitionTools.java @@ -0,0 +1,26 @@ +package dev.sonpx.loyalty.mcp.tool; + +import dev.sonpx.loyalty.mcp.model.Result; +import dev.sonpx.loyalty.mcp.reward.model.PoolDefinition; +import dev.sonpx.loyalty.mcp.service.PoolDefinitionService; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.ai.mcp.annotation.McpTool; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class PoolDefinitionTools { + + private final PoolDefinitionService poolDefinitionService; + + @McpTool(description = "Lấy thông tin chi tiết một Point Pool theo ID.") + public Result getPoolDefinitionById(String poolId) { + return poolDefinitionService.findById(poolId); + } + + @McpTool(description = "Lấy thông tin nhiều Point Pool theo danh sách ID, phân tách bằng dấu phẩy.") + public Result> getPoolDefinitionsByIds(String ids) { + return poolDefinitionService.findActiveByIds(ids); + } +} diff --git a/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/tool/TransactionCodeTools.java b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/tool/TransactionCodeTools.java new file mode 100644 index 0000000..25e89a3 --- /dev/null +++ b/loyalty-mcp-server/src/main/java/dev/sonpx/loyalty/mcp/tool/TransactionCodeTools.java @@ -0,0 +1,31 @@ +package dev.sonpx.loyalty.mcp.tool; + +import dev.sonpx.loyalty.mcp.model.Result; +import dev.sonpx.loyalty.mcp.reward.model.TransactionCode; +import dev.sonpx.loyalty.mcp.service.TransactionCodeService; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.ai.mcp.annotation.McpTool; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class TransactionCodeTools { + + private final TransactionCodeService transactionCodeService; + + @McpTool(description = "Lấy thông tin chi tiết một Mã giao dịch (Transaction Code) theo mã.") + public Result getTransactionCode(String transactionCode) { + return transactionCodeService.findByCode(transactionCode); + } + + @McpTool(description = "Lấy thông tin nhiều Mã giao dịch theo danh sách mã, phân tách bằng dấu phẩy.") + public Result> getTransactionCodes(String transactionCodes) { + return transactionCodeService.findByCodes(transactionCodes); + } + + @McpTool(description = "Kiểm tra xem một Mã giao dịch có tồn tại hay không.") + public Result checkTransactionCodeExists(String transactionCode) { + return transactionCodeService.exists(transactionCode); + } +}