Skip to content

Commit 2662757

Browse files
committed
FINERACT-2246: New command processing - document management
1 parent f5951f1 commit 2662757

File tree

111 files changed

+3413
-2839
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

111 files changed

+3413
-2839
lines changed

config/docker/env/fineract-common.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ FINERACT_MANAGEMENT_ENDPOINT_WEB_EXPOSURE_INCLUDE=health,info,prometheus
5454
FINERACT_MANAGEMENT_METRICS_TAGS_APPLICATION=fineract
5555
FINERACT_REMOTE_JOB_MESSAGE_HANDLER_SPRING_EVENTS_ENABLED=true
5656
FINERACT_INSECURE_HTTP_CLIENT=true
57+
FINERACT_CONTENT_FILESYSTEM_ROOT_FOLDER=/tmp
5758
SPRING_PROFILES_ACTIVE=test,diagnostics
5859
OTEL_SERVICE_NAME=fineract
5960
JAVA_TOOL_OPTIONS="-Xmx1G -XX:MinRAMPercentage=25 -XX:MaxRAMPercentage=80 -XX:TieredStopAtLevel=1 -XX:+UseContainerSupport -XX:+UseStringDeduplication --add-exports=java.naming/com.sun.jndi.ldap=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.security=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.management/javax.management=ALL-UNNAMED --add-opens=java.naming/javax.naming=ALL-UNNAMED"

fineract-client-feign/src/main/java/org/apache/fineract/client/feign/services/DocumentsApiFixed.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@
2222
import feign.RequestLine;
2323
import feign.Response;
2424
import java.util.List;
25-
import org.apache.fineract.client.models.DeleteEntityTypeEntityIdDocumentsResponse;
25+
import org.apache.fineract.client.models.DocumentCreateResponse;
2626
import org.apache.fineract.client.models.DocumentData;
27-
import org.apache.fineract.client.models.PostEntityTypeEntityIdDocumentsResponse;
28-
import org.apache.fineract.client.models.PutEntityTypeEntityIdDocumentsResponse;
27+
import org.apache.fineract.client.models.DocumentDeleteResponse;
28+
import org.apache.fineract.client.models.DocumentUpdateResponse;
2929

