mirror of
https://github.com/hpd840321/craftlabs-authorization-sdk.git
synced 2026-06-09 10:00:30 +08:00
feat: add M9 ReportService + ReportController
This commit is contained in:
+42
@@ -0,0 +1,42 @@
|
||||
package cn.craftlabs.platform.api.report;
|
||||
|
||||
import cn.craftlabs.platform.api.service.ReportService;
|
||||
import cn.craftlabs.platform.api.web.dto.CallbackStatsResponse;
|
||||
import cn.craftlabs.platform.api.web.dto.ContractSnReportRow;
|
||||
import cn.craftlabs.platform.api.web.dto.ProjectHealthRow;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/reports")
|
||||
public class ReportController {
|
||||
|
||||
private final ReportService reportService;
|
||||
|
||||
public ReportController(ReportService reportService) {
|
||||
this.reportService = reportService;
|
||||
}
|
||||
|
||||
@GetMapping("/contract-sn")
|
||||
public List<ContractSnReportRow> getContractSnReport(
|
||||
@RequestParam(value = "projectId", required = false) Long projectId,
|
||||
@RequestParam(value = "contractId", required = false) Long contractId) {
|
||||
return reportService.getContractSnReport(projectId, contractId);
|
||||
}
|
||||
|
||||
@GetMapping("/callback-stats")
|
||||
public CallbackStatsResponse getCallbackStats(
|
||||
@RequestParam(value = "from", required = false) String from,
|
||||
@RequestParam(value = "to", required = false) String to) {
|
||||
return reportService.getCallbackStats(from, to);
|
||||
}
|
||||
|
||||
@GetMapping("/project-health")
|
||||
public List<ProjectHealthRow> getProjectHealth() {
|
||||
return reportService.getProjectHealth();
|
||||
}
|
||||
}
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
package cn.craftlabs.platform.api.service;
|
||||
|
||||
import cn.craftlabs.platform.api.persistence.callback.PlatformCallbackInbox;
|
||||
import cn.craftlabs.platform.api.persistence.callback.PlatformCallbackInboxMapper;
|
||||
import cn.craftlabs.platform.api.persistence.contract.PlatformContract;
|
||||
import cn.craftlabs.platform.api.persistence.contract.PlatformContractLine;
|
||||
import cn.craftlabs.platform.api.persistence.contract.PlatformContractLineMapper;
|
||||
import cn.craftlabs.platform.api.persistence.contract.PlatformContractMapper;
|
||||
import cn.craftlabs.platform.api.persistence.customer.PlatformCustomer;
|
||||
import cn.craftlabs.platform.api.persistence.customer.PlatformCustomerMapper;
|
||||
import cn.craftlabs.platform.api.persistence.license.PlatformLicenseSn;
|
||||
import cn.craftlabs.platform.api.persistence.license.PlatformLicenseSnMapper;
|
||||
import cn.craftlabs.platform.api.persistence.project.PlatformProject;
|
||||
import cn.craftlabs.platform.api.persistence.project.PlatformProjectMapper;
|
||||
import cn.craftlabs.platform.api.web.dto.CallbackStatsResponse;
|
||||
import cn.craftlabs.platform.api.web.dto.ContractSnReportRow;
|
||||
import cn.craftlabs.platform.api.web.dto.ProjectHealthRow;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class ReportService {
|
||||
|
||||
private final PlatformContractMapper contractMapper;
|
||||
private final PlatformContractLineMapper contractLineMapper;
|
||||
private final PlatformLicenseSnMapper licenseSnMapper;
|
||||
private final PlatformCallbackInboxMapper callbackInboxMapper;
|
||||
private final PlatformProjectMapper projectMapper;
|
||||
private final PlatformCustomerMapper customerMapper;
|
||||
|
||||
public ReportService(
|
||||
PlatformContractMapper contractMapper,
|
||||
PlatformContractLineMapper contractLineMapper,
|
||||
PlatformLicenseSnMapper licenseSnMapper,
|
||||
PlatformCallbackInboxMapper callbackInboxMapper,
|
||||
PlatformProjectMapper projectMapper,
|
||||
PlatformCustomerMapper customerMapper) {
|
||||
this.contractMapper = contractMapper;
|
||||
this.contractLineMapper = contractLineMapper;
|
||||
this.licenseSnMapper = licenseSnMapper;
|
||||
this.callbackInboxMapper = callbackInboxMapper;
|
||||
this.projectMapper = projectMapper;
|
||||
this.customerMapper = customerMapper;
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<ContractSnReportRow> getContractSnReport(Long projectId, Long contractId) {
|
||||
LambdaQueryWrapper<PlatformContract> q = Wrappers.lambdaQuery(PlatformContract.class)
|
||||
.eq(projectId != null, PlatformContract::getProjectId, projectId)
|
||||
.eq(contractId != null, PlatformContract::getId, contractId)
|
||||
.orderByDesc(PlatformContract::getId);
|
||||
List<PlatformContract> contracts = contractMapper.selectList(q);
|
||||
List<ContractSnReportRow> rows = new ArrayList<>();
|
||||
for (PlatformContract contract : contracts) {
|
||||
String customerName = resolveCustomerName(contract.getCustomerId());
|
||||
LambdaQueryWrapper<PlatformContractLine> lineQ = Wrappers.lambdaQuery(PlatformContractLine.class)
|
||||
.eq(PlatformContractLine::getContractId, contract.getId());
|
||||
List<PlatformContractLine> lines = contractLineMapper.selectList(lineQ);
|
||||
for (PlatformContractLine line : lines) {
|
||||
LambdaQueryWrapper<PlatformLicenseSn> snQ = Wrappers.lambdaQuery(PlatformLicenseSn.class)
|
||||
.eq(PlatformLicenseSn::getContractLineId, line.getId());
|
||||
List<PlatformLicenseSn> sns = licenseSnMapper.selectList(snQ);
|
||||
int issuedCount = sns.size();
|
||||
int activatedCount = (int) sns.stream().filter(sn -> "ACTIVATED".equals(sn.getStatus())).count();
|
||||
int expectedCount = line.getQuantity() != null ? line.getQuantity().intValue() : 0;
|
||||
int gapCount = Math.max(0, expectedCount - issuedCount);
|
||||
|
||||
ContractSnReportRow row = new ContractSnReportRow();
|
||||
row.setContractId(contract.getId());
|
||||
row.setContractTitle(contract.getTitle());
|
||||
row.setCustomerName(customerName);
|
||||
row.setLineItemName(line.getItemName());
|
||||
row.setExpectedCount(expectedCount);
|
||||
row.setIssuedCount(issuedCount);
|
||||
row.setActivatedCount(activatedCount);
|
||||
row.setGapCount(gapCount);
|
||||
row.setStatus(gapCount > 0 ? "缺额" : "正常");
|
||||
rows.add(row);
|
||||
}
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public CallbackStatsResponse getCallbackStats(String from, String to) {
|
||||
List<PlatformCallbackInbox> all = callbackInboxMapper.selectList(Wrappers.lambdaQuery(PlatformCallbackInbox.class));
|
||||
long totalEvents = all.size();
|
||||
long processedCount = all.stream().filter(c -> "PROCESSED".equals(c.getStatus())).count();
|
||||
long pendingCount = all.stream().filter(c -> "PENDING".equals(c.getStatus())).count();
|
||||
double successRate = totalEvents > 0 ? (double) processedCount / totalEvents * 100 : 0.0;
|
||||
|
||||
Map<String, Long> typeGroup = all.stream()
|
||||
.collect(Collectors.groupingBy(PlatformCallbackInbox::getEventType, Collectors.counting()));
|
||||
List<Map<String, Object>> eventTypeDistribution = new ArrayList<>();
|
||||
for (Map.Entry<String, Long> entry : typeGroup.entrySet()) {
|
||||
Map<String, Object> item = new HashMap<>();
|
||||
item.put("eventType", entry.getKey());
|
||||
item.put("count", entry.getValue());
|
||||
eventTypeDistribution.add(item);
|
||||
}
|
||||
|
||||
CallbackStatsResponse resp = new CallbackStatsResponse();
|
||||
resp.setTotalEvents(totalEvents);
|
||||
resp.setSuccessRate(successRate);
|
||||
resp.setPendingCount(pendingCount);
|
||||
resp.setEventTypeDistribution(eventTypeDistribution);
|
||||
resp.setTopFailureReasons(new ArrayList<>());
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<ProjectHealthRow> getProjectHealth() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
private String resolveCustomerName(Long customerId) {
|
||||
if (customerId == null) {
|
||||
return null;
|
||||
}
|
||||
PlatformCustomer c = customerMapper.selectById(customerId);
|
||||
return c != null ? c.getName() : null;
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package cn.craftlabs.platform.api.web.dto;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class CallbackStatsResponse {
|
||||
|
||||
private long totalEvents;
|
||||
private double successRate;
|
||||
private long pendingCount;
|
||||
private List<Map<String, Object>> eventTypeDistribution;
|
||||
private List<Map<String, Object>> topFailureReasons;
|
||||
|
||||
public long getTotalEvents() {
|
||||
return totalEvents;
|
||||
}
|
||||
|
||||
public void setTotalEvents(long totalEvents) {
|
||||
this.totalEvents = totalEvents;
|
||||
}
|
||||
|
||||
public double getSuccessRate() {
|
||||
return successRate;
|
||||
}
|
||||
|
||||
public void setSuccessRate(double successRate) {
|
||||
this.successRate = successRate;
|
||||
}
|
||||
|
||||
public long getPendingCount() {
|
||||
return pendingCount;
|
||||
}
|
||||
|
||||
public void setPendingCount(long pendingCount) {
|
||||
this.pendingCount = pendingCount;
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> getEventTypeDistribution() {
|
||||
return eventTypeDistribution;
|
||||
}
|
||||
|
||||
public void setEventTypeDistribution(List<Map<String, Object>> eventTypeDistribution) {
|
||||
this.eventTypeDistribution = eventTypeDistribution;
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> getTopFailureReasons() {
|
||||
return topFailureReasons;
|
||||
}
|
||||
|
||||
public void setTopFailureReasons(List<Map<String, Object>> topFailureReasons) {
|
||||
this.topFailureReasons = topFailureReasons;
|
||||
}
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
package cn.craftlabs.platform.api.web.dto;
|
||||
|
||||
public class ContractSnReportRow {
|
||||
|
||||
private Long contractId;
|
||||
private String contractTitle;
|
||||
private String customerName;
|
||||
private String lineItemName;
|
||||
private int expectedCount;
|
||||
private int issuedCount;
|
||||
private int activatedCount;
|
||||
private int gapCount;
|
||||
private String status;
|
||||
|
||||
public Long getContractId() {
|
||||
return contractId;
|
||||
}
|
||||
|
||||
public void setContractId(Long contractId) {
|
||||
this.contractId = contractId;
|
||||
}
|
||||
|
||||
public String getContractTitle() {
|
||||
return contractTitle;
|
||||
}
|
||||
|
||||
public void setContractTitle(String contractTitle) {
|
||||
this.contractTitle = contractTitle;
|
||||
}
|
||||
|
||||
public String getCustomerName() {
|
||||
return customerName;
|
||||
}
|
||||
|
||||
public void setCustomerName(String customerName) {
|
||||
this.customerName = customerName;
|
||||
}
|
||||
|
||||
public String getLineItemName() {
|
||||
return lineItemName;
|
||||
}
|
||||
|
||||
public void setLineItemName(String lineItemName) {
|
||||
this.lineItemName = lineItemName;
|
||||
}
|
||||
|
||||
public int getExpectedCount() {
|
||||
return expectedCount;
|
||||
}
|
||||
|
||||
public void setExpectedCount(int expectedCount) {
|
||||
this.expectedCount = expectedCount;
|
||||
}
|
||||
|
||||
public int getIssuedCount() {
|
||||
return issuedCount;
|
||||
}
|
||||
|
||||
public void setIssuedCount(int issuedCount) {
|
||||
this.issuedCount = issuedCount;
|
||||
}
|
||||
|
||||
public int getActivatedCount() {
|
||||
return activatedCount;
|
||||
}
|
||||
|
||||
public void setActivatedCount(int activatedCount) {
|
||||
this.activatedCount = activatedCount;
|
||||
}
|
||||
|
||||
public int getGapCount() {
|
||||
return gapCount;
|
||||
}
|
||||
|
||||
public void setGapCount(int gapCount) {
|
||||
this.gapCount = gapCount;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
package cn.craftlabs.platform.api.web.dto;
|
||||
|
||||
public class ProjectHealthRow {
|
||||
|
||||
private Long projectId;
|
||||
private String projectName;
|
||||
private double deliveryRate;
|
||||
private double snIssuedRate;
|
||||
private double activationRate;
|
||||
private String healthLevel;
|
||||
|
||||
public Long getProjectId() {
|
||||
return projectId;
|
||||
}
|
||||
|
||||
public void setProjectId(Long projectId) {
|
||||
this.projectId = projectId;
|
||||
}
|
||||
|
||||
public String getProjectName() {
|
||||
return projectName;
|
||||
}
|
||||
|
||||
public void setProjectName(String projectName) {
|
||||
this.projectName = projectName;
|
||||
}
|
||||
|
||||
public double getDeliveryRate() {
|
||||
return deliveryRate;
|
||||
}
|
||||
|
||||
public void setDeliveryRate(double deliveryRate) {
|
||||
this.deliveryRate = deliveryRate;
|
||||
}
|
||||
|
||||
public double getSnIssuedRate() {
|
||||
return snIssuedRate;
|
||||
}
|
||||
|
||||
public void setSnIssuedRate(double snIssuedRate) {
|
||||
this.snIssuedRate = snIssuedRate;
|
||||
}
|
||||
|
||||
public double getActivationRate() {
|
||||
return activationRate;
|
||||
}
|
||||
|
||||
public void setActivationRate(double activationRate) {
|
||||
this.activationRate = activationRate;
|
||||
}
|
||||
|
||||
public String getHealthLevel() {
|
||||
return healthLevel;
|
||||
}
|
||||
|
||||
public void setHealthLevel(String healthLevel) {
|
||||
this.healthLevel = healthLevel;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user