feat(wcs): add shared domain contracts
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
package com.ruoyi.wcs.domain.shared;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Objects;
|
||||
|
||||
public final class DomainEvent {
|
||||
private final String eventId;
|
||||
private final String aggregateId;
|
||||
private final long sequence;
|
||||
private final Instant occurredAt;
|
||||
private final String type;
|
||||
|
||||
public DomainEvent(String eventId, String aggregateId, long sequence,
|
||||
Instant occurredAt, String type) {
|
||||
this.eventId = requireText(eventId, "eventId");
|
||||
this.aggregateId = requireText(aggregateId, "aggregateId");
|
||||
if (sequence < 1L) {
|
||||
throw new IllegalArgumentException("sequence must be positive");
|
||||
}
|
||||
this.sequence = sequence;
|
||||
this.occurredAt = Objects.requireNonNull(occurredAt, "occurredAt");
|
||||
this.type = requireText(type, "type");
|
||||
}
|
||||
|
||||
public String getEventId() {
|
||||
return eventId;
|
||||
}
|
||||
|
||||
public String getAggregateId() {
|
||||
return aggregateId;
|
||||
}
|
||||
|
||||
public long getSequence() {
|
||||
return sequence;
|
||||
}
|
||||
|
||||
public Instant getOccurredAt() {
|
||||
return occurredAt;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
private static String requireText(String value, String field) {
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
throw new IllegalArgumentException(field + " must not be blank");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.ruoyi.wcs.domain.shared;
|
||||
|
||||
public final class DomainRuleViolation extends RuntimeException {
|
||||
public DomainRuleViolation(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.ruoyi.wcs.domain.shared;
|
||||
|
||||
public interface IdGenerator {
|
||||
String nextId();
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.ruoyi.wcs.domain.shared;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
public interface WcsClock {
|
||||
Instant now();
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.ruoyi.wcs.domain.shared;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
class SharedContractsTest {
|
||||
|
||||
@Test
|
||||
void rejectsBlankEventIdentity() {
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
new DomainEvent("", "ORDER-1", 1L, Instant.EPOCH, "OrderAccepted"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsInvalidEventSequence() {
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
new DomainEvent("E-1", "ORDER-1", 0L, Instant.EPOCH, "OrderAccepted"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void exposesDeterministicEventFields() {
|
||||
Instant occurredAt = Instant.parse("2026-08-04T00:00:00Z");
|
||||
DomainEvent event = new DomainEvent("E-1", "ORDER-1", 2L,
|
||||
occurredAt, "OrderPlanned");
|
||||
|
||||
assertEquals("E-1", event.getEventId());
|
||||
assertEquals("ORDER-1", event.getAggregateId());
|
||||
assertEquals(2L, event.getSequence());
|
||||
assertEquals(occurredAt, event.getOccurredAt());
|
||||
assertEquals("OrderPlanned", event.getType());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user