eva4j 1.0.13 → 1.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +314 -10
- package/COMMAND_EVALUATION.md +15 -16
- package/DOMAIN_YAML_GUIDE.md +576 -10
- package/FUTURE_FEATURES.md +1627 -1168
- package/README.md +318 -13
- package/bin/eva4j.js +34 -0
- package/config/defaults.json +1 -0
- package/design-system.md +797 -0
- package/docs/commands/EVALUATE_SYSTEM.md +994 -0
- package/docs/commands/GENERATE_ENTITIES.md +795 -6
- package/docs/commands/INDEX.md +10 -1
- package/examples/domain-endpoints-relations.yaml +353 -0
- package/examples/domain-endpoints-versioned.yaml +144 -0
- package/examples/domain-endpoints.yaml +135 -0
- package/examples/domain-events.yaml +166 -20
- package/examples/domain-listeners.yaml +212 -0
- package/examples/domain-one-to-many.yaml +1 -0
- package/examples/domain-one-to-one.yaml +1 -0
- package/examples/domain-ports.yaml +414 -0
- package/examples/domain-soft-delete.yaml +47 -44
- package/examples/system/notification.yaml +147 -0
- package/examples/system/product.yaml +185 -0
- package/examples/system/system.yaml +112 -0
- package/examples/system-report.html +971 -0
- package/examples/system.yaml +332 -0
- package/package.json +2 -1
- package/src/commands/build.js +714 -0
- package/src/commands/create.js +7 -3
- package/src/commands/detach.js +1 -0
- package/src/commands/evaluate-system.js +610 -0
- package/src/commands/generate-entities.js +1331 -49
- package/src/commands/generate-http-exchange.js +2 -0
- package/src/commands/generate-kafka-event.js +98 -11
- package/src/generators/base-generator.js +8 -1
- package/src/generators/postman-generator.js +188 -0
- package/src/generators/shared-generator.js +10 -0
- package/src/utils/config-manager.js +54 -0
- package/src/utils/context-builder.js +1 -0
- package/src/utils/domain-diagram.js +192 -0
- package/src/utils/domain-validator.js +970 -0
- package/src/utils/fake-data.js +376 -0
- package/src/utils/naming.js +3 -2
- package/src/utils/system-validator.js +434 -0
- package/src/utils/yaml-to-entity.js +302 -8
- package/templates/aggregate/AggregateMapper.java.ejs +3 -2
- package/templates/aggregate/AggregateRepository.java.ejs +8 -2
- package/templates/aggregate/AggregateRepositoryImpl.java.ejs +13 -3
- package/templates/aggregate/AggregateRoot.java.ejs +60 -2
- package/templates/aggregate/DomainEventHandler.java.ejs +27 -20
- package/templates/aggregate/DomainEventRecord.java.ejs +24 -8
- package/templates/aggregate/DomainEventSnapshot.java.ejs +46 -0
- package/templates/aggregate/JpaAggregateRoot.java.ejs +6 -0
- package/templates/aggregate/JpaRepository.java.ejs +5 -0
- package/templates/base/gradle/build.gradle.ejs +3 -2
- package/templates/base/root/AGENTS.md.ejs +306 -45
- package/templates/base/root/skill-build-domain-yaml-references-generate-entities.md.ejs +1663 -0
- package/templates/base/root/skill-build-system-yaml.ejs +1446 -0
- package/templates/base/root/system.yaml.ejs +97 -0
- package/templates/crud/ApplicationMapper.java.ejs +4 -0
- package/templates/crud/Controller.java.ejs +4 -4
- package/templates/crud/CreateCommand.java.ejs +4 -0
- package/templates/crud/CreateItemDto.java.ejs +4 -0
- package/templates/crud/CreateValueObjectDto.java.ejs +4 -0
- package/templates/crud/DeleteCommandHandler.java.ejs +10 -2
- package/templates/crud/EndpointsController.java.ejs +178 -0
- package/templates/crud/FindByQuery.java.ejs +17 -0
- package/templates/crud/FindByQueryHandler.java.ejs +57 -0
- package/templates/crud/ListQuery.java.ejs +1 -1
- package/templates/crud/ListQueryHandler.java.ejs +8 -8
- package/templates/crud/ScaffoldCommand.java.ejs +12 -0
- package/templates/crud/ScaffoldCommandHandler.java.ejs +43 -0
- package/templates/crud/ScaffoldQuery.java.ejs +13 -0
- package/templates/crud/ScaffoldQueryHandler.java.ejs +41 -0
- package/templates/crud/SubEntityAddCommand.java.ejs +21 -0
- package/templates/crud/SubEntityAddCommandHandler.java.ejs +43 -0
- package/templates/crud/SubEntityRemoveCommand.java.ejs +9 -0
- package/templates/crud/SubEntityRemoveCommandHandler.java.ejs +42 -0
- package/templates/crud/TransitionCommand.java.ejs +9 -0
- package/templates/crud/TransitionCommandHandler.java.ejs +39 -0
- package/templates/crud/UpdateCommand.java.ejs +4 -0
- package/templates/evaluate/report.html.ejs +1363 -0
- package/templates/kafka-event/DomainEventHandlerMethod.ejs +3 -1
- package/templates/kafka-event/Event.java.ejs +16 -0
- package/templates/kafka-listener/KafkaController.java.ejs +1 -1
- package/templates/kafka-listener/KafkaListenerClass.java.ejs +1 -1
- package/templates/kafka-listener/ListenerClass.java.ejs +65 -0
- package/templates/kafka-listener/ListenerCommand.java.ejs +31 -0
- package/templates/kafka-listener/ListenerCommandHandler.java.ejs +23 -0
- package/templates/kafka-listener/ListenerIntegrationEvent.java.ejs +37 -0
- package/templates/kafka-listener/ListenerMethod.java.ejs +1 -1
- package/templates/kafka-listener/ListenerNestedType.java.ejs +28 -0
- package/templates/mock/MockEvent.java.ejs +10 -0
- package/templates/mock/MockMessageBrokerImpl.java.ejs +35 -0
- package/templates/mock/MockMessageBrokerImplMethod.java.ejs +6 -0
- package/templates/mock/SpringEventListener.java.ejs +61 -0
- package/templates/ports/PortDomainModel.java.ejs +35 -0
- package/templates/ports/PortFeignAdapter.java.ejs +67 -0
- package/templates/ports/PortFeignClient.java.ejs +45 -0
- package/templates/ports/PortFeignConfig.java.ejs +24 -0
- package/templates/ports/PortInterface.java.ejs +45 -0
- package/templates/ports/PortNestedType.java.ejs +28 -0
- package/templates/ports/PortRequestDto.java.ejs +30 -0
- package/templates/ports/PortResponseDto.java.ejs +28 -0
- package/templates/postman/Collection.json.ejs +1 -1
- package/templates/postman/UnifiedCollection.json.ejs +185 -0
- package/templates/shared/configurations/eventPublicationConfig/EventPublicationSchemaConfig.java.ejs +109 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
2
|
+
# notification — Domain Model (Supporting Domain)
|
|
3
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
4
|
+
# Dispatches notifications to users across multiple channels (EMAIL, SMS, PUSH).
|
|
5
|
+
# Tests: listeners (consuming ProductPublishedEvent + ProductDiscontinuedEvent),
|
|
6
|
+
# enum transitions with triggers, soft delete, scaffold endpoint.
|
|
7
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
8
|
+
|
|
9
|
+
aggregates:
|
|
10
|
+
|
|
11
|
+
# ════════════════════════════════════════════════════════════════════════════
|
|
12
|
+
# Aggregate: Notification
|
|
13
|
+
# ════════════════════════════════════════════════════════════════════════════
|
|
14
|
+
- name: Notification
|
|
15
|
+
entities:
|
|
16
|
+
- name: Notification
|
|
17
|
+
isRoot: true
|
|
18
|
+
tableName: notifications
|
|
19
|
+
hasSoftDelete: true
|
|
20
|
+
audit:
|
|
21
|
+
enabled: true
|
|
22
|
+
trackUser: false
|
|
23
|
+
fields:
|
|
24
|
+
- name: id
|
|
25
|
+
type: String
|
|
26
|
+
- name: recipientId
|
|
27
|
+
type: String
|
|
28
|
+
validations:
|
|
29
|
+
- type: NotBlank
|
|
30
|
+
message: "Recipient ID is required"
|
|
31
|
+
- name: channel
|
|
32
|
+
type: NotificationChannel
|
|
33
|
+
validations:
|
|
34
|
+
- type: NotNull
|
|
35
|
+
message: "Channel is required"
|
|
36
|
+
- name: subject
|
|
37
|
+
type: String
|
|
38
|
+
validations:
|
|
39
|
+
- type: NotBlank
|
|
40
|
+
message: "Subject is required"
|
|
41
|
+
- name: message
|
|
42
|
+
type: String
|
|
43
|
+
validations:
|
|
44
|
+
- type: NotBlank
|
|
45
|
+
message: "Message is required"
|
|
46
|
+
- name: status
|
|
47
|
+
type: NotificationStatus
|
|
48
|
+
readOnly: true
|
|
49
|
+
- name: sentAt
|
|
50
|
+
type: LocalDateTime
|
|
51
|
+
readOnly: true
|
|
52
|
+
- name: readAt
|
|
53
|
+
type: LocalDateTime
|
|
54
|
+
readOnly: true
|
|
55
|
+
|
|
56
|
+
enums:
|
|
57
|
+
- name: NotificationChannel
|
|
58
|
+
values:
|
|
59
|
+
- EMAIL
|
|
60
|
+
- SMS
|
|
61
|
+
- PUSH
|
|
62
|
+
|
|
63
|
+
- name: NotificationStatus
|
|
64
|
+
initialValue: PENDING
|
|
65
|
+
transitions:
|
|
66
|
+
- from: PENDING
|
|
67
|
+
to: SENT
|
|
68
|
+
method: send
|
|
69
|
+
- from: SENT
|
|
70
|
+
to: READ
|
|
71
|
+
method: markRead
|
|
72
|
+
- from: [PENDING, SENT]
|
|
73
|
+
to: FAILED
|
|
74
|
+
method: fail
|
|
75
|
+
values:
|
|
76
|
+
- PENDING
|
|
77
|
+
- SENT
|
|
78
|
+
- READ
|
|
79
|
+
- FAILED
|
|
80
|
+
|
|
81
|
+
events:
|
|
82
|
+
# NotificationSentEvent — triggered by send transition
|
|
83
|
+
- name: NotificationSentEvent
|
|
84
|
+
triggers:
|
|
85
|
+
- send
|
|
86
|
+
fields:
|
|
87
|
+
- name: notificationId
|
|
88
|
+
type: String
|
|
89
|
+
- name: recipientId
|
|
90
|
+
type: String
|
|
91
|
+
- name: sentAt
|
|
92
|
+
type: LocalDateTime
|
|
93
|
+
|
|
94
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
95
|
+
# Declarative REST endpoints
|
|
96
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
97
|
+
endpoints:
|
|
98
|
+
basePath: /notifications
|
|
99
|
+
versions:
|
|
100
|
+
- version: v1
|
|
101
|
+
operations:
|
|
102
|
+
- useCase: CreateNotification
|
|
103
|
+
method: POST
|
|
104
|
+
path: /
|
|
105
|
+
- useCase: GetNotification
|
|
106
|
+
method: GET
|
|
107
|
+
path: /{id}
|
|
108
|
+
- useCase: FindAllNotifications
|
|
109
|
+
method: GET
|
|
110
|
+
path: /
|
|
111
|
+
- useCase: DeleteNotification
|
|
112
|
+
method: DELETE
|
|
113
|
+
path: /{id}
|
|
114
|
+
# Scaffold: MarkNotificationRead doesn't match transition pattern
|
|
115
|
+
# (transition method is markRead → MarkReadNotification, not MarkNotificationRead)
|
|
116
|
+
# → generates ScaffoldCommand stub with TODO
|
|
117
|
+
- useCase: MarkNotificationRead
|
|
118
|
+
method: PUT
|
|
119
|
+
path: /{id}/read
|
|
120
|
+
|
|
121
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
122
|
+
# Consumed events (listeners)
|
|
123
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
124
|
+
listeners:
|
|
125
|
+
- event: ProductPublishedEvent
|
|
126
|
+
producer: product
|
|
127
|
+
topic: PRODUCT_PUBLISHED
|
|
128
|
+
useCase: SendProductPublishedNotification
|
|
129
|
+
fields:
|
|
130
|
+
- name: productId
|
|
131
|
+
type: String
|
|
132
|
+
- name: name
|
|
133
|
+
type: String
|
|
134
|
+
- name: price
|
|
135
|
+
type: BigDecimal
|
|
136
|
+
- name: publishedAt
|
|
137
|
+
type: LocalDateTime
|
|
138
|
+
|
|
139
|
+
- event: ProductDiscontinuedEvent
|
|
140
|
+
producer: product
|
|
141
|
+
topic: PRODUCT_DISCONTINUED
|
|
142
|
+
useCase: SendProductDiscontinuedNotification
|
|
143
|
+
fields:
|
|
144
|
+
- name: productId
|
|
145
|
+
type: String
|
|
146
|
+
- name: discontinuedAt
|
|
147
|
+
type: LocalDateTime
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
2
|
+
# product — Domain Model (Core Domain)
|
|
3
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
4
|
+
# Manages the product catalog and categories. Two aggregates with separate
|
|
5
|
+
# lifecycles. Tests: multi-aggregate endpoints fix, VO-unwrap in raise(),
|
|
6
|
+
# transitions + triggers, cross-aggregate reference.
|
|
7
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
8
|
+
|
|
9
|
+
aggregates:
|
|
10
|
+
|
|
11
|
+
# ════════════════════════════════════════════════════════════════════════════
|
|
12
|
+
# Aggregate: Product
|
|
13
|
+
# ════════════════════════════════════════════════════════════════════════════
|
|
14
|
+
- name: Product
|
|
15
|
+
entities:
|
|
16
|
+
- name: Product
|
|
17
|
+
isRoot: true
|
|
18
|
+
tableName: products
|
|
19
|
+
audit:
|
|
20
|
+
enabled: true
|
|
21
|
+
trackUser: true
|
|
22
|
+
fields:
|
|
23
|
+
- name: id
|
|
24
|
+
type: String
|
|
25
|
+
- name: name
|
|
26
|
+
type: String
|
|
27
|
+
validations:
|
|
28
|
+
- type: NotBlank
|
|
29
|
+
message: "Product name is required"
|
|
30
|
+
- name: description
|
|
31
|
+
type: String
|
|
32
|
+
- name: price
|
|
33
|
+
type: Price
|
|
34
|
+
validations:
|
|
35
|
+
- type: NotNull
|
|
36
|
+
message: "Price is required"
|
|
37
|
+
- name: categoryId
|
|
38
|
+
type: String
|
|
39
|
+
reference:
|
|
40
|
+
aggregate: Category
|
|
41
|
+
validations:
|
|
42
|
+
- type: NotBlank
|
|
43
|
+
message: "Category ID is required"
|
|
44
|
+
- name: status
|
|
45
|
+
type: ProductStatus
|
|
46
|
+
readOnly: true
|
|
47
|
+
- name: publishedAt
|
|
48
|
+
type: LocalDateTime
|
|
49
|
+
readOnly: true
|
|
50
|
+
|
|
51
|
+
valueObjects:
|
|
52
|
+
- name: Price
|
|
53
|
+
fields:
|
|
54
|
+
- name: amount
|
|
55
|
+
type: BigDecimal
|
|
56
|
+
- name: currency
|
|
57
|
+
type: String
|
|
58
|
+
methods:
|
|
59
|
+
- name: isPositive
|
|
60
|
+
returnType: boolean
|
|
61
|
+
parameters: []
|
|
62
|
+
body: "return this.amount != null && this.amount.compareTo(java.math.BigDecimal.ZERO) > 0;"
|
|
63
|
+
|
|
64
|
+
enums:
|
|
65
|
+
- name: ProductStatus
|
|
66
|
+
initialValue: DRAFT
|
|
67
|
+
transitions:
|
|
68
|
+
- from: DRAFT
|
|
69
|
+
to: PUBLISHED
|
|
70
|
+
method: publish
|
|
71
|
+
- from: PUBLISHED
|
|
72
|
+
to: DISCONTINUED
|
|
73
|
+
method: discontinue
|
|
74
|
+
- from: DRAFT
|
|
75
|
+
to: DISCONTINUED
|
|
76
|
+
method: discontinue
|
|
77
|
+
values:
|
|
78
|
+
- DRAFT
|
|
79
|
+
- PUBLISHED
|
|
80
|
+
- DISCONTINUED
|
|
81
|
+
|
|
82
|
+
events:
|
|
83
|
+
# ProductPublishedEvent — triggered by publish transition.
|
|
84
|
+
# price: BigDecimal tests VO-unwrap: entity.price is Price, event expects BigDecimal
|
|
85
|
+
# → generator should emit: this.getPrice().getAmount()
|
|
86
|
+
- name: ProductPublishedEvent
|
|
87
|
+
topic: PRODUCT_PUBLISHED
|
|
88
|
+
triggers:
|
|
89
|
+
- publish
|
|
90
|
+
fields:
|
|
91
|
+
- name: productId
|
|
92
|
+
type: String
|
|
93
|
+
- name: name
|
|
94
|
+
type: String
|
|
95
|
+
- name: price
|
|
96
|
+
type: BigDecimal
|
|
97
|
+
- name: publishedAt
|
|
98
|
+
type: LocalDateTime
|
|
99
|
+
|
|
100
|
+
# ProductDiscontinuedEvent — triggered by discontinue transition
|
|
101
|
+
- name: ProductDiscontinuedEvent
|
|
102
|
+
topic: PRODUCT_DISCONTINUED
|
|
103
|
+
triggers:
|
|
104
|
+
- discontinue
|
|
105
|
+
fields:
|
|
106
|
+
- name: productId
|
|
107
|
+
type: String
|
|
108
|
+
- name: discontinuedAt
|
|
109
|
+
type: LocalDateTime
|
|
110
|
+
|
|
111
|
+
# ════════════════════════════════════════════════════════════════════════════
|
|
112
|
+
# Aggregate: Category
|
|
113
|
+
# ════════════════════════════════════════════════════════════════════════════
|
|
114
|
+
- name: Category
|
|
115
|
+
entities:
|
|
116
|
+
- name: Category
|
|
117
|
+
isRoot: true
|
|
118
|
+
tableName: categories
|
|
119
|
+
audit:
|
|
120
|
+
enabled: true
|
|
121
|
+
trackUser: false
|
|
122
|
+
fields:
|
|
123
|
+
- name: id
|
|
124
|
+
type: String
|
|
125
|
+
- name: name
|
|
126
|
+
type: String
|
|
127
|
+
validations:
|
|
128
|
+
- type: NotBlank
|
|
129
|
+
message: "Category name is required"
|
|
130
|
+
- name: description
|
|
131
|
+
type: String
|
|
132
|
+
|
|
133
|
+
events:
|
|
134
|
+
# CategoryCreatedEvent — no triggers, raise() called manually in the handler
|
|
135
|
+
- name: CategoryCreatedEvent
|
|
136
|
+
fields:
|
|
137
|
+
- name: categoryId
|
|
138
|
+
type: String
|
|
139
|
+
- name: name
|
|
140
|
+
type: String
|
|
141
|
+
|
|
142
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
143
|
+
# Declarative REST endpoints
|
|
144
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
145
|
+
# Multi-aggregate: Product ops are classified to Product, Category ops to
|
|
146
|
+
# Category. Validates the cross-aggregate classification fix.
|
|
147
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
148
|
+
endpoints:
|
|
149
|
+
basePath: /
|
|
150
|
+
versions:
|
|
151
|
+
- version: v1
|
|
152
|
+
operations:
|
|
153
|
+
# ── Product ───────────────────────────────────────────────────────────
|
|
154
|
+
- useCase: CreateProduct
|
|
155
|
+
method: POST
|
|
156
|
+
path: /products
|
|
157
|
+
- useCase: GetProduct
|
|
158
|
+
method: GET
|
|
159
|
+
path: /products/{id}
|
|
160
|
+
- useCase: FindAllProducts
|
|
161
|
+
method: GET
|
|
162
|
+
path: /products
|
|
163
|
+
- useCase: UpdateProduct
|
|
164
|
+
method: PUT
|
|
165
|
+
path: /products/{id}
|
|
166
|
+
- useCase: PublishProduct
|
|
167
|
+
method: PUT
|
|
168
|
+
path: /products/{id}/publish
|
|
169
|
+
- useCase: DiscontinueProduct
|
|
170
|
+
method: PUT
|
|
171
|
+
path: /products/{id}/discontinue
|
|
172
|
+
|
|
173
|
+
# ── Category ──────────────────────────────────────────────────────────
|
|
174
|
+
- useCase: CreateCategory
|
|
175
|
+
method: POST
|
|
176
|
+
path: /categories
|
|
177
|
+
- useCase: GetCategory
|
|
178
|
+
method: GET
|
|
179
|
+
path: /categories/{id}
|
|
180
|
+
- useCase: FindAllCategorys
|
|
181
|
+
method: GET
|
|
182
|
+
path: /categories
|
|
183
|
+
- useCase: UpdateCategory
|
|
184
|
+
method: PUT
|
|
185
|
+
path: /categories/{id}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
system:
|
|
2
|
+
name: product-catalog
|
|
3
|
+
groupId: com.example
|
|
4
|
+
javaVersion: 21
|
|
5
|
+
springBootVersion: 3.5.5
|
|
6
|
+
database: postgresql
|
|
7
|
+
|
|
8
|
+
messaging:
|
|
9
|
+
enabled: true
|
|
10
|
+
broker: kafka
|
|
11
|
+
kafka:
|
|
12
|
+
bootstrapServers: localhost:9092
|
|
13
|
+
defaultGroupId: product-catalog
|
|
14
|
+
topicPrefix: catalog
|
|
15
|
+
|
|
16
|
+
modules:
|
|
17
|
+
|
|
18
|
+
# ─────────────────────────────────────────────
|
|
19
|
+
# CATÁLOGO DE PRODUCTOS
|
|
20
|
+
# ─────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
- name: product
|
|
23
|
+
description: "Catálogo de productos y categorías. Gestiona el ciclo de vida de un producto (DRAFT → PUBLISHED → DISCONTINUED). Dos agregados: Product y Category."
|
|
24
|
+
exposes:
|
|
25
|
+
# ── Product ───────────────────────────────
|
|
26
|
+
- method: POST
|
|
27
|
+
path: /products
|
|
28
|
+
useCase: CreateProduct
|
|
29
|
+
description: "Crear nuevo producto en estado DRAFT"
|
|
30
|
+
- method: GET
|
|
31
|
+
path: /products/{id}
|
|
32
|
+
useCase: GetProduct
|
|
33
|
+
description: "Obtener detalle de un producto"
|
|
34
|
+
- method: GET
|
|
35
|
+
path: /products
|
|
36
|
+
useCase: FindAllProducts
|
|
37
|
+
description: "Listar productos con paginación"
|
|
38
|
+
- method: PUT
|
|
39
|
+
path: /products/{id}
|
|
40
|
+
useCase: UpdateProduct
|
|
41
|
+
description: "Actualizar datos de un producto en estado DRAFT"
|
|
42
|
+
- method: PUT
|
|
43
|
+
path: /products/{id}/publish
|
|
44
|
+
useCase: PublishProduct
|
|
45
|
+
description: "Publicar un producto: DRAFT → PUBLISHED. Emite ProductPublishedEvent."
|
|
46
|
+
- method: PUT
|
|
47
|
+
path: /products/{id}/discontinue
|
|
48
|
+
useCase: DiscontinueProduct
|
|
49
|
+
description: "Discontinuar un producto: PUBLISHED/DRAFT → DISCONTINUED"
|
|
50
|
+
# ── Category ──────────────────────────────
|
|
51
|
+
- method: POST
|
|
52
|
+
path: /categories
|
|
53
|
+
useCase: CreateCategory
|
|
54
|
+
description: "Crear nueva categoría de productos"
|
|
55
|
+
- method: GET
|
|
56
|
+
path: /categories/{id}
|
|
57
|
+
useCase: GetCategory
|
|
58
|
+
description: "Obtener detalle de una categoría"
|
|
59
|
+
- method: GET
|
|
60
|
+
path: /categories
|
|
61
|
+
useCase: FindAllCategorys
|
|
62
|
+
description: "Listar categorías con paginación"
|
|
63
|
+
- method: PUT
|
|
64
|
+
path: /categories/{id}
|
|
65
|
+
useCase: UpdateCategory
|
|
66
|
+
description: "Actualizar nombre/descripción de una categoría"
|
|
67
|
+
|
|
68
|
+
# ─────────────────────────────────────────────
|
|
69
|
+
# NOTIFICACIONES
|
|
70
|
+
# ─────────────────────────────────────────────
|
|
71
|
+
|
|
72
|
+
- name: notification
|
|
73
|
+
description: "Despacha notificaciones a usuarios por EMAIL, SMS o PUSH. Reacciona a eventos del dominio product para informar a usuarios interesados."
|
|
74
|
+
exposes:
|
|
75
|
+
- method: POST
|
|
76
|
+
path: /notifications
|
|
77
|
+
useCase: CreateNotification
|
|
78
|
+
description: "Crear y encolar una notificación manualmente"
|
|
79
|
+
- method: GET
|
|
80
|
+
path: /notifications/{id}
|
|
81
|
+
useCase: GetNotification
|
|
82
|
+
description: "Obtener estado de una notificación"
|
|
83
|
+
- method: GET
|
|
84
|
+
path: /notifications
|
|
85
|
+
useCase: FindAllNotifications
|
|
86
|
+
description: "Listar notificaciones con paginación"
|
|
87
|
+
- method: DELETE
|
|
88
|
+
path: /notifications/{id}
|
|
89
|
+
useCase: DeleteNotification
|
|
90
|
+
description: "Eliminar lógicamente una notificación (soft delete)"
|
|
91
|
+
- method: PUT
|
|
92
|
+
path: /notifications/{id}/read
|
|
93
|
+
useCase: MarkNotificationRead
|
|
94
|
+
description: "Marcar notificación como leída"
|
|
95
|
+
|
|
96
|
+
integrations:
|
|
97
|
+
async:
|
|
98
|
+
# Producto publicado → notification envía alerta a usuarios suscritos
|
|
99
|
+
- event: ProductPublishedEvent
|
|
100
|
+
producer: product
|
|
101
|
+
topic: PRODUCT_PUBLISHED
|
|
102
|
+
consumers:
|
|
103
|
+
- module: notification
|
|
104
|
+
useCase: SendProductPublishedNotification
|
|
105
|
+
|
|
106
|
+
# Producto discontinuado → notification informa aos usuarios
|
|
107
|
+
- event: ProductDiscontinuedEvent
|
|
108
|
+
producer: product
|
|
109
|
+
topic: PRODUCT_DISCONTINUED
|
|
110
|
+
consumers:
|
|
111
|
+
- module: notification
|
|
112
|
+
useCase: SendProductDiscontinuedNotification
|