diff --git a/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/device/DeviceController.java b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/device/DeviceController.java new file mode 100644 index 0000000..8b234fd --- /dev/null +++ b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/device/DeviceController.java @@ -0,0 +1,80 @@ +package cn.craftlabs.platform.api.device; + +import cn.craftlabs.platform.api.service.DeviceService; +import cn.craftlabs.platform.api.web.dto.DeviceBindingResponse; +import cn.craftlabs.platform.api.web.dto.DeviceCreateRequest; +import cn.craftlabs.platform.api.web.dto.DeviceResponse; +import cn.craftlabs.platform.api.web.dto.DeviceSwapRequestDto; +import cn.craftlabs.platform.api.web.dto.PageResponse; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import org.springframework.http.HttpStatus; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ResponseStatusException; + +import java.util.List; + +@RestController +@RequestMapping("/api/v1/devices") +@Validated +public class DeviceController { + + private final DeviceService deviceService; + + public DeviceController(DeviceService deviceService) { + this.deviceService = deviceService; + } + + @GetMapping + public PageResponse list( + @RequestParam(value = "page", defaultValue = "0") @Min(0) int page, + @RequestParam(value = "size", defaultValue = "20") @Min(1) @Max(200) int size, + @RequestParam(value = "customerId", required = false) Long customerId, + @RequestParam(value = "site", required = false) String site, + @RequestParam(value = "snCode", required = false) String snCode) { + return deviceService.listDevices(page, size, customerId, site, snCode); + } + + @GetMapping("/{id}") + public DeviceResponse get(@PathVariable("id") long id) { + DeviceResponse result = deviceService.getDevice(id); + if (result == null) { + throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Device not found: " + id); + } + return result; + } + + @PostMapping + public DeviceResponse create(@Valid @RequestBody DeviceCreateRequest request) { + return deviceService.createDevice(request); + } + + @PutMapping("/{id}") + public DeviceResponse update(@PathVariable("id") long id, @Valid @RequestBody DeviceCreateRequest request) { + DeviceResponse result = deviceService.updateDevice(id, request); + if (result == null) { + throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Device not found: " + id); + } + return result; + } + + @GetMapping("/{id}/bindings") + public List bindings(@PathVariable("id") long id) { + return deviceService.getBindings(id); + } + + @PostMapping("/{id}/swap-request") + public void swapRequest(@PathVariable("id") long id, @Valid @RequestBody DeviceSwapRequestDto request) { + request.setOldDeviceId(id); + deviceService.createSwapRequest(request); + } +} diff --git a/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/service/CallbackEventIngestService.java b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/service/CallbackEventIngestService.java index f7ba7c3..0708e25 100644 --- a/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/service/CallbackEventIngestService.java +++ b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/service/CallbackEventIngestService.java @@ -33,16 +33,19 @@ public class CallbackEventIngestService { private final PlatformLicenseSnMapper licenseSnMapper; private final PlatformContractLineMapper contractLineMapper; private final ObjectMapper objectMapper; + private final DeviceService deviceService; public CallbackEventIngestService( PlatformCallbackInboxMapper inboxMapper, PlatformLicenseSnMapper licenseSnMapper, PlatformContractLineMapper contractLineMapper, - ObjectMapper objectMapper) { + ObjectMapper objectMapper, + DeviceService deviceService) { this.inboxMapper = inboxMapper; this.licenseSnMapper = licenseSnMapper; this.contractLineMapper = contractLineMapper; this.objectMapper = objectMapper; + this.deviceService = deviceService; } @Transactional @@ -107,6 +110,12 @@ public class CallbackEventIngestService { } throw e; } + if (row.getEventType() != null && row.getEventType().startsWith("device:")) { + String mid = extractMid(request.getRawPayload()); + if (mid != null && row.getLicenseSnId() != null) { + deviceService.handleDeviceEvent(mid, row.getLicenseSnId()); + } + } return new CallbackEventIngestResponse(row.getId(), false); } @@ -157,6 +166,19 @@ public class CallbackEventIngestService { } } + private static String extractMid(JsonNode payload) { + if (payload == null || !payload.isObject()) return null; + JsonNode data = payload.get("data"); + if (data != null && data.isObject()) { + JsonNode mid = data.get("mid"); + if (mid != null && mid.isTextual()) { + String t = mid.asText(); + if (org.springframework.util.StringUtils.hasText(t)) return t.trim(); + } + } + return null; + } + private static String extractSnCode(JsonNode payload) { if (payload == null || !payload.isObject()) { return null;