Skip to content

Commit efd9436

Browse files
feat(retentions): agregar métodos para borradores (#7)
* chore(retentions): add new retentions method for support drafts * chore: keep retention draft methods unreleased --------- Co-authored-by: javorosas <javier.rosasb@gmail.com>
1 parent 9a53e6b commit efd9436

5 files changed

Lines changed: 150 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## Unreleased
9+
10+
### Added
11+
12+
- Add draft support methods for retentions: `retentions.updateDraft(String id, Map<String, Object> data)`, `retentions.copyToDraft(String id)`, `retentions.stampDraft(String id)`, and `retentions.cancel(String id)`.
13+
814
## [1.3.0] - 2026-06-07
915

1016
### Added

README.es.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@ Maven:
2929
<dependency>
3030
<groupId>io.facturapi</groupId>
3131
<artifactId>facturapi-java</artifactId>
32-
<version>1.1.0</version>
32+
<version>1.3.0</version>
3333
</dependency>
3434
```
3535

3636
Gradle:
3737

3838
```gradle
39-
implementation("io.facturapi:facturapi-java:1.1.0")
39+
implementation("io.facturapi:facturapi-java:1.3.0")
4040
```
4141

4242
## Inicio rápido

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@ Maven:
2929
<dependency>
3030
<groupId>io.facturapi</groupId>
3131
<artifactId>facturapi-java</artifactId>
32-
<version>1.1.0</version>
32+
<version>1.3.0</version>
3333
</dependency>
3434
```
3535

3636
Gradle:
3737

3838
```gradle
39-
implementation("io.facturapi:facturapi-java:1.1.0")
39+
implementation("io.facturapi:facturapi-java:1.3.0")
4040
```
4141

4242
## Quickstart

src/main/java/io/facturapi/resources/RetentionsResource.java

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public RetentionsResource(FacturapiHttpClient client) {
1919
}
2020

2121
/**
22-
* Creates a new valid retention (CFDI).
22+
* Creates a new retention (CFDI).
2323
*
2424
* @param data Retention payload.
2525
* @return Created retention.
@@ -63,6 +63,51 @@ public Retention cancel(String id, Map<String, ?> params) {
6363
return delete("/retentions/" + id, params, Retention.class);
6464
}
6565

66+
/**
67+
* Cancels a retention, or deletes it directly when it is a draft.
68+
*
69+
* @param id Retention id.
70+
* @return Canceled or deleted retention.
71+
* @see <a href="https://docs.facturapi.io/api#operation/cancelRetention">API reference</a>
72+
*/
73+
public Retention cancel(String id) {
74+
return delete("/retentions/" + id, null, Retention.class);
75+
}
76+
77+
/**
78+
* Updates a draft retention.
79+
*
80+
* @param id Retention id.
81+
* @param data Retention updates.
82+
* @return Updated draft retention.
83+
* @see <a href="https://docs.facturapi.io/api#operation/updateDraftRetention">API reference</a>
84+
*/
85+
public Retention updateDraft(String id, Map<String, Object> data) {
86+
return put("/retentions/" + id, data, null, Retention.class);
87+
}
88+
89+
/**
90+
* Creates a draft copy from an existing retention.
91+
*
92+
* @param id Retention id.
93+
* @return Draft retention.
94+
* @see <a href="https://docs.facturapi.io/api#operation/copyToDraftRetention">API reference</a>
95+
*/
96+
public Retention copyToDraft(String id) {
97+
return post("/retentions/" + id + "/copy", null, null, Retention.class);
98+
}
99+
100+
/**
101+
* Stamps an existing draft retention.
102+
*
103+
* @param id Retention id.
104+
* @return Stamped retention.
105+
* @see <a href="https://docs.facturapi.io/api#operation/stampDraftRetention">API reference</a>
106+
*/
107+
public Retention stampDraft(String id) {
108+
return post("/retentions/" + id + "/stamp", null, null, Retention.class);
109+
}
110+
66111
/**
67112
* Sends the retention to the customer's email.
68113
*

src/test/java/io/facturapi/FacturapiResourcesTest.java

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,100 @@ void invoicePdfCanBeStreamed() throws Exception {
112112
assertEquals("/v2/invoices/inv_1/pdf", request.uri().getPath());
113113
}
114114

115+
@Test
116+
void retentionDraftCreateSupportsDraftStatus() {
117+
StubHttpClient httpClient = new StubHttpClient();
118+
httpClient.enqueueJson(200, "{\"id\":\"ret_draft_1\",\"status\":\"draft\"}");
119+
120+
Facturapi sdk = new Facturapi(
121+
FacturapiConfig.builder("sk_test")
122+
.httpClient(httpClient.client())
123+
.build()
124+
);
125+
126+
Map<String, Object> payload = new java.util.HashMap<>();
127+
payload.put("status", "draft");
128+
payload.put("customer", null);
129+
130+
var response = sdk.retentions().create(payload);
131+
132+
assertEquals("ret_draft_1", response.getId());
133+
assertEquals("draft", response.getStatus());
134+
var request = httpClient.requests().get(0);
135+
assertEquals("POST", request.method());
136+
assertEquals("/v2/retentions", request.uri().getPath());
137+
assertTrue(request.bodyUtf8().contains("\"status\":\"draft\""));
138+
assertTrue(request.bodyUtf8().contains("\"customer\":null"));
139+
}
140+
141+
@Test
142+
void retentionDraftUpdateUsesExpectedPath() {
143+
StubHttpClient httpClient = new StubHttpClient();
144+
httpClient.enqueueJson(200, "{\"id\":\"ret_1\",\"folio_int\":\"R-2026-001\"}");
145+
146+
Facturapi sdk = new Facturapi(
147+
FacturapiConfig.builder("sk_test")
148+
.httpClient(httpClient.client())
149+
.build()
150+
);
151+
152+
var response = sdk.retentions().updateDraft("ret_1", Map.of("folio_int", "R-2026-001"));
153+
154+
assertEquals("ret_1", response.getId());
155+
assertEquals("R-2026-001", response.getFolioInt());
156+
var request = httpClient.requests().get(0);
157+
assertEquals("PUT", request.method());
158+
assertEquals("/v2/retentions/ret_1", request.uri().getPath());
159+
assertTrue(request.bodyUtf8().contains("\"folio_int\":\"R-2026-001\""));
160+
}
161+
162+
@Test
163+
void retentionDraftCopyAndStampUseExpectedPaths() {
164+
StubHttpClient httpClient = new StubHttpClient();
165+
httpClient.enqueueJson(200, "{\"id\":\"ret_copy_1\",\"status\":\"draft\"}");
166+
httpClient.enqueueJson(200, "{\"id\":\"ret_1\",\"status\":\"valid\"}");
167+
168+
Facturapi sdk = new Facturapi(
169+
FacturapiConfig.builder("sk_test")
170+
.httpClient(httpClient.client())
171+
.build()
172+
);
173+
174+
var draft = sdk.retentions().copyToDraft("ret_1");
175+
var stamped = sdk.retentions().stampDraft("ret_copy_1");
176+
177+
assertEquals("ret_copy_1", draft.getId());
178+
assertEquals("ret_1", stamped.getId());
179+
assertEquals("POST", httpClient.requests().get(0).method());
180+
assertEquals("/v2/retentions/ret_1/copy", httpClient.requests().get(0).uri().getPath());
181+
assertEquals("POST", httpClient.requests().get(1).method());
182+
assertEquals("/v2/retentions/ret_copy_1/stamp", httpClient.requests().get(1).uri().getPath());
183+
}
184+
185+
@Test
186+
void retentionDraftCancelAndListUseExpectedPaths() {
187+
StubHttpClient httpClient = new StubHttpClient();
188+
httpClient.enqueueJson(200, "{\"id\":\"ret_draft_1\",\"status\":\"canceled\"}");
189+
httpClient.enqueueJson(200, "{\"data\":[{\"id\":\"ret_draft_2\",\"status\":\"draft\"}]}");
190+
191+
Facturapi sdk = new Facturapi(
192+
FacturapiConfig.builder("sk_test")
193+
.httpClient(httpClient.client())
194+
.build()
195+
);
196+
197+
var deleted = sdk.retentions().cancel("ret_draft_1");
198+
var drafts = sdk.retentions().list(Map.of("status", "draft"));
199+
200+
assertEquals("ret_draft_1", deleted.getId());
201+
assertEquals(1, drafts.getData().size());
202+
assertEquals("DELETE", httpClient.requests().get(0).method());
203+
assertEquals("/v2/retentions/ret_draft_1", httpClient.requests().get(0).uri().getPath());
204+
var listRequest = httpClient.requests().get(1);
205+
assertEquals("GET", listRequest.method());
206+
assertEquals("/v2/retentions?status=draft", listRequest.uri().getPath() + "?" + listRequest.uri().getQuery());
207+
}
208+
115209
@Test
116210
void organizationUploadsAcceptBytes() {
117211
StubHttpClient httpClient = new StubHttpClient();

0 commit comments

Comments
 (0)