3030
/**
3131
* This class was originally generated by <a href="https://openapi-generator.tech">OpenAPI Generator</a>, but then had
@@ -44,7 +44,7 @@ public interface DocumentsApiFixed {
4444
* @return PostEntityTypeEntityIdDocumentsResponse
4545
*/
4646
@RequestLine("POST /v1/{entityType}/{entityId}/documents")
47-
PostEntityTypeEntityIdDocumentsResponse createDocument(@Param("entityType") String entityType, @Param("entityId") Long entityId,
47+
DocumentCreateResponse createDocument(@Param("entityType") String entityType, @Param("entityId") Long entityId,
4848
org.apache.fineract.client.feign.FineractMultipartEncoder.MultipartData multipartData);
4949

5050
/**
@@ -59,7 +59,7 @@ PostEntityTypeEntityIdDocumentsResponse createDocument(@Param("entityType") Stri
5959
* @return DeleteEntityTypeEntityIdDocumentsResponse
6060
*/
6161
@RequestLine("DELETE /v1/{entityType}/{entityId}/documents/{documentId}")
62-
DeleteEntityTypeEntityIdDocumentsResponse deleteDocument(@Param("entityType") String entityType, @Param("entityId") Long entityId,
62+
DocumentDeleteResponse deleteDocument(@Param("entityType") String entityType, @Param("entityId") Long entityId,
6363
@Param("documentId") Long documentId);
6464

6565
/**
@@ -114,6 +114,6 @@ DocumentData getDocument(@Param("entityType") String entityType, @Param("entityI
114114
* @return PutEntityTypeEntityIdDocumentsResponse
115115
*/
116116
@RequestLine("PUT /v1/{entityType}/{entityId}/documents/{documentId}")
117-
PutEntityTypeEntityIdDocumentsResponse updateDocument(@Param("entityType") String entityType, @Param("entityId") Long entityId,
117+
DocumentUpdateResponse updateDocument(@Param("entityType") String entityType, @Param("entityId") Long entityId,
118118
@Param("documentId") Long documentId, org.apache.fineract.client.feign.FineractMultipartEncoder.MultipartData multipartData);
119119
}

fineract-client-feign/src/test/java/org/apache/fineract/client/services/DocumentsApiFixedIntegrationTest.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
import java.util.concurrent.TimeUnit;
3636
import org.apache.fineract.client.feign.FineractFeignClientConfig;
3737
import org.apache.fineract.client.feign.services.DocumentsApiFixed;
38-
import org.apache.fineract.client.models.DeleteEntityTypeEntityIdDocumentsResponse;
3938
import org.apache.fineract.client.models.DocumentData;
4039
import org.junit.jupiter.api.AfterEach;
4140
import org.junit.jupiter.api.BeforeEach;
@@ -149,7 +148,7 @@ void testDeleteDocument() {
149148
.willReturn(aResponse().withStatus(200).withHeader("Content-Type", "application/json").withBody(responseBody)));
150149

151150
DocumentsApiFixed api = config.createClient(DocumentsApiFixed.class);
152-
DeleteEntityTypeEntityIdDocumentsResponse response = api.deleteDocument("clients", 123L, 456L);
151+
var response = api.deleteDocument("clients", 123L, 456L);
153152

154153
assertThat(response).isNotNull();
155154
assertThat(response.getResourceId()).isEqualTo(456L);
@@ -162,7 +161,7 @@ void testDeleteDocumentForLoan() {
162161
.willReturn(aResponse().withStatus(200).withHeader("Content-Type", "application/json").withBody(responseBody)));
163162

164163
DocumentsApiFixed api = config.createClient(DocumentsApiFixed.class);
165-
DeleteEntityTypeEntityIdDocumentsResponse response = api.deleteDocument("loans", 789L, 999L);
164+
var response = api.deleteDocument("loans", 789L, 999L);
166165

167166
assertThat(response).isNotNull();
168167
assertThat(response.getResourceId()).isEqualTo(999L);

fineract-client/src/main/java/org/apache/fineract/client/services/DocumentsApiFixed.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@
2020

2121
import java.util.List;
2222
import okhttp3.ResponseBody;
23-
import org.apache.fineract.client.models.DeleteEntityTypeEntityIdDocumentsResponse;
23+
import org.apache.fineract.client.models.DocumentCreateResponse;
2424
import org.apache.fineract.client.models.DocumentData;
25-
import org.apache.fineract.client.models.PostEntityTypeEntityIdDocumentsResponse;
26-
import org.apache.fineract.client.models.PutEntityTypeEntityIdDocumentsResponse;
25+
import org.apache.fineract.client.models.DocumentDeleteResponse;
26+
import org.apache.fineract.client.models.DocumentUpdateResponse;
2727
import retrofit2.Call;
2828
import retrofit2.http.DELETE;
2929
import retrofit2.http.GET;
@@ -54,7 +54,7 @@ public interface DocumentsApiFixed {
5454
*/
5555
@retrofit2.http.Multipart
5656
@POST("v1/{entityType}/{entityId}/documents")
57-
Call<PostEntityTypeEntityIdDocumentsResponse> createDocument(@retrofit2.http.Path("entityType") String entityType,
57+
Call<DocumentCreateResponse> createDocument(@retrofit2.http.Path("entityType") String entityType,
5858
@retrofit2.http.Path("entityId") Long entityId, @retrofit2.http.Part okhttp3.MultipartBody.Part file,
5959
@retrofit2.http.Part("name") String name, @retrofit2.http.Part("description") String description);
6060

@@ -70,7 +70,7 @@ Call<PostEntityTypeEntityIdDocumentsResponse> createDocument(@retrofit2.http.Pat
7070
* @return Call&lt;DeleteEntityTypeEntityIdDocumentsResponse&gt;
7171
*/
7272
@DELETE("v1/{entityType}/{entityId}/documents/{documentId}")
73-
Call<DeleteEntityTypeEntityIdDocumentsResponse> deleteDocument(@retrofit2.http.Path("entityType") String entityType,
73+
Call<DocumentDeleteResponse> deleteDocument(@retrofit2.http.Path("entityType") String entityType,
7474
@retrofit2.http.Path("entityId") Long entityId, @retrofit2.http.Path("documentId") Long documentId);
7575

7676
/**
@@ -139,7 +139,7 @@ Call<List<DocumentData>> retrieveAllDocuments(@retrofit2.http.Path("entityType")
139139
*/
140140
@retrofit2.http.Multipart
141141
@PUT("v1/{entityType}/{entityId}/documents/{documentId}")
142-
Call<PutEntityTypeEntityIdDocumentsResponse> updateDocument(@retrofit2.http.Path("entityType") String entityType,
142+
Call<DocumentUpdateResponse> updateDocument(@retrofit2.http.Path("entityType") String entityType,
143143
@retrofit2.http.Path("entityId") Long entityId, @retrofit2.http.Path("documentId") Long documentId,
144144
@retrofit2.http.Part okhttp3.MultipartBody.Part file, @retrofit2.http.Part("name") String name,
145145
@retrofit2.http.Part("description") String description);

fineract-command/src/main/java/org/apache/fineract/command/implementation/DefaultCommandAuditor.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,16 @@ void onStartup() {
139139
@Retry(name = "commandAuditFallback", fallbackMethod = "fatal")
140140
@SuppressWarnings("UnusedMethod")
141141
private void fallback(Command<?> command, Throwable t) throws Exception {
142+
if (Boolean.TRUE.equals(properties.getFileDeadLetterQueueEnabled())) {
143+
fallback(command, null, t);
144+
} else {
145+
fatal(command, t);
146+
}
147+
}
148+
149+
@Retry(name = "commandAuditFallback", fallbackMethod = "fatal")
150+
@SuppressWarnings("UnusedMethod")
151+
private void fallback(Command<?> command, Object response, Throwable t) throws Exception {
142152
if (Boolean.TRUE.equals(properties.getFileDeadLetterQueueEnabled())) {
143153
setError(command, t);
144154
write(command);
@@ -149,6 +159,11 @@ private void fallback(Command<?> command, Throwable t) throws Exception {
149159

150160
@SuppressWarnings("UnusedMethod")
151161
private void fatal(Command<?> command, Throwable t) {
162+
fatal(command, null, t);
163+
}
164+
165+
@SuppressWarnings("UnusedMethod")
166+
private void fatal(Command<?> command, Object response, Throwable t) {
152167
// note: last line of defense; if this fails then all is lost
153168
setError(command, t);
154169
log.error("Command audit error: {}", command, t);

fineract-core/src/main/java/org/apache/fineract/infrastructure/bulkimport/service/BulkImportWorkbookService.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,10 @@
1818
*/
1919
package org.apache.fineract.infrastructure.bulkimport.service;
2020

21-
import jakarta.ws.rs.core.Response;
2221
import java.io.InputStream;
2322
import java.util.Collection;
2423
import org.apache.fineract.infrastructure.bulkimport.data.GlobalEntityType;
2524
import org.apache.fineract.infrastructure.bulkimport.data.ImportData;
26-
import org.apache.fineract.infrastructure.documentmanagement.data.DocumentData;
2725
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
2826

2927
public interface BulkImportWorkbookService {
@@ -32,9 +30,4 @@ Long importWorkbook(String entityType, InputStream inputStream, FormDataContentD
3230
String dateFormat);
3331

3432
Collection<ImportData> getImports(GlobalEntityType type);
35-
36-
DocumentData getOutputTemplateLocation(String importDocumentId);
37-
38-
Response getOutputTemplate(String importDocumentId);
39-
4033
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.fineract.infrastructure.documentmanagement.adapter;
20+
21+
import java.io.Serial;
22+
import java.io.Serializable;
23+
import java.util.Optional;
24+
import lombok.AllArgsConstructor;
25+
import lombok.Builder;
26+
import lombok.Data;
27+
import lombok.NoArgsConstructor;
28+
29+
// NOTE: this is a trick to decouple the entity image IDs from the image service
30+
@Deprecated
31+
public interface EntityImageIdAdapter {
32+
33+
boolean accept(String entityType);
34+
35+
Optional<ImageIdResult> get(Long entityId);
36+
37+
default void set(Long entityId) {
38+
set(entityId, null);
39+
}
40+
41+
void set(Long entityId, Long imageId);
42+
43+
@Builder
44+
@Data
45+
@NoArgsConstructor
46+
@AllArgsConstructor
47+
class ImageIdResult implements Serializable {
48+
49+
@Serial
50+
private static final long serialVersionUID = 1L;
51+
52+
private Long id;
53+
private String displayName;
54+
}
55+
}

fineract-core/src/main/java/org/apache/fineract/organisation/monetary/handler/CurrencyUpdateCommandHandler.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ public class CurrencyUpdateCommandHandler implements CommandHandler<CurrencyUpda
4040
@Transactional
4141
@Override
4242
public CurrencyUpdateResponse handle(final Command<CurrencyUpdateRequest> command) {
43-
// NOTE: fallback method needs to be in the same class
4443
return writePlatformService.updateAllowedCurrencies(command.getPayload());
4544
}
4645

fineract-core/src/main/java/org/apache/fineract/organisation/staff/domain/Staff.java

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import jakarta.persistence.Entity;
2323
import jakarta.persistence.JoinColumn;
2424
import jakarta.persistence.ManyToOne;
25-
import jakarta.persistence.OneToOne;
2625
import jakarta.persistence.Table;
2726
import jakarta.persistence.UniqueConstraint;
2827
import java.time.LocalDate;
@@ -33,7 +32,6 @@
3332
import org.apache.fineract.infrastructure.core.api.JsonCommand;
3433
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
3534
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
36-
import org.apache.fineract.infrastructure.documentmanagement.domain.Image;
3735
import org.apache.fineract.organisation.office.domain.Office;
3836

3937
@Getter
@@ -81,9 +79,8 @@ public class Staff extends AbstractPersistableCustom<Long> {
8179
@JoinColumn(name = "organisational_role_parent_staff_id")
8280
private Staff organisationalRoleParentStaff;
8381

84-
@OneToOne(optional = true)
85-
@JoinColumn(name = "image_id")
86-
private Image image;
82+
@Column(name = "image_id")
83+
private Long imageId;
8784

8885
public static Staff fromJson(final Office staffOffice, final JsonCommand command) {
8986

@@ -262,8 +259,4 @@ public Office office() {
262259
return this.office;
263260
}
264261

265-
public void setImage(Image image) {
266-
this.image = image;
267-
}
268-
269262
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.fineract.portfolio.client.adapter;
20+
21+
import java.util.Optional;
22+
import lombok.RequiredArgsConstructor;
23+
import lombok.extern.slf4j.Slf4j;
24+
import org.apache.fineract.infrastructure.documentmanagement.adapter.EntityImageIdAdapter;
25+
import org.apache.fineract.portfolio.client.domain.ClientRepository;
26+
import org.springframework.stereotype.Component;
27+
28+
@Slf4j
29+
@RequiredArgsConstructor
30+
@Component
31+
@Deprecated
32+
final class ClientImageIdAdapter implements EntityImageIdAdapter {
33+
34+
private static final String ENTITY_TYPE = "clients";
35+
36+
private final ClientRepository repository;
37+
38+
@Override
39+
public boolean accept(String entityType) {
40+
return ENTITY_TYPE.equalsIgnoreCase(entityType);
41+
}
42+
43+
@Override
44+
public Optional<ImageIdResult> get(Long entityId) {
45+
return repository.findById(entityId)
46+
.map(client -> ImageIdResult.builder().id(client.getImageId()).displayName(client.getDisplayName()).build());
47+
}
48+
49+
@Override
50+
public void set(Long entityId, Long imageId) {
51+
if (imageId == null) {
52+
repository.removeImageId(entityId);
53+
} else {
54+
repository.updateByIdAndImageId(entityId, imageId);
55+
}
56+
}
57+
}

0 commit comments

Comments
 (0)