FINERACT-2239: New command processing - resource notes
This commit is contained in:
committed by
Aleksandar Vidakovic
parent
28f63cc20e
commit
02fb166b5b
@@ -16,8 +16,6 @@
|
||||
# under the License.
|
||||
#
|
||||
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
fineract:
|
||||
# user: "${FINERACT_USER}:${FINERACT_GROUP}"
|
||||
|
||||
+1
-1
@@ -56,4 +56,4 @@ FINERACT_REMOTE_JOB_MESSAGE_HANDLER_SPRING_EVENTS_ENABLED=true
|
||||
FINERACT_INSECURE_HTTP_CLIENT=true
|
||||
SPRING_PROFILES_ACTIVE=test,diagnostics
|
||||
OTEL_SERVICE_NAME=fineract
|
||||
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"
|
||||
JAVA_TOOL_OPTIONS=" -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5000 -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"
|
||||
|
||||
+9
-16
@@ -19,9 +19,12 @@
|
||||
package com.acme.fineract.portfolio.note.service;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.client.domain.Client;
|
||||
import org.apache.fineract.portfolio.note.data.NoteCreateRequest;
|
||||
import org.apache.fineract.portfolio.note.data.NoteCreateResponse;
|
||||
import org.apache.fineract.portfolio.note.data.NoteDeleteRequest;
|
||||
import org.apache.fineract.portfolio.note.data.NoteDeleteResponse;
|
||||
import org.apache.fineract.portfolio.note.data.NoteUpdateRequest;
|
||||
import org.apache.fineract.portfolio.note.data.NoteUpdateResponse;
|
||||
import org.apache.fineract.portfolio.note.service.NoteWritePlatformService;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
@@ -38,27 +41,17 @@ public class AcmeNoteWritePlatformService implements NoteWritePlatformService, I
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult createNote(JsonCommand command) {
|
||||
public NoteCreateResponse createNote(NoteCreateRequest request) {
|
||||
throw new UnsupportedOperationException("createNote() is not yet implemented.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createLoanTransactionNote(Long loanTransactionId, String note) {
|
||||
throw new UnsupportedOperationException("createLoanTransactionNote() is not yet implemented.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult updateNote(JsonCommand command) {
|
||||
public NoteUpdateResponse updateNote(NoteUpdateRequest request) {
|
||||
throw new UnsupportedOperationException("updateNote() is not yet implemented.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult deleteNote(JsonCommand command) {
|
||||
public NoteDeleteResponse deleteNote(NoteDeleteRequest request) {
|
||||
throw new UnsupportedOperationException("deleteNote() is not yet implemented.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createAndPersistClientNote(Client client, JsonCommand command) {
|
||||
log.warn("createAndPersistClientNote() is intentionally left empty and does nothing.");
|
||||
}
|
||||
}
|
||||
|
||||
-12
@@ -21,7 +21,6 @@ package com.acme.fineract.portfolio.note.starter;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.config.FineractProperties;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.infrastructure.core.service.database.RoutingDataSource;
|
||||
import org.apache.fineract.infrastructure.core.service.database.RoutingDataSourceServiceFactory;
|
||||
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
|
||||
@@ -29,7 +28,6 @@ import org.apache.fineract.portfolio.group.domain.GroupRepository;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||
import org.apache.fineract.portfolio.note.domain.NoteRepository;
|
||||
import org.apache.fineract.portfolio.note.serialization.NoteCommandFromApiJsonDeserializer;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
@@ -38,11 +36,6 @@ import org.springframework.jdbc.core.JdbcTemplate;
|
||||
public class TestDefaultConfiguration {
|
||||
// NOTE: unfortunately an abastract base class that contains all these mock functions won't work
|
||||
|
||||
@Bean
|
||||
public FromJsonHelper fromJsonHelper() {
|
||||
return mock(FromJsonHelper.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RoutingDataSourceServiceFactory routingDataSourceServiceFactory() {
|
||||
return mock(RoutingDataSourceServiceFactory.class);
|
||||
@@ -82,9 +75,4 @@ public class TestDefaultConfiguration {
|
||||
public LoanTransactionRepository loanTransactionRepository() {
|
||||
return mock(LoanTransactionRepository.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public NoteCommandFromApiJsonDeserializer fromApiJsonDeserializer(FromJsonHelper fromJsonHelper) {
|
||||
return new NoteCommandFromApiJsonDeserializer(fromJsonHelper);
|
||||
}
|
||||
}
|
||||
|
||||
-12
@@ -20,7 +20,6 @@ package com.acme.fineract.portfolio.note.starter;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.infrastructure.core.service.database.RoutingDataSource;
|
||||
import org.apache.fineract.infrastructure.core.service.database.RoutingDataSourceServiceFactory;
|
||||
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
|
||||
@@ -28,7 +27,6 @@ import org.apache.fineract.portfolio.group.domain.GroupRepository;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||
import org.apache.fineract.portfolio.note.domain.NoteRepository;
|
||||
import org.apache.fineract.portfolio.note.serialization.NoteCommandFromApiJsonDeserializer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
@@ -37,11 +35,6 @@ import org.springframework.jdbc.core.JdbcTemplate;
|
||||
public class TestOverrideConfiguration {
|
||||
// NOTE: unfortunately an abastract base class that contains all these mock functions won't work
|
||||
|
||||
@Bean
|
||||
public FromJsonHelper fromJsonHelper() {
|
||||
return mock(FromJsonHelper.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RoutingDataSourceServiceFactory routingDataSourceServiceFactory() {
|
||||
return mock(RoutingDataSourceServiceFactory.class);
|
||||
@@ -81,9 +74,4 @@ public class TestOverrideConfiguration {
|
||||
public LoanTransactionRepository loanTransactionRepository() {
|
||||
return mock(LoanTransactionRepository.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public NoteCommandFromApiJsonDeserializer fromApiJsonDeserializer(FromJsonHelper fromJsonHelper) {
|
||||
return new NoteCommandFromApiJsonDeserializer(fromJsonHelper);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ services:
|
||||
service: fineract
|
||||
ports:
|
||||
- "8443:8443"
|
||||
- "5000:5000"
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
|
||||
+6
-1
@@ -18,6 +18,8 @@
|
||||
*/
|
||||
package org.apache.fineract.infrastructure.cache.data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@@ -28,7 +30,10 @@ import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public final class CacheData {
|
||||
public final class CacheData implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private EnumOptionData cacheType;
|
||||
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.note.data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.apache.fineract.portfolio.note.domain.NoteType;
|
||||
|
||||
@Builder
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class NoteCreateRequest implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Hidden
|
||||
private Long resourceId;
|
||||
@Hidden
|
||||
private NoteType type;
|
||||
@Size(max = 1000, message = "{org.apache.fineract.portfolio.note.note.size}")
|
||||
@NotNull(message = "{org.apache.fineract.portfolio.note.note.not-null}")
|
||||
private String note;
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.note.data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Builder
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class NoteCreateResponse implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Long entityId;
|
||||
private Long officeId;
|
||||
private Long resourceId;
|
||||
}
|
||||
@@ -18,31 +18,37 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.note.data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.OffsetDateTime;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
|
||||
/**
|
||||
* Immutable data object represent note or case information about a client, loan or loan transaction.
|
||||
*/
|
||||
@Getter
|
||||
@Builder
|
||||
public class NoteData {
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class NoteData implements Serializable {
|
||||
|
||||
private final Long id;
|
||||
private final Long clientId;
|
||||
private final Long groupId;
|
||||
private final Long loanId;
|
||||
private final Long loanTransactionId;
|
||||
private final Long depositAccountId;
|
||||
private final Long savingAccountId;
|
||||
private final EnumOptionData noteType;
|
||||
private final String note;
|
||||
private final Long createdById;
|
||||
private final String createdByUsername;
|
||||
private final OffsetDateTime createdOn;
|
||||
private final Long updatedById;
|
||||
private final String updatedByUsername;
|
||||
private final OffsetDateTime updatedOn;
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Long id;
|
||||
private Long clientId;
|
||||
private Long groupId;
|
||||
private Long loanId;
|
||||
private Long loanTransactionId;
|
||||
private Long depositAccountId;
|
||||
private Long savingAccountId;
|
||||
private EnumOptionData noteType;
|
||||
private String note;
|
||||
private Long createdById;
|
||||
private String createdByUsername;
|
||||
private OffsetDateTime createdOn;
|
||||
private Long updatedById;
|
||||
private String updatedByUsername;
|
||||
private OffsetDateTime updatedOn;
|
||||
}
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.note.data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.apache.fineract.portfolio.note.domain.NoteType;
|
||||
|
||||
@Builder
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class NoteDeleteRequest implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Hidden
|
||||
private Long id;
|
||||
@Hidden
|
||||
private Long resourceId;
|
||||
@Hidden
|
||||
private NoteType type;
|
||||
}
|
||||
+4
-2
@@ -21,16 +21,18 @@ package org.apache.fineract.portfolio.note.data;
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Builder
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class NoteRequest implements Serializable {
|
||||
public class NoteDeleteResponse implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String note;
|
||||
private Long resourceId;
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.note.data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.apache.fineract.portfolio.note.domain.NoteType;
|
||||
|
||||
@Builder
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class NoteUpdateRequest implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Hidden
|
||||
private Long id;
|
||||
@Hidden
|
||||
private Long resourceId;
|
||||
@Hidden
|
||||
private NoteType type;
|
||||
@Size(max = 1000, message = "{org.apache.fineract.portfolio.note.note.size}")
|
||||
@NotNull(message = "{org.apache.fineract.portfolio.note.note.not-null}")
|
||||
private String note;
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.note.data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Builder
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class NoteUpdateResponse implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Long officeId;
|
||||
private Long resourceId;
|
||||
private Map<String, Object> changes;
|
||||
}
|
||||
+9
-10
@@ -18,19 +18,18 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.note.service;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.client.domain.Client;
|
||||
import org.apache.fineract.portfolio.note.data.NoteCreateRequest;
|
||||
import org.apache.fineract.portfolio.note.data.NoteCreateResponse;
|
||||
import org.apache.fineract.portfolio.note.data.NoteDeleteRequest;
|
||||
import org.apache.fineract.portfolio.note.data.NoteDeleteResponse;
|
||||
import org.apache.fineract.portfolio.note.data.NoteUpdateRequest;
|
||||
import org.apache.fineract.portfolio.note.data.NoteUpdateResponse;
|
||||
|
||||
public interface NoteWritePlatformService {
|
||||
|
||||
CommandProcessingResult createNote(JsonCommand command);
|
||||
NoteCreateResponse createNote(NoteCreateRequest request);
|
||||
|
||||
void createLoanTransactionNote(Long loanTransactionId, String note);
|
||||
NoteUpdateResponse updateNote(NoteUpdateRequest request);
|
||||
|
||||
CommandProcessingResult updateNote(JsonCommand command);
|
||||
|
||||
CommandProcessingResult deleteNote(JsonCommand command);
|
||||
|
||||
void createAndPersistClientNote(Client client, JsonCommand command);
|
||||
NoteDeleteResponse deleteNote(NoteDeleteRequest request);
|
||||
}
|
||||
|
||||
+8
-4
@@ -49,9 +49,11 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelation;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelationTypeEnum;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||
import org.apache.fineract.portfolio.loanaccount.repository.LoanBuyDownFeeBalanceRepository;
|
||||
import org.apache.fineract.portfolio.note.service.NoteWritePlatformService;
|
||||
import org.apache.fineract.portfolio.note.data.NoteCreateRequest;
|
||||
import org.apache.fineract.portfolio.note.domain.NoteType;
|
||||
import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
|
||||
import org.apache.fineract.portfolio.paymentdetail.service.PaymentDetailWritePlatformService;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Slf4j
|
||||
@@ -63,11 +65,11 @@ public class BuyDownFeeWritePlatformServiceImpl implements BuyDownFeePlatformSer
|
||||
private final LoanTransactionRepository loanTransactionRepository;
|
||||
private final PaymentDetailWritePlatformService paymentDetailWritePlatformService;
|
||||
private final LoanJournalEntryPoster loanJournalEntryPoster;
|
||||
private final NoteWritePlatformService noteWritePlatformService;
|
||||
private final ExternalIdFactory externalIdFactory;
|
||||
private final LoanBuyDownFeeBalanceRepository loanBuyDownFeeBalanceRepository;
|
||||
private final BusinessEventNotifierService businessEventNotifierService;
|
||||
private final CodeValueRepository codeValueRepository;
|
||||
private final ApplicationEventPublisher eventPublisher;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
@@ -108,7 +110,8 @@ public class BuyDownFeeWritePlatformServiceImpl implements BuyDownFeePlatformSer
|
||||
// Add note if provided
|
||||
final String noteText = command.stringValueOfParameterNamed("note");
|
||||
if (StringUtils.isNotBlank(noteText)) {
|
||||
noteWritePlatformService.createLoanTransactionNote(buyDownFeeTransaction.getId(), noteText);
|
||||
eventPublisher.publishEvent(NoteCreateRequest.builder().type(NoteType.LOAN_TRANSACTION)
|
||||
.resourceId(buyDownFeeTransaction.getId()).note(noteText).build());
|
||||
}
|
||||
|
||||
loanJournalEntryPoster.postJournalEntriesForLoanTransaction(buyDownFeeTransaction, false, false);
|
||||
@@ -177,7 +180,8 @@ public class BuyDownFeeWritePlatformServiceImpl implements BuyDownFeePlatformSer
|
||||
// Create a note if provided
|
||||
final String noteText = command.stringValueOfParameterNamed("note");
|
||||
if (StringUtils.isNotBlank(noteText)) {
|
||||
noteWritePlatformService.createLoanTransactionNote(savedBuyDownFeeAdjustment.getId(), noteText);
|
||||
eventPublisher.publishEvent(NoteCreateRequest.builder().type(NoteType.LOAN_TRANSACTION)
|
||||
.resourceId(savedBuyDownFeeAdjustment.getId()).note(noteText).build());
|
||||
}
|
||||
|
||||
loanJournalEntryPoster.postJournalEntriesForLoanTransaction(savedBuyDownFeeAdjustment, false, false);
|
||||
|
||||
+8
-4
@@ -48,9 +48,11 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelation;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelationTypeEnum;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||
import org.apache.fineract.portfolio.loanaccount.repository.LoanCapitalizedIncomeBalanceRepository;
|
||||
import org.apache.fineract.portfolio.note.service.NoteWritePlatformService;
|
||||
import org.apache.fineract.portfolio.note.data.NoteCreateRequest;
|
||||
import org.apache.fineract.portfolio.note.domain.NoteType;
|
||||
import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
|
||||
import org.apache.fineract.portfolio.paymentdetail.service.PaymentDetailWritePlatformService;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Slf4j
|
||||
@@ -62,7 +64,6 @@ public class CapitalizedIncomeWritePlatformServiceImpl implements CapitalizedInc
|
||||
private final LoanTransactionRepository loanTransactionRepository;
|
||||
private final PaymentDetailWritePlatformService paymentDetailWritePlatformService;
|
||||
private final LoanJournalEntryPoster journalEntryPoster;
|
||||
private final NoteWritePlatformService noteWritePlatformService;
|
||||
private final ExternalIdFactory externalIdFactory;
|
||||
private final LoanCapitalizedIncomeBalanceRepository capitalizedIncomeBalanceRepository;
|
||||
private final ReprocessLoanTransactionsService reprocessLoanTransactionsService;
|
||||
@@ -71,6 +72,7 @@ public class CapitalizedIncomeWritePlatformServiceImpl implements CapitalizedInc
|
||||
private final BusinessEventNotifierService businessEventNotifierService;
|
||||
private final CodeValueRepository codeValueRepository;
|
||||
private final LoanScheduleService loanScheduleService;
|
||||
private final ApplicationEventPublisher eventPublisher;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
@@ -107,7 +109,8 @@ public class CapitalizedIncomeWritePlatformServiceImpl implements CapitalizedInc
|
||||
// Create a note if provided
|
||||
final String noteText = command.stringValueOfParameterNamed("note");
|
||||
if (noteText != null && !noteText.isEmpty()) {
|
||||
noteWritePlatformService.createLoanTransactionNote(capitalizedIncomeTransaction.getId(), noteText);
|
||||
eventPublisher.publishEvent(NoteCreateRequest.builder().type(NoteType.LOAN_TRANSACTION)
|
||||
.resourceId(capitalizedIncomeTransaction.getId()).note(noteText).build());
|
||||
}
|
||||
|
||||
// Create journal entries immediately for this transaction
|
||||
@@ -156,7 +159,8 @@ public class CapitalizedIncomeWritePlatformServiceImpl implements CapitalizedInc
|
||||
// Create a note if provided
|
||||
final String noteText = command.stringValueOfParameterNamed("note");
|
||||
if (noteText != null && !noteText.isEmpty()) {
|
||||
noteWritePlatformService.createLoanTransactionNote(savedCapitalizedIncomeAdjustment.getId(), noteText);
|
||||
eventPublisher.publishEvent(NoteCreateRequest.builder().type(NoteType.LOAN_TRANSACTION)
|
||||
.resourceId(savedCapitalizedIncomeAdjustment.getId()).note(noteText).build());
|
||||
}
|
||||
// Create journal entries immediately for this transaction
|
||||
journalEntryPoster.postJournalEntriesForLoanTransaction(savedCapitalizedIncomeAdjustment, false, false);
|
||||
|
||||
+6
-7
@@ -42,9 +42,9 @@ import org.apache.fineract.portfolio.loanaccount.service.LoanScheduleService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.ProgressiveLoanTransactionValidator;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.ProgressiveLoanTransactionValidatorImpl;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.ReprocessLoanTransactionsService;
|
||||
import org.apache.fineract.portfolio.note.service.NoteWritePlatformService;
|
||||
import org.apache.fineract.portfolio.paymentdetail.service.PaymentDetailWritePlatformService;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@@ -56,15 +56,14 @@ public class ProgressiveLoanAccountConfiguration {
|
||||
public CapitalizedIncomePlatformService capitalizedIncomePlatformService(ProgressiveLoanTransactionValidator loanTransactionValidator,
|
||||
LoanAssembler loanAssembler, LoanTransactionRepository loanTransactionRepository,
|
||||
PaymentDetailWritePlatformService paymentDetailWritePlatformService, LoanJournalEntryPoster journalEntryPoster,
|
||||
NoteWritePlatformService noteWritePlatformService, ExternalIdFactory externalIdFactory,
|
||||
LoanCapitalizedIncomeBalanceRepository capitalizedIncomeBalanceRepository,
|
||||
ExternalIdFactory externalIdFactory, LoanCapitalizedIncomeBalanceRepository capitalizedIncomeBalanceRepository,
|
||||
ReprocessLoanTransactionsService reprocessLoanTransactionsService, LoanBalanceService loanBalanceService,
|
||||
LoanLifecycleStateMachine loanLifecycleStateMachine, BusinessEventNotifierService businessEventNotifierService,
|
||||
CodeValueRepository codeValueRepository, LoanScheduleService loanScheduleService) {
|
||||
CodeValueRepository codeValueRepository, LoanScheduleService loanScheduleService, ApplicationEventPublisher eventPublisher) {
|
||||
return new CapitalizedIncomeWritePlatformServiceImpl(loanTransactionValidator, loanAssembler, loanTransactionRepository,
|
||||
paymentDetailWritePlatformService, journalEntryPoster, noteWritePlatformService, externalIdFactory,
|
||||
capitalizedIncomeBalanceRepository, reprocessLoanTransactionsService, loanBalanceService, loanLifecycleStateMachine,
|
||||
businessEventNotifierService, codeValueRepository, loanScheduleService);
|
||||
paymentDetailWritePlatformService, journalEntryPoster, externalIdFactory, capitalizedIncomeBalanceRepository,
|
||||
reprocessLoanTransactionsService, loanBalanceService, loanLifecycleStateMachine, businessEventNotifierService,
|
||||
codeValueRepository, loanScheduleService, eventPublisher);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
+44
@@ -157,6 +157,50 @@ public class SecurityConfig {
|
||||
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_READ, "READ_CURRENCY")
|
||||
.requestMatchers(API_MATCHER.matcher(HttpMethod.POST, "/api/*/currencies"))
|
||||
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "UPDATE_CURRENCY")
|
||||
// notes: read
|
||||
.requestMatchers(API_MATCHER.matcher(HttpMethod.GET, "/api/*/clients/*/notes"))
|
||||
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_READ, "READ_CLIENTNOTE")
|
||||
.requestMatchers(API_MATCHER.matcher(HttpMethod.GET, "/api/*/loans/*/notes"))
|
||||
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_READ, "READ_LOANNOTE")
|
||||
.requestMatchers(API_MATCHER.matcher(HttpMethod.GET, "/api/*/loanTransactions/*/notes"))
|
||||
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_READ, "READ_LOANTRANSACTIONNOTE")
|
||||
.requestMatchers(API_MATCHER.matcher(HttpMethod.GET, "/api/*/savings/*/notes"))
|
||||
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_READ, "READ_SAVINGNOTE")
|
||||
.requestMatchers(API_MATCHER.matcher(HttpMethod.GET, "/api/*/groups/*/notes"))
|
||||
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_READ, "READ_GROUPNOTE")
|
||||
// notes: create
|
||||
.requestMatchers(API_MATCHER.matcher(HttpMethod.POST, "/api/*/clients/*/notes"))
|
||||
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "CREATE_CLIENTNOTE")
|
||||
.requestMatchers(API_MATCHER.matcher(HttpMethod.POST, "/api/*/loans/*/notes"))
|
||||
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "CREATE_LOANNOTE")
|
||||
.requestMatchers(API_MATCHER.matcher(HttpMethod.POST, "/api/*/loanTransactions/*/notes"))
|
||||
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "CREATE_LOANTRANSACTIONNOTE")
|
||||
.requestMatchers(API_MATCHER.matcher(HttpMethod.POST, "/api/*/savings/*/notes"))
|
||||
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "CREATE_SAVINGNOTE")
|
||||
.requestMatchers(API_MATCHER.matcher(HttpMethod.POST, "/api/*/groups/*/notes"))
|
||||
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "CREATE_GROUPNOTE")
|
||||
// notes: update
|
||||
.requestMatchers(API_MATCHER.matcher(HttpMethod.PUT, "/api/*/clients/*/notes"))
|
||||
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "UPDATE_CLIENTNOTE")
|
||||
.requestMatchers(API_MATCHER.matcher(HttpMethod.PUT, "/api/*/loans/*/notes"))
|
||||
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "UPDATE_LOANNOTE")
|
||||
.requestMatchers(API_MATCHER.matcher(HttpMethod.PUT, "/api/*/loanTransactions/*/notes"))
|
||||
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "UPDATE_LOANTRANSACTIONNOTE")
|
||||
.requestMatchers(API_MATCHER.matcher(HttpMethod.PUT, "/api/*/savings/*/notes"))
|
||||
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "UPDATE_SAVINGNOTE")
|
||||
.requestMatchers(API_MATCHER.matcher(HttpMethod.PUT, "/api/*/groups/*/notes"))
|
||||
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "UPDATE_GROUPNOTE")
|
||||
// notes: delete
|
||||
.requestMatchers(API_MATCHER.matcher(HttpMethod.DELETE, "/api/*/clients/*/notes"))
|
||||
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "DELETE_CLIENTNOTE")
|
||||
.requestMatchers(API_MATCHER.matcher(HttpMethod.DELETE, "/api/*/loans/*/notes"))
|
||||
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "DELETE_LOANNOTE")
|
||||
.requestMatchers(API_MATCHER.matcher(HttpMethod.DELETE, "/api/*/loanTransactions/*/notes"))
|
||||
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "DELETE_LOANTRANSACTIONNOTE")
|
||||
.requestMatchers(API_MATCHER.matcher(HttpMethod.DELETE, "/api/*/savings/*/notes"))
|
||||
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "DELETE_SAVINGNOTE")
|
||||
.requestMatchers(API_MATCHER.matcher(HttpMethod.DELETE, "/api/*/groups/*/notes"))
|
||||
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "DELETE_GROUPNOTE")
|
||||
|
||||
.requestMatchers(API_MATCHER.matcher(HttpMethod.POST, "/api/*/twofactor/validate")).fullyAuthenticated()
|
||||
.requestMatchers(API_MATCHER.matcher("/api/*/twofactor")).fullyAuthenticated()
|
||||
|
||||
+6
-6
@@ -175,7 +175,6 @@ import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
|
||||
import org.apache.fineract.portfolio.loanproduct.service.LoanDropdownReadPlatformService;
|
||||
import org.apache.fineract.portfolio.loanproduct.service.LoanProductReadPlatformService;
|
||||
import org.apache.fineract.portfolio.note.domain.NoteRepository;
|
||||
import org.apache.fineract.portfolio.note.service.NoteWritePlatformService;
|
||||
import org.apache.fineract.portfolio.paymentdetail.service.PaymentDetailWritePlatformService;
|
||||
import org.apache.fineract.portfolio.paymenttype.service.PaymentTypeReadPlatformService;
|
||||
import org.apache.fineract.portfolio.rate.service.RateAssembler;
|
||||
@@ -184,6 +183,7 @@ import org.apache.fineract.portfolio.repaymentwithpostdatedchecks.service.Repaym
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccountRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.savings.service.GSIMReadPlatformService;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
@@ -397,12 +397,12 @@ public class LoanAccountConfiguration {
|
||||
public BuyDownFeePlatformService buyDownFeePlatformService(ProgressiveLoanTransactionValidator loanTransactionValidator,
|
||||
LoanAssembler loanAssembler, LoanTransactionRepository loanTransactionRepository,
|
||||
PaymentDetailWritePlatformService paymentDetailWritePlatformService, LoanJournalEntryPoster loanJournalEntryPoster,
|
||||
NoteWritePlatformService noteWritePlatformService, ExternalIdFactory externalIdFactory,
|
||||
LoanBuyDownFeeBalanceRepository loanBuyDownFeeBalanceRepository, BusinessEventNotifierService businessEventNotifierService,
|
||||
CodeValueRepository codeValueRepository) {
|
||||
ExternalIdFactory externalIdFactory, LoanBuyDownFeeBalanceRepository loanBuyDownFeeBalanceRepository,
|
||||
BusinessEventNotifierService businessEventNotifierService, CodeValueRepository codeValueRepository,
|
||||
ApplicationEventPublisher eventPublisher) {
|
||||
return new BuyDownFeeWritePlatformServiceImpl(loanTransactionValidator, loanAssembler, loanTransactionRepository,
|
||||
paymentDetailWritePlatformService, loanJournalEntryPoster, noteWritePlatformService, externalIdFactory,
|
||||
loanBuyDownFeeBalanceRepository, businessEventNotifierService, codeValueRepository);
|
||||
paymentDetailWritePlatformService, loanJournalEntryPoster, externalIdFactory, loanBuyDownFeeBalanceRepository,
|
||||
businessEventNotifierService, codeValueRepository, eventPublisher);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
+93
-139
@@ -19,13 +19,8 @@
|
||||
package org.apache.fineract.portfolio.note.api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.DELETE;
|
||||
import jakarta.ws.rs.GET;
|
||||
@@ -35,201 +30,160 @@ import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.commands.domain.CommandWrapper;
|
||||
import org.apache.fineract.commands.service.CommandWrapperBuilder;
|
||||
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
|
||||
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.command.core.CommandPipeline;
|
||||
import org.apache.fineract.portfolio.note.command.NoteCreateCommand;
|
||||
import org.apache.fineract.portfolio.note.command.NoteDeleteCommand;
|
||||
import org.apache.fineract.portfolio.note.command.NoteUpdateCommand;
|
||||
import org.apache.fineract.portfolio.note.data.NoteCreateRequest;
|
||||
import org.apache.fineract.portfolio.note.data.NoteCreateResponse;
|
||||
import org.apache.fineract.portfolio.note.data.NoteData;
|
||||
import org.apache.fineract.portfolio.note.data.NoteRequest;
|
||||
import org.apache.fineract.portfolio.note.data.NoteDeleteRequest;
|
||||
import org.apache.fineract.portfolio.note.data.NoteDeleteResponse;
|
||||
import org.apache.fineract.portfolio.note.data.NoteUpdateRequest;
|
||||
import org.apache.fineract.portfolio.note.data.NoteUpdateResponse;
|
||||
import org.apache.fineract.portfolio.note.domain.NoteType;
|
||||
import org.apache.fineract.portfolio.note.exception.NoteResourceNotSupportedException;
|
||||
import org.apache.fineract.portfolio.note.service.NoteReadPlatformService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Path("/v1/{resourceType}/{resourceId}/notes")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Component
|
||||
@Tag(name = "Notes", description = "Notes API allows to enter notes for supported resources.")
|
||||
@Tag(name = "Notes", description = """
|
||||
Notes API allows to enter notes for supported resources.
|
||||
""")
|
||||
@RequiredArgsConstructor
|
||||
public class NotesApiResource {
|
||||
|
||||
public static final String CLIENTNOTE = "CLIENTNOTE";
|
||||
public static final String LOANNOTE = "LOANNOTE";
|
||||
public static final String LOANTRANSACTIONNOTE = "LOANTRANSACTIONNOTE";
|
||||
public static final String SAVINGNOTE = "SAVINGNOTE";
|
||||
public static final String GROUPNOTE = "GROUPNOTE";
|
||||
public static final String INVALIDNOTE = "INVALIDNOTE";
|
||||
private static final Set<String> NOTE_DATA_PARAMETERS = new HashSet<>(
|
||||
Arrays.asList("id", "resourceId", "clientId", "groupId", "loanId", "loanTransactionId", "depositAccountId", "savingAccountId",
|
||||
"noteType", "note", "createdById", "createdByUsername", "createdOn", "updatedById", "updatedByUsername", "updatedOn"));
|
||||
private final PlatformSecurityContext context;
|
||||
private final NoteReadPlatformService readPlatformService;
|
||||
private final DefaultToApiJsonSerializer<NoteData> toApiJsonSerializer;
|
||||
private final ApiRequestParameterHelper apiRequestParameterHelper;
|
||||
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||
private final CommandPipeline commandPipeline;
|
||||
|
||||
@GET
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve a Resource's description", description = "Retrieves a Resource's Notes\n\n"
|
||||
+ "Note: Notes are returned in descending createOn order.\n" + "\n" + "Example Requests:\n" + "\n" + "clients/2/notes\n" + "\n"
|
||||
+ "\n" + "groups/2/notes?fields=note,createdOn,createdByUsername")
|
||||
public List<NoteData> retrieveNotesByResource(
|
||||
@PathParam("resourceType") @Parameter(description = "resourceType") final String resourceType,
|
||||
@PathParam("resourceId") @Parameter(description = "resourceId") final Long resourceId) {
|
||||
@Operation(summary = "Retrieve a Resource's description", description = """
|
||||
Retrieves a resource's notes
|
||||
|
||||
final NoteType noteType = NoteType.fromApiUrl(resourceType);
|
||||
Note: results are returned in descending createOn order.
|
||||
|
||||
Example Requests:
|
||||
|
||||
- clients/2/notes
|
||||
- groups/2/notes?fields=note,createdOn,createdByUsername
|
||||
""")
|
||||
public List<NoteData> retrieveNotesByResource(@PathParam("resourceType") final String resourceType,
|
||||
@PathParam("resourceId") final Long resourceId) {
|
||||
final var noteType = NoteType.fromApiUrl(resourceType);
|
||||
|
||||
if (noteType == null) {
|
||||
throw new NoteResourceNotSupportedException(resourceType);
|
||||
}
|
||||
|
||||
this.context.authenticatedUser().validateHasReadPermission(getResourceDetails(noteType, resourceId).entityName());
|
||||
|
||||
final Integer noteTypeId = noteType.getValue();
|
||||
|
||||
return readPlatformService.retrieveNotesByResource(resourceId, noteTypeId);
|
||||
return readPlatformService.retrieveNotesByResource(resourceId, noteType.getValue());
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{noteId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve a Resource Note", description = "Retrieves a Resource Note\n\n" + "Example Requests:\n" + "\n"
|
||||
+ "clients/1/notes/76\n" + "\n" + "\n" + "groups/1/notes/20\n" + "\n" + "\n"
|
||||
+ "clients/1/notes/76?fields=note,createdOn,createdByUsername\n" + "\n" + "\n"
|
||||
+ "groups/1/notes/20?fields=note,createdOn,createdByUsername")
|
||||
public NoteData retrieveNote(@PathParam("resourceType") @Parameter(description = "resourceType") final String resourceType,
|
||||
@PathParam("resourceId") @Parameter(description = "resourceId") final Long resourceId,
|
||||
@PathParam("noteId") @Parameter(description = "noteId") final Long noteId) {
|
||||
@Operation(summary = "Retrieve a Resource Note", description = """
|
||||
Retrieves a resource Note
|
||||
|
||||
Example Requests:
|
||||
|
||||
- clients/1/notes/76
|
||||
- groups/1/notes/20
|
||||
- clients/1/notes/76?fields=note,createdOn,createdByUsername
|
||||
- groups/1/notes/20?fields=note,createdOn,createdByUsername
|
||||
""")
|
||||
public NoteData retrieveNote(@PathParam("resourceType") final String resourceType, @PathParam("resourceId") final Long resourceId,
|
||||
@PathParam("noteId") final Long noteId) {
|
||||
final NoteType noteType = NoteType.fromApiUrl(resourceType);
|
||||
|
||||
if (noteType == null) {
|
||||
throw new NoteResourceNotSupportedException(resourceType);
|
||||
}
|
||||
|
||||
this.context.authenticatedUser().validateHasReadPermission(getResourceDetails(noteType, resourceId).entityName());
|
||||
|
||||
final Integer noteTypeId = noteType.getValue();
|
||||
|
||||
final NoteData note = this.readPlatformService.retrieveNote(noteId, resourceId, noteTypeId);
|
||||
return note;
|
||||
return readPlatformService.retrieveNote(noteId, resourceId, noteType.getValue());
|
||||
}
|
||||
|
||||
@POST
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Add a Resource Note", description = "Adds a new note to a supported resource.\n\n" + "Example Requests:\n" + "\n"
|
||||
+ "clients/1/notes\n" + "\n" + "\n" + "groups/1/notes")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = NoteRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = NotesApiResourceSwagger.PostResourceTypeResourceIdNotesResponse.class))) })
|
||||
public CommandProcessingResult addNewNote(@PathParam("resourceType") @Parameter(description = "resourceType") final String resourceType,
|
||||
@PathParam("resourceId") @Parameter(description = "resourceId") final Long resourceId,
|
||||
@Parameter(hidden = true) final NoteRequest noteRequest) {
|
||||
@Operation(summary = "Add a Resource Note", description = """
|
||||
Adds a new note to a supported resource.
|
||||
|
||||
final NoteType noteType = NoteType.fromApiUrl(resourceType);
|
||||
Example Requests:
|
||||
|
||||
if (noteType == null) {
|
||||
- clients/1/notes
|
||||
- groups/1/notes
|
||||
""")
|
||||
public NoteCreateResponse addNewNote(@PathParam("resourceType") final String resourceType,
|
||||
@PathParam("resourceId") final Long resourceId, @Valid final NoteCreateRequest request) {
|
||||
final var type = NoteType.fromApiUrl(resourceType);
|
||||
|
||||
if (type == null) {
|
||||
throw new NoteResourceNotSupportedException(resourceType);
|
||||
}
|
||||
|
||||
final CommandWrapper resourceDetails = getResourceDetails(noteType, resourceId);
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().createNote(resourceDetails, resourceType, resourceId)
|
||||
.withJson(toApiJsonSerializer.serialize(noteRequest)).build();
|
||||
request.setResourceId(resourceId);
|
||||
request.setType(type);
|
||||
|
||||
return commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
final var command = new NoteCreateCommand();
|
||||
|
||||
command.setPayload(request);
|
||||
|
||||
final Supplier<NoteCreateResponse> response = commandPipeline.send(command);
|
||||
|
||||
return response.get();
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("{noteId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Update a Resource Note", description = "Updates a Resource Note")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = NoteRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = NotesApiResourceSwagger.PutResourceTypeResourceIdNotesNoteIdResponse.class))) })
|
||||
public CommandProcessingResult updateNote(@PathParam("resourceType") @Parameter(description = "resourceType") final String resourceType,
|
||||
@PathParam("resourceId") @Parameter(description = "resourceId") final Long resourceId,
|
||||
@PathParam("noteId") @Parameter(description = "noteId") final Long noteId,
|
||||
@Parameter(hidden = true) final NoteRequest noteRequest) {
|
||||
@Operation(summary = "Update a Resource Note", description = """
|
||||
Updates a Resource Note
|
||||
""")
|
||||
public NoteUpdateResponse updateNote(@PathParam("resourceType") final String resourceType,
|
||||
@PathParam("resourceId") final Long resourceId, @PathParam("noteId") final Long noteId,
|
||||
@Valid final NoteUpdateRequest request) {
|
||||
final var type = NoteType.fromApiUrl(resourceType);
|
||||
|
||||
final NoteType noteType = NoteType.fromApiUrl(resourceType);
|
||||
|
||||
if (noteType == null) {
|
||||
if (type == null) {
|
||||
throw new NoteResourceNotSupportedException(resourceType);
|
||||
}
|
||||
|
||||
final CommandWrapper resourceDetails = getResourceDetails(noteType, resourceId);
|
||||
request.setId(noteId);
|
||||
request.setResourceId(resourceId);
|
||||
request.setType(type);
|
||||
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateNote(resourceDetails, resourceType, resourceId, noteId)
|
||||
.withJson(toApiJsonSerializer.serialize(noteRequest)).build();
|
||||
final var command = new NoteUpdateCommand();
|
||||
|
||||
return commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
command.setPayload(request);
|
||||
|
||||
final Supplier<NoteUpdateResponse> response = commandPipeline.send(command);
|
||||
|
||||
return response.get();
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("{noteId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Delete a Resource Note", description = "Deletes a Resource Note")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = NotesApiResourceSwagger.DeleteResourceTypeResourceIdNotesNoteIdResponse.class))) })
|
||||
public CommandProcessingResult deleteNote(@PathParam("resourceType") @Parameter(description = "resourceType") final String resourceType,
|
||||
@PathParam("resourceId") @Parameter(description = "resourceId") final Long resourceId,
|
||||
@PathParam("noteId") @Parameter(description = "noteId") final Long noteId) {
|
||||
@Operation(summary = "Delete a Resource Note", description = """
|
||||
Deletes a Resource Note
|
||||
""")
|
||||
public NoteDeleteResponse deleteNote(@PathParam("resourceType") final String resourceType,
|
||||
@PathParam("resourceId") final Long resourceId, @PathParam("noteId") final Long noteId) {
|
||||
final var type = NoteType.fromApiUrl(resourceType);
|
||||
|
||||
final NoteType noteType = NoteType.fromApiUrl(resourceType);
|
||||
|
||||
if (noteType == null) {
|
||||
if (type == null) {
|
||||
throw new NoteResourceNotSupportedException(resourceType);
|
||||
}
|
||||
|
||||
final CommandWrapper resourceDetails = getResourceDetails(noteType, resourceId);
|
||||
var request = NoteDeleteRequest.builder().id(noteId).resourceId(resourceId).type(type).build();
|
||||
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteNote(resourceDetails, resourceType, resourceId, noteId)
|
||||
.build();
|
||||
final var command = new NoteDeleteCommand();
|
||||
|
||||
return commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
}
|
||||
command.setPayload(request);
|
||||
|
||||
private CommandWrapper getResourceDetails(final NoteType type, final Long resourceId) {
|
||||
CommandWrapperBuilder resourceDetails = new CommandWrapperBuilder();
|
||||
String resourceNameForPermissions;
|
||||
switch (type) {
|
||||
case CLIENT -> {
|
||||
resourceNameForPermissions = CLIENTNOTE;
|
||||
resourceDetails.withClientId(resourceId);
|
||||
}
|
||||
case LOAN -> {
|
||||
resourceNameForPermissions = LOANNOTE;
|
||||
resourceDetails.withLoanId(resourceId);
|
||||
}
|
||||
case LOAN_TRANSACTION -> {
|
||||
resourceNameForPermissions = LOANTRANSACTIONNOTE;
|
||||
// updating loanId, to distinguish saving transaction note and
|
||||
// loan transaction note as we are using subEntityId for both.
|
||||
resourceDetails.withLoanId(resourceId);
|
||||
resourceDetails.withSubEntityId(resourceId);
|
||||
}
|
||||
case SAVING_ACCOUNT -> {
|
||||
resourceNameForPermissions = SAVINGNOTE;
|
||||
resourceDetails.withSavingsId(resourceId);
|
||||
}
|
||||
case GROUP -> {
|
||||
resourceNameForPermissions = GROUPNOTE;
|
||||
resourceDetails.withGroupId(resourceId);
|
||||
}
|
||||
default -> resourceNameForPermissions = INVALIDNOTE;
|
||||
}
|
||||
return resourceDetails.withEntityName(resourceNameForPermissions).build();
|
||||
final Supplier<NoteDeleteResponse> response = commandPipeline.send(command);
|
||||
|
||||
return response.get();
|
||||
}
|
||||
}
|
||||
|
||||
-82
@@ -1,82 +0,0 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.note.api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
/**
|
||||
* Created by Chirag Gupta on 12/29/17.
|
||||
*/
|
||||
public final class NotesApiResourceSwagger {
|
||||
|
||||
private NotesApiResourceSwagger() {}
|
||||
|
||||
@Schema(description = "PostResourceTypeResourceIdNotesRequest")
|
||||
public static final class PostResourceTypeResourceIdNotesRequest {
|
||||
|
||||
private PostResourceTypeResourceIdNotesRequest() {}
|
||||
|
||||
@Schema(example = "a note about the client")
|
||||
public String note;
|
||||
}
|
||||
|
||||
@Schema(description = "PostResourceTypeResourceIdNotesResponse")
|
||||
public static final class PostResourceTypeResourceIdNotesResponse {
|
||||
|
||||
private PostResourceTypeResourceIdNotesResponse() {}
|
||||
|
||||
@Schema(example = "1")
|
||||
public Long officeId;
|
||||
@Schema(example = "1")
|
||||
public Long clientId;
|
||||
@Schema(example = "76")
|
||||
public Long resourceId;
|
||||
}
|
||||
|
||||
@Schema(description = "PutResourceTypeResourceIdNotesNoteIdResponse")
|
||||
public static final class PutResourceTypeResourceIdNotesNoteIdResponse {
|
||||
|
||||
private PutResourceTypeResourceIdNotesNoteIdResponse() {}
|
||||
|
||||
static final class PutNotesChanges {
|
||||
|
||||
private PutNotesChanges() {}
|
||||
|
||||
@Schema(example = "a note about the client")
|
||||
public String note;
|
||||
}
|
||||
|
||||
@Schema(example = "1")
|
||||
public Long officeId;
|
||||
@Schema(example = "1")
|
||||
public Long clientId;
|
||||
@Schema(example = "76")
|
||||
public Long resourceId;
|
||||
public PutNotesChanges changes;
|
||||
}
|
||||
|
||||
@Schema(description = "DeleteResourceTypeResourceIdNotesNoteIdResponse")
|
||||
public static final class DeleteResourceTypeResourceIdNotesNoteIdResponse {
|
||||
|
||||
private DeleteResourceTypeResourceIdNotesNoteIdResponse() {}
|
||||
|
||||
@Schema(example = "76")
|
||||
public Long resourceId;
|
||||
}
|
||||
}
|
||||
+7
-12
@@ -18,16 +18,11 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.note.command;
|
||||
|
||||
/**
|
||||
* Immutable command used for create or update of notes.
|
||||
*/
|
||||
public class NoteCommand {
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.fineract.command.core.Command;
|
||||
import org.apache.fineract.portfolio.note.data.NoteCreateRequest;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final String note;
|
||||
|
||||
public NoteCommand(final String note) {
|
||||
this.note = note;
|
||||
}
|
||||
|
||||
}
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class NoteCreateCommand extends Command<NoteCreateRequest> {}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.note.command;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.fineract.command.core.Command;
|
||||
import org.apache.fineract.portfolio.note.data.NoteDeleteRequest;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class NoteDeleteCommand extends Command<NoteDeleteRequest> {}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.note.command;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.fineract.command.core.Command;
|
||||
import org.apache.fineract.portfolio.note.data.NoteUpdateRequest;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class NoteUpdateCommand extends Command<NoteUpdateRequest> {}
|
||||
+8
-19
@@ -23,10 +23,9 @@ import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.commons.lang3.Strings;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
|
||||
import org.apache.fineract.portfolio.client.domain.Client;
|
||||
import org.apache.fineract.portfolio.group.domain.Group;
|
||||
@@ -74,13 +73,11 @@ public class Note extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||
@JoinColumn(name = "share_account_id", nullable = true)
|
||||
private ShareAccount shareAccount;
|
||||
|
||||
public static Note clientNoteFromJson(final Client client, final JsonCommand command) {
|
||||
final String note = command.stringValueOfParameterNamed("note");
|
||||
public static Note clientNote(final Client client, final String note) {
|
||||
return new Note(client, note);
|
||||
}
|
||||
|
||||
public static Note groupNoteFromJson(final Group group, final JsonCommand command) {
|
||||
final String note = command.stringValueOfParameterNamed("note");
|
||||
public static Note groupNote(final Group group, final String note) {
|
||||
return new Note(group, note);
|
||||
}
|
||||
|
||||
@@ -164,20 +161,12 @@ public class Note extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||
this.noteTypeId = NoteType.SHARE_ACCOUNT.getValue();
|
||||
}
|
||||
|
||||
public Map<String, Object> update(final JsonCommand command) {
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<>(7);
|
||||
|
||||
final String noteParamName = "note";
|
||||
if (command.isChangeInStringParameterNamed(noteParamName, this.note)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(noteParamName);
|
||||
actualChanges.put(noteParamName, newValue);
|
||||
this.note = StringUtils.defaultIfEmpty(newValue, null);
|
||||
public Map<String, Object> update(final String note) {
|
||||
if (!Strings.CI.equals(note, this.note)) {
|
||||
this.note = StringUtils.defaultIfEmpty(note, null);
|
||||
return Map.of("note", note);
|
||||
}
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
public boolean isNotAgainstClientWithIdOf(final Long clientId) {
|
||||
return !this.client.identifiedBy(clientId);
|
||||
return Map.of();
|
||||
}
|
||||
|
||||
public String getNote() {
|
||||
|
||||
+20
-13
@@ -18,27 +18,34 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.note.handler;
|
||||
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import io.github.resilience4j.retry.annotation.Retry;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.command.core.Command;
|
||||
import org.apache.fineract.command.core.CommandHandler;
|
||||
import org.apache.fineract.portfolio.note.data.NoteCreateRequest;
|
||||
import org.apache.fineract.portfolio.note.data.NoteCreateResponse;
|
||||
import org.apache.fineract.portfolio.note.service.NoteWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class DeleteNoteCommandHandler implements NewCommandSourceHandler {
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class NoteCreateCommandHandler implements CommandHandler<NoteCreateRequest, NoteCreateResponse> {
|
||||
|
||||
private final NoteWritePlatformService writePlatformService;
|
||||
|
||||
@Autowired
|
||||
public DeleteNoteCommandHandler(final NoteWritePlatformService writePlatformService) {
|
||||
this.writePlatformService = writePlatformService;
|
||||
@Retry(name = "commandNoteCreate", fallbackMethod = "fallback")
|
||||
@Override
|
||||
@Transactional
|
||||
public NoteCreateResponse handle(Command<NoteCreateRequest> command) {
|
||||
return writePlatformService.createNote(command.getPayload());
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
return this.writePlatformService.deleteNote(command);
|
||||
public NoteCreateResponse fallback(Command<NoteCreateRequest> command, Throwable t) {
|
||||
// NOTE: fallback method needs to be in the same class
|
||||
return CommandHandler.super.fallback(command, t);
|
||||
}
|
||||
}
|
||||
+21
-16
@@ -18,29 +18,34 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.note.handler;
|
||||
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import io.github.resilience4j.retry.annotation.Retry;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.command.core.Command;
|
||||
import org.apache.fineract.command.core.CommandHandler;
|
||||
import org.apache.fineract.portfolio.note.data.NoteDeleteRequest;
|
||||
import org.apache.fineract.portfolio.note.data.NoteDeleteResponse;
|
||||
import org.apache.fineract.portfolio.note.service.NoteWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class UpdateNoteCommandHandler implements NewCommandSourceHandler {
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class NoteDeleteCommandHandler implements CommandHandler<NoteDeleteRequest, NoteDeleteResponse> {
|
||||
|
||||
private final NoteWritePlatformService writePlatformService;
|
||||
|
||||
@Autowired
|
||||
public UpdateNoteCommandHandler(final NoteWritePlatformService noteWritePlatformService) {
|
||||
this.writePlatformService = noteWritePlatformService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Retry(name = "commandNoteDelete", fallbackMethod = "fallback")
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
|
||||
return this.writePlatformService.updateNote(command);
|
||||
@Transactional
|
||||
public NoteDeleteResponse handle(Command<NoteDeleteRequest> command) {
|
||||
return writePlatformService.deleteNote(command.getPayload());
|
||||
}
|
||||
|
||||
@Override
|
||||
public NoteDeleteResponse fallback(Command<NoteDeleteRequest> command, Throwable t) {
|
||||
// NOTE: fallback method needs to be in the same class
|
||||
return CommandHandler.super.fallback(command, t);
|
||||
}
|
||||
}
|
||||
+21
-15
@@ -18,28 +18,34 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.note.handler;
|
||||
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import io.github.resilience4j.retry.annotation.Retry;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.command.core.Command;
|
||||
import org.apache.fineract.command.core.CommandHandler;
|
||||
import org.apache.fineract.portfolio.note.data.NoteUpdateRequest;
|
||||
import org.apache.fineract.portfolio.note.data.NoteUpdateResponse;
|
||||
import org.apache.fineract.portfolio.note.service.NoteWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class CreateNoteCommandHandler implements NewCommandSourceHandler {
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class NoteUpdateCommandHandler implements CommandHandler<NoteUpdateRequest, NoteUpdateResponse> {
|
||||
|
||||
private final NoteWritePlatformService writePlatformService;
|
||||
|
||||
@Autowired
|
||||
public CreateNoteCommandHandler(final NoteWritePlatformService writePlatformService) {
|
||||
this.writePlatformService = writePlatformService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Retry(name = "commandNoteUpdate", fallbackMethod = "fallback")
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
return this.writePlatformService.createNote(command);
|
||||
@Transactional
|
||||
public NoteUpdateResponse handle(Command<NoteUpdateRequest> command) {
|
||||
return writePlatformService.updateNote(command.getPayload());
|
||||
}
|
||||
|
||||
@Override
|
||||
public NoteUpdateResponse fallback(Command<NoteUpdateRequest> command, Throwable t) {
|
||||
// NOTE: fallback method needs to be in the same class
|
||||
return CommandHandler.super.fallback(command, t);
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.note.listener;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.portfolio.note.data.NoteCreateRequest;
|
||||
import org.apache.fineract.portfolio.note.service.NoteWritePlatformService;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Component
|
||||
class NoteListener {
|
||||
|
||||
private final NoteWritePlatformService noteWritePlatformService;
|
||||
|
||||
@EventListener
|
||||
void onCreate(NoteCreateRequest request) {
|
||||
noteWritePlatformService.createNote(request);
|
||||
}
|
||||
|
||||
@EventListener
|
||||
void onUpdate(NoteCreateRequest request) {
|
||||
noteWritePlatformService.createNote(request);
|
||||
}
|
||||
|
||||
@EventListener
|
||||
void onDelete(NoteCreateRequest request) {
|
||||
noteWritePlatformService.createNote(request);
|
||||
}
|
||||
}
|
||||
-102
@@ -1,102 +0,0 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.note.serialization;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.AbstractFromApiJsonDeserializer;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromApiJsonDeserializer;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.portfolio.note.command.NoteCommand;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Implementation of {@link FromApiJsonDeserializer} for {@link NoteCommand} 's.
|
||||
*/
|
||||
@Component
|
||||
public final class NoteCommandFromApiJsonDeserializer extends AbstractFromApiJsonDeserializer<NoteCommand> {
|
||||
|
||||
public static final String NOTE = "note";
|
||||
/**
|
||||
* The parameters supported for this command.
|
||||
*/
|
||||
private static final Set<String> SUPPORTED_PARAMETERS = new HashSet<>(List.of(NOTE));
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
|
||||
@Autowired
|
||||
public NoteCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper) {
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NoteCommand commandFromApiJson(final String json) {
|
||||
|
||||
if (StringUtils.isBlank(json)) {
|
||||
throw new InvalidJsonException();
|
||||
}
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {
|
||||
|
||||
}.getType();
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, SUPPORTED_PARAMETERS);
|
||||
|
||||
final JsonElement element = this.fromApiJsonHelper.parse(json);
|
||||
final String note = this.fromApiJsonHelper.extractStringNamed(NOTE, element);
|
||||
|
||||
return new NoteCommand(note);
|
||||
}
|
||||
|
||||
public void validateNote(final String json) {
|
||||
if (StringUtils.isBlank(json)) {
|
||||
throw new InvalidJsonException();
|
||||
}
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {
|
||||
|
||||
}.getType();
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, SUPPORTED_PARAMETERS);
|
||||
final JsonElement element = this.fromApiJsonHelper.parse(json);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource(NOTE);
|
||||
|
||||
final String note = this.fromApiJsonHelper.extractStringNamed(NOTE, element);
|
||||
baseDataValidator.reset().parameter(NOTE).value(note).notBlank().notExceedingLengthOf(1000);
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
||||
dataValidationErrors);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+77
-365
@@ -18,30 +18,26 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.note.service;
|
||||
|
||||
import java.util.Map;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.portfolio.client.domain.Client;
|
||||
import org.apache.commons.lang3.Strings;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.client.exception.ClientNotFoundException;
|
||||
import org.apache.fineract.portfolio.group.domain.Group;
|
||||
import org.apache.fineract.portfolio.group.domain.GroupRepository;
|
||||
import org.apache.fineract.portfolio.group.exception.GroupNotFoundException;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanTransactionNotFoundException;
|
||||
import org.apache.fineract.portfolio.note.data.NoteCreateRequest;
|
||||
import org.apache.fineract.portfolio.note.data.NoteCreateResponse;
|
||||
import org.apache.fineract.portfolio.note.data.NoteDeleteRequest;
|
||||
import org.apache.fineract.portfolio.note.data.NoteDeleteResponse;
|
||||
import org.apache.fineract.portfolio.note.data.NoteUpdateRequest;
|
||||
import org.apache.fineract.portfolio.note.data.NoteUpdateResponse;
|
||||
import org.apache.fineract.portfolio.note.domain.Note;
|
||||
import org.apache.fineract.portfolio.note.domain.NoteRepository;
|
||||
import org.apache.fineract.portfolio.note.domain.NoteType;
|
||||
import org.apache.fineract.portfolio.note.exception.NoteNotFoundException;
|
||||
import org.apache.fineract.portfolio.note.exception.NoteResourceNotSupportedException;
|
||||
import org.apache.fineract.portfolio.note.serialization.NoteCommandFromApiJsonDeserializer;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccountRepository;
|
||||
import org.apache.fineract.portfolio.savings.exception.SavingsAccountNotFoundException;
|
||||
|
||||
@@ -53,419 +49,135 @@ public class NoteWritePlatformServiceJpaRepositoryImpl implements NoteWritePlatf
|
||||
private final GroupRepository groupRepository;
|
||||
private final LoanRepositoryWrapper loanRepository;
|
||||
private final LoanTransactionRepository loanTransactionRepository;
|
||||
private final NoteCommandFromApiJsonDeserializer fromApiJsonDeserializer;
|
||||
private final SavingsAccountRepository savingsAccountRepository;
|
||||
|
||||
public NoteWritePlatformServiceJpaRepositoryImpl(final NoteRepository noteRepository, final ClientRepositoryWrapper clientRepository,
|
||||
final GroupRepository groupRepository, final LoanRepositoryWrapper loanRepository,
|
||||
final LoanTransactionRepository loanTransactionRepository, final NoteCommandFromApiJsonDeserializer fromApiJsonDeserializer,
|
||||
final SavingsAccountRepository savingsAccountRepository) {
|
||||
final LoanTransactionRepository loanTransactionRepository, final SavingsAccountRepository savingsAccountRepository) {
|
||||
this.noteRepository = noteRepository;
|
||||
this.clientRepository = clientRepository;
|
||||
this.groupRepository = groupRepository;
|
||||
this.loanRepository = loanRepository;
|
||||
this.loanTransactionRepository = loanTransactionRepository;
|
||||
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
|
||||
this.savingsAccountRepository = savingsAccountRepository;
|
||||
}
|
||||
|
||||
private CommandProcessingResult createClientNote(final JsonCommand command) {
|
||||
|
||||
final Long resourceId = command.getClientId();
|
||||
|
||||
final Client client = this.clientRepository.findOneWithNotFoundDetection(resourceId);
|
||||
if (client == null) {
|
||||
throw new ClientNotFoundException(resourceId);
|
||||
}
|
||||
final Note newNote = Note.clientNoteFromJson(client, command);
|
||||
|
||||
this.noteRepository.saveAndFlush(newNote);
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(newNote.getId()) //
|
||||
.withClientId(client.getId()) //
|
||||
.withOfficeId(client.officeId()) //
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createAndPersistClientNote(final Client client, final JsonCommand command) {
|
||||
final String noteText = command.stringValueOfParameterNamed("note");
|
||||
if (StringUtils.isNotBlank(noteText)) {
|
||||
final Note newNote = new Note(client, noteText);
|
||||
this.noteRepository.save(newNote);
|
||||
}
|
||||
}
|
||||
public NoteCreateResponse createNote(final NoteCreateRequest request) {
|
||||
Note note;
|
||||
Long officeId;
|
||||
|
||||
private CommandProcessingResult createGroupNote(final JsonCommand command) {
|
||||
|
||||
final Long resourceId = command.getGroupId();
|
||||
|
||||
final Group group = this.groupRepository.findById(resourceId).orElseThrow(() -> new GroupNotFoundException(resourceId));
|
||||
final Note newNote = Note.groupNoteFromJson(group, command);
|
||||
|
||||
this.noteRepository.saveAndFlush(newNote);
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(newNote.getId()) //
|
||||
.withGroupId(group.getId()) //
|
||||
.withOfficeId(group.officeId()) //
|
||||
.build();
|
||||
}
|
||||
|
||||
private CommandProcessingResult createLoanNote(final JsonCommand command) {
|
||||
|
||||
final Long resourceId = command.getLoanId();
|
||||
|
||||
final Loan loan = this.loanRepository.findOneWithNotFoundDetection(resourceId);
|
||||
final String note = command.stringValueOfParameterNamed("note");
|
||||
final Note newNote = Note.loanNote(loan, note);
|
||||
|
||||
this.noteRepository.saveAndFlush(newNote);
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(newNote.getId()) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withLoanId(loan.getId()) //
|
||||
.build();
|
||||
}
|
||||
|
||||
private CommandProcessingResult createLoanTransactionNote(final JsonCommand command) {
|
||||
|
||||
final Long resourceId = command.subentityId();
|
||||
|
||||
final LoanTransaction loanTransaction = this.loanTransactionRepository.findById(resourceId)
|
||||
.orElseThrow(() -> new LoanTransactionNotFoundException(resourceId));
|
||||
|
||||
final Loan loan = loanTransaction.getLoan();
|
||||
|
||||
final String note = command.stringValueOfParameterNamed("note");
|
||||
final Note newNote = Note.loanTransactionNote(loan, loanTransaction, note);
|
||||
|
||||
this.noteRepository.saveAndFlush(newNote);
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(newNote.getId()) //
|
||||
.withOfficeId(loan.getOfficeId())//
|
||||
.withLoanId(loan.getId())// Loan can be associated
|
||||
.build();
|
||||
}
|
||||
|
||||
private CommandProcessingResult createSavingAccountNote(final JsonCommand command) {
|
||||
final Long resourceId = command.getSavingsId();
|
||||
final SavingsAccount savingAccount = this.savingsAccountRepository.findById(resourceId)
|
||||
.orElseThrow(() -> new SavingsAccountNotFoundException(resourceId));
|
||||
|
||||
final String note = command.stringValueOfParameterNamed("note");
|
||||
final Note newNote = Note.savingNote(savingAccount, note);
|
||||
|
||||
this.noteRepository.saveAndFlush(newNote);
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(newNote.getId()) //
|
||||
.withOfficeId(savingAccount.getClient().getOffice().getId()) //
|
||||
.withSavingsId(savingAccount.getId()) //
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult createNote(final JsonCommand command) {
|
||||
|
||||
this.fromApiJsonDeserializer.validateNote(command.json());
|
||||
|
||||
final String resourceUrl = getResourceUrlFromCommand(command); // command.getSupportedEntityType();
|
||||
final NoteType type = NoteType.fromApiUrl(resourceUrl);
|
||||
switch (type) {
|
||||
switch (request.getType()) {
|
||||
case CLIENT: {
|
||||
return createClientNote(command);
|
||||
final var client = this.clientRepository.findOneWithNotFoundDetection(request.getResourceId());
|
||||
note = noteRepository.saveAndFlush(Note.clientNote(client, request.getNote()));
|
||||
officeId = client.officeId();
|
||||
}
|
||||
break;
|
||||
case GROUP: {
|
||||
return createGroupNote(command);
|
||||
final var group = groupRepository.findById(request.getResourceId())
|
||||
.orElseThrow(() -> new GroupNotFoundException(request.getResourceId()));
|
||||
note = noteRepository.saveAndFlush(Note.groupNote(group, request.getNote()));
|
||||
officeId = group.officeId();
|
||||
}
|
||||
break;
|
||||
case LOAN: {
|
||||
return createLoanNote(command);
|
||||
final var loan = loanRepository.findOneWithNotFoundDetection(request.getResourceId());
|
||||
note = noteRepository.saveAndFlush(Note.loanNote(loan, request.getNote()));
|
||||
officeId = loan.getOfficeId();
|
||||
}
|
||||
break;
|
||||
case LOAN_TRANSACTION: {
|
||||
return createLoanTransactionNote(command);
|
||||
final var loanTransaction = this.loanTransactionRepository.findById(request.getResourceId())
|
||||
.orElseThrow(() -> new LoanTransactionNotFoundException(request.getResourceId()));
|
||||
note = noteRepository.saveAndFlush(Note.loanTransactionNote(loanTransaction.getLoan(), loanTransaction, request.getNote()));
|
||||
officeId = loanTransaction.getLoan().getOfficeId();
|
||||
}
|
||||
break;
|
||||
case SAVING_ACCOUNT: {
|
||||
return createSavingAccountNote(command);
|
||||
final var savingAccount = savingsAccountRepository.findById(request.getResourceId())
|
||||
.orElseThrow(() -> new SavingsAccountNotFoundException(request.getResourceId()));
|
||||
note = noteRepository.saveAndFlush(Note.savingNote(savingAccount, request.getNote()));
|
||||
officeId = savingAccount.getClient().getOffice().getId();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new NoteResourceNotSupportedException(resourceUrl);
|
||||
throw new NoteResourceNotSupportedException(request.getType().getApiUrl());
|
||||
}
|
||||
|
||||
return NoteCreateResponse.builder().entityId(note.getId()).resourceId(note.getId()).officeId(officeId).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createLoanTransactionNote(final Long loanTransactionId, final String note) {
|
||||
final LoanTransaction loanTransaction = this.loanTransactionRepository.findById(loanTransactionId)
|
||||
.orElseThrow(() -> new LoanTransactionNotFoundException(loanTransactionId));
|
||||
public NoteUpdateResponse updateNote(final NoteUpdateRequest request) {
|
||||
final var result = getNote(request.getType(), request.getResourceId(), request.getId());
|
||||
final var note = result.getLeft();
|
||||
final var response = NoteUpdateResponse.builder().officeId(result.getRight()).resourceId(request.getResourceId());
|
||||
|
||||
final Loan loan = loanTransaction.getLoan();
|
||||
|
||||
final Note newNote = Note.loanTransactionNote(loan, loanTransaction, note);
|
||||
|
||||
this.noteRepository.save(newNote);
|
||||
}
|
||||
|
||||
private String getResourceUrlFromCommand(JsonCommand command) {
|
||||
|
||||
final String resourceUrl;
|
||||
|
||||
if (command.getClientId() != null) {
|
||||
resourceUrl = NoteType.CLIENT.getApiUrl();
|
||||
} else if (command.getGroupId() != null) {
|
||||
resourceUrl = NoteType.GROUP.getApiUrl();
|
||||
} else if (command.getLoanId() != null) {
|
||||
if (command.subentityId() != null) {
|
||||
resourceUrl = NoteType.LOAN_TRANSACTION.getApiUrl();
|
||||
} else {
|
||||
resourceUrl = NoteType.LOAN.getApiUrl();
|
||||
}
|
||||
} else if (command.getSavingsId() != null) {
|
||||
// TODO: SAVING_TRANSACTION type need to be add.
|
||||
resourceUrl = NoteType.SAVING_ACCOUNT.getApiUrl();
|
||||
} else {
|
||||
resourceUrl = "";
|
||||
if (!Strings.CI.equals(note.getNote(), request.getNote())) {
|
||||
response.changes(note.update(request.getNote()));
|
||||
noteRepository.saveAndFlush(note);
|
||||
}
|
||||
|
||||
return resourceUrl;
|
||||
}
|
||||
|
||||
private CommandProcessingResult updateClientNote(final JsonCommand command) {
|
||||
|
||||
final Long resourceId = command.getClientId();
|
||||
final Long noteId = command.entityId();
|
||||
|
||||
final NoteType type = NoteType.CLIENT;
|
||||
|
||||
final Client client = this.clientRepository.findOneWithNotFoundDetection(resourceId);
|
||||
|
||||
final Note noteForUpdate = this.noteRepository.findByClientAndId(client, noteId);
|
||||
if (noteForUpdate == null) {
|
||||
throw new NoteNotFoundException(noteId, resourceId, type.name().toLowerCase());
|
||||
}
|
||||
|
||||
final Map<String, Object> changes = noteForUpdate.update(command);
|
||||
|
||||
if (!changes.isEmpty()) {
|
||||
this.noteRepository.saveAndFlush(noteForUpdate);
|
||||
}
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(noteForUpdate.getId()) //
|
||||
.withClientId(client.getId()) //
|
||||
.withOfficeId(client.officeId()) //
|
||||
.with(changes) //
|
||||
.build();
|
||||
}
|
||||
|
||||
private CommandProcessingResult updateGroupNote(final JsonCommand command) {
|
||||
|
||||
final Long resourceId = command.getGroupId();
|
||||
final Long noteId = command.entityId();
|
||||
|
||||
final NoteType type = NoteType.GROUP;
|
||||
|
||||
final Group group = this.groupRepository.findById(resourceId).orElseThrow(() -> new GroupNotFoundException(resourceId));
|
||||
|
||||
final Note noteForUpdate = this.noteRepository.findByGroupAndId(group, noteId);
|
||||
|
||||
if (noteForUpdate == null) {
|
||||
throw new NoteNotFoundException(noteId, resourceId, type.name().toLowerCase());
|
||||
}
|
||||
|
||||
final Map<String, Object> changes = noteForUpdate.update(command);
|
||||
|
||||
if (!changes.isEmpty()) {
|
||||
this.noteRepository.saveAndFlush(noteForUpdate);
|
||||
}
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(noteForUpdate.getId()) //
|
||||
.withGroupId(group.getId()) //
|
||||
.withOfficeId(group.officeId()) //
|
||||
.with(changes).build();
|
||||
}
|
||||
|
||||
private CommandProcessingResult updateLoanNote(final JsonCommand command) {
|
||||
|
||||
final Long resourceId = command.getLoanId();
|
||||
final Long noteId = command.entityId();
|
||||
|
||||
final NoteType type = NoteType.LOAN;
|
||||
|
||||
final Loan loan = this.loanRepository.findOneWithNotFoundDetection(resourceId);
|
||||
final Note noteForUpdate = this.noteRepository.findByLoanAndId(loan, noteId);
|
||||
if (noteForUpdate == null) {
|
||||
throw new NoteNotFoundException(noteId, resourceId, type.name().toLowerCase());
|
||||
}
|
||||
|
||||
final Map<String, Object> changes = noteForUpdate.update(command);
|
||||
|
||||
if (!changes.isEmpty()) {
|
||||
this.noteRepository.saveAndFlush(noteForUpdate);
|
||||
}
|
||||
|
||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(noteForUpdate.getId())
|
||||
.withLoanId(loan.getId()).withOfficeId(loan.getOfficeId()).with(changes).build();
|
||||
}
|
||||
|
||||
private CommandProcessingResult updateLoanTransactionNote(final JsonCommand command) {
|
||||
|
||||
final Long resourceId = command.subentityId();
|
||||
final Long noteId = command.entityId();
|
||||
|
||||
final NoteType type = NoteType.LOAN_TRANSACTION;
|
||||
|
||||
final LoanTransaction loanTransaction = this.loanTransactionRepository.findById(resourceId)
|
||||
.orElseThrow(() -> new LoanTransactionNotFoundException(resourceId));
|
||||
final Loan loan = loanTransaction.getLoan();
|
||||
|
||||
final Note noteForUpdate = this.noteRepository.findByLoanTransactionAndId(loanTransaction, noteId);
|
||||
|
||||
if (noteForUpdate == null) {
|
||||
throw new NoteNotFoundException(noteId, resourceId, type.name().toLowerCase());
|
||||
}
|
||||
|
||||
final Map<String, Object> changes = noteForUpdate.update(command);
|
||||
|
||||
if (!changes.isEmpty()) {
|
||||
this.noteRepository.saveAndFlush(noteForUpdate);
|
||||
}
|
||||
|
||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(noteForUpdate.getId())
|
||||
.withLoanId(loan.getId()).withOfficeId(loan.getOfficeId()).with(changes).build();
|
||||
}
|
||||
|
||||
private CommandProcessingResult updateSavingAccountNote(final JsonCommand command) {
|
||||
final Long resourceId = command.getSavingsId();
|
||||
final Long noteId = command.entityId();
|
||||
final NoteType type = NoteType.SAVING_ACCOUNT;
|
||||
final SavingsAccount savingAccount = this.savingsAccountRepository.findById(resourceId)
|
||||
.orElseThrow(() -> new SavingsAccountNotFoundException(resourceId));
|
||||
|
||||
final Note noteForUpdate = this.noteRepository.findBySavingsAccountAndId(savingAccount, noteId);
|
||||
if (noteForUpdate == null) {
|
||||
throw new NoteNotFoundException(noteId, resourceId, type.name().toLowerCase());
|
||||
}
|
||||
final Map<String, Object> changes = noteForUpdate.update(command);
|
||||
if (!changes.isEmpty()) {
|
||||
this.noteRepository.saveAndFlush(noteForUpdate);
|
||||
}
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(noteForUpdate.getId()) //
|
||||
.withOfficeId(savingAccount.getClient().getOffice().getId()) //
|
||||
.withSavingsId(savingAccount.getId()) //
|
||||
.with(changes) //
|
||||
.build();
|
||||
return response.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult updateNote(final JsonCommand command) {
|
||||
public NoteDeleteResponse deleteNote(final NoteDeleteRequest request) {
|
||||
var note = getNote(request.getType(), request.getResourceId(), request.getId());
|
||||
|
||||
this.fromApiJsonDeserializer.validateNote(command.json());
|
||||
noteRepository.delete(note.getLeft());
|
||||
|
||||
final String resourceUrl = getResourceUrlFromCommand(command); // command.getSupportedEntityType();
|
||||
final NoteType type = NoteType.fromApiUrl(resourceUrl);
|
||||
return NoteDeleteResponse.builder().resourceId(request.getId()).build();
|
||||
}
|
||||
|
||||
private Pair<Note, Long> getNote(NoteType type, Long resourceId, Long noteId) {
|
||||
Note note = null;
|
||||
Long officeId = null;
|
||||
|
||||
switch (type) {
|
||||
case CLIENT: {
|
||||
return updateClientNote(command);
|
||||
}
|
||||
case GROUP: {
|
||||
return updateGroupNote(command);
|
||||
}
|
||||
case LOAN: {
|
||||
return updateLoanNote(command);
|
||||
}
|
||||
case LOAN_TRANSACTION: {
|
||||
return updateLoanTransactionNote(command);
|
||||
}
|
||||
case SAVING_ACCOUNT: {
|
||||
return updateSavingAccountNote(command);
|
||||
}
|
||||
default:
|
||||
throw new NoteResourceNotSupportedException(resourceUrl);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult deleteNote(final JsonCommand command) {
|
||||
|
||||
final Note noteForDelete = getNoteForDelete(command);
|
||||
|
||||
this.noteRepository.delete(noteForDelete);
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(null) //
|
||||
.withEntityId(command.entityId()) //
|
||||
.build();
|
||||
}
|
||||
|
||||
private Note getNoteForDelete(final JsonCommand command) {
|
||||
final String resourceUrl = getResourceUrlFromCommand(command);// command.getSupportedEntityType();
|
||||
final Long noteId = command.entityId();
|
||||
final NoteType type = NoteType.fromApiUrl(resourceUrl);
|
||||
Long resourceId = null;
|
||||
Note noteForUpdate = null;
|
||||
switch (type) {
|
||||
case CLIENT: {
|
||||
resourceId = command.getClientId();
|
||||
final Client client = this.clientRepository.findOneWithNotFoundDetection(resourceId);
|
||||
noteForUpdate = this.noteRepository.findByClientAndId(client, noteId);
|
||||
final var client = clientRepository.findOneWithNotFoundDetection(resourceId);
|
||||
note = noteRepository.findByClientAndId(client, noteId);
|
||||
officeId = client.officeId();
|
||||
}
|
||||
break;
|
||||
case GROUP: {
|
||||
final Long groupId = command.getGroupId();
|
||||
resourceId = groupId;
|
||||
Group group = this.groupRepository.findById(groupId).orElseThrow(() -> new GroupNotFoundException(groupId));
|
||||
noteForUpdate = this.noteRepository.findByGroupAndId(group, noteId);
|
||||
final var group = groupRepository.findById(resourceId).orElseThrow(() -> new GroupNotFoundException(resourceId));
|
||||
note = noteRepository.findByGroupAndId(group, noteId);
|
||||
officeId = group.officeId();
|
||||
}
|
||||
break;
|
||||
case LOAN: {
|
||||
resourceId = command.getLoanId();
|
||||
final Loan loan = this.loanRepository.findOneWithNotFoundDetection(resourceId);
|
||||
noteForUpdate = this.noteRepository.findByLoanAndId(loan, noteId);
|
||||
final var loan = loanRepository.findOneWithNotFoundDetection(resourceId);
|
||||
note = noteRepository.findByLoanAndId(loan, noteId);
|
||||
officeId = loan.getOfficeId();
|
||||
}
|
||||
break;
|
||||
case LOAN_TRANSACTION: {
|
||||
resourceId = command.subentityId();
|
||||
final Long loanTransactionId = resourceId;
|
||||
final LoanTransaction loanTransaction = this.loanTransactionRepository.findById(loanTransactionId)
|
||||
.orElseThrow(() -> new LoanTransactionNotFoundException(loanTransactionId));
|
||||
noteForUpdate = this.noteRepository.findByLoanTransactionAndId(loanTransaction, noteId);
|
||||
final var loanTransaction = loanTransactionRepository.findById(resourceId)
|
||||
.orElseThrow(() -> new LoanTransactionNotFoundException(resourceId));
|
||||
note = noteRepository.findByLoanTransactionAndId(loanTransaction, noteId);
|
||||
officeId = loanTransaction.getLoan().getOfficeId();
|
||||
}
|
||||
break;
|
||||
case SAVING_ACCOUNT: {
|
||||
final Long savinsAccountId = command.getSavingsId();
|
||||
final SavingsAccount savingAccount = this.savingsAccountRepository.findById(savinsAccountId)
|
||||
.orElseThrow(() -> new SavingsAccountNotFoundException(savinsAccountId));
|
||||
|
||||
noteForUpdate = this.noteRepository.findBySavingsAccountAndId(savingAccount, noteId);
|
||||
final var savingAccount = savingsAccountRepository.findById(resourceId)
|
||||
.orElseThrow(() -> new SavingsAccountNotFoundException(resourceId));
|
||||
note = noteRepository.findBySavingsAccountAndId(savingAccount, noteId);
|
||||
officeId = savingAccount.getClient().getOffice().getId();
|
||||
}
|
||||
break;
|
||||
case SHARE_ACCOUNT:
|
||||
log.error("TODO Implement getNoteForDelete for SHARE_ACCOUNT");
|
||||
break;
|
||||
case SAVINGS_TRANSACTION:
|
||||
log.error("TODO Implement getNoteForDelete for SAVINGS_TRANSACTION");
|
||||
log.error("Not yet implemented: {}", type);
|
||||
break;
|
||||
}
|
||||
if (noteForUpdate == null) {
|
||||
|
||||
if (note == null) {
|
||||
throw new NoteNotFoundException(noteId, resourceId, type.name().toLowerCase());
|
||||
}
|
||||
return noteForUpdate;
|
||||
}
|
||||
|
||||
return Pair.of(note, officeId);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -23,7 +23,6 @@ import org.apache.fineract.portfolio.group.domain.GroupRepository;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||
import org.apache.fineract.portfolio.note.domain.NoteRepository;
|
||||
import org.apache.fineract.portfolio.note.serialization.NoteCommandFromApiJsonDeserializer;
|
||||
import org.apache.fineract.portfolio.note.service.NoteReadPlatformService;
|
||||
import org.apache.fineract.portfolio.note.service.NoteReadPlatformServiceImpl;
|
||||
import org.apache.fineract.portfolio.note.service.NoteWritePlatformService;
|
||||
@@ -47,8 +46,8 @@ public class NoteAutoConfiguration {
|
||||
@ConditionalOnMissingBean
|
||||
public NoteWritePlatformService noteWritePlatformService(NoteRepository noteRepository, ClientRepositoryWrapper clientRepository,
|
||||
GroupRepository groupRepository, LoanRepositoryWrapper loanRepository, LoanTransactionRepository loanTransactionRepository,
|
||||
NoteCommandFromApiJsonDeserializer fromApiJsonDeserializer, SavingsAccountRepository savingsAccountRepository) {
|
||||
SavingsAccountRepository savingsAccountRepository) {
|
||||
return new NoteWritePlatformServiceJpaRepositoryImpl(noteRepository, clientRepository, groupRepository, loanRepository,
|
||||
loanTransactionRepository, fromApiJsonDeserializer, savingsAccountRepository);
|
||||
loanTransactionRepository, savingsAccountRepository);
|
||||
}
|
||||
}
|
||||
|
||||
+6
-3
@@ -57,7 +57,8 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanOfficerService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanWritePlatformService;
|
||||
import org.apache.fineract.portfolio.note.service.NoteWritePlatformService;
|
||||
import org.apache.fineract.portfolio.note.data.NoteCreateRequest;
|
||||
import org.apache.fineract.portfolio.note.domain.NoteType;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccountRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService;
|
||||
@@ -67,6 +68,7 @@ import org.apache.fineract.portfolio.transfer.exception.ClientNotAwaitingTransfe
|
||||
import org.apache.fineract.portfolio.transfer.exception.ClientNotAwaitingTransferApprovalOrOnHoldException;
|
||||
import org.apache.fineract.portfolio.transfer.exception.TransferNotSupportedException;
|
||||
import org.apache.fineract.portfolio.transfer.exception.TransferNotSupportedException.TransferNotSupportedReason;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@@ -81,11 +83,11 @@ public class TransferWritePlatformServiceJpaRepositoryImpl implements TransferWr
|
||||
private final LoanRepositoryWrapper loanRepositoryWrapper;
|
||||
private final SavingsAccountRepositoryWrapper savingsAccountRepositoryWrapper;
|
||||
private final TransfersDataValidator transfersDataValidator;
|
||||
private final NoteWritePlatformService noteWritePlatformService;
|
||||
private final StaffRepositoryWrapper staffRepositoryWrapper;
|
||||
private final ClientTransferDetailsRepositoryWrapper clientTransferDetailsRepositoryWrapper;
|
||||
private final PlatformSecurityContext context;
|
||||
private final LoanOfficerService loanOfficerService;
|
||||
private final ApplicationEventPublisher eventPublisher;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@@ -466,7 +468,8 @@ public class TransferWritePlatformServiceJpaRepositoryImpl implements TransferWr
|
||||
client.updateProposedTransferDate(null);
|
||||
}
|
||||
|
||||
this.noteWritePlatformService.createAndPersistClientNote(client, jsonCommand);
|
||||
this.eventPublisher.publishEvent(NoteCreateRequest.builder().type(NoteType.CLIENT).resourceId(client.getId())
|
||||
.note(jsonCommand.stringValueOfParameterNamed("note")).build());
|
||||
this.clientTransferDetailsRepositoryWrapper
|
||||
.save(ClientTransferDetails.instance(client.getId(), client.getOffice().getId(), destinationOffice.getId(), transferDate,
|
||||
transferEventType.getValue(), DateUtils.getBusinessLocalDate(), this.context.authenticatedUser().getId()));
|
||||
|
||||
+5
-6
@@ -28,13 +28,13 @@ import org.apache.fineract.portfolio.group.domain.GroupRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanOfficerService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanWritePlatformService;
|
||||
import org.apache.fineract.portfolio.note.service.NoteWritePlatformService;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccountRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService;
|
||||
import org.apache.fineract.portfolio.transfer.data.TransfersDataValidator;
|
||||
import org.apache.fineract.portfolio.transfer.service.TransferWritePlatformService;
|
||||
import org.apache.fineract.portfolio.transfer.service.TransferWritePlatformServiceJpaRepositoryImpl;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@@ -47,14 +47,13 @@ public class TransferConfiguration {
|
||||
OfficeRepositoryWrapper officeRepository, CalendarInstanceRepository calendarInstanceRepository,
|
||||
LoanWritePlatformService loanWritePlatformService, GroupRepositoryWrapper groupRepository,
|
||||
LoanRepositoryWrapper loanRepositoryWrapper, TransfersDataValidator transfersDataValidator,
|
||||
NoteWritePlatformService noteWritePlatformService, StaffRepositoryWrapper staffRepositoryWrapper,
|
||||
SavingsAccountRepositoryWrapper savingsAccountRepositoryWrapper,
|
||||
StaffRepositoryWrapper staffRepositoryWrapper, SavingsAccountRepositoryWrapper savingsAccountRepositoryWrapper,
|
||||
SavingsAccountWritePlatformService savingsAccountWritePlatformService,
|
||||
ClientTransferDetailsRepositoryWrapper clientTransferDetailsRepositoryWrapper, PlatformSecurityContext context,
|
||||
LoanOfficerService loanOfficerService) {
|
||||
LoanOfficerService loanOfficerService, ApplicationEventPublisher eventPublisher) {
|
||||
return new TransferWritePlatformServiceJpaRepositoryImpl(clientRepositoryWrapper, officeRepository, calendarInstanceRepository,
|
||||
groupRepository, loanWritePlatformService, savingsAccountWritePlatformService, loanRepositoryWrapper,
|
||||
savingsAccountRepositoryWrapper, transfersDataValidator, noteWritePlatformService, staffRepositoryWrapper,
|
||||
clientTransferDetailsRepositoryWrapper, context, loanOfficerService);
|
||||
savingsAccountRepositoryWrapper, transfersDataValidator, staffRepositoryWrapper, clientTransferDetailsRepositoryWrapper,
|
||||
context, loanOfficerService, eventPublisher);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -487,30 +487,58 @@ resilience4j.retry.instances.postInterest.enable-exponential-backoff=${FINERACT_
|
||||
resilience4j.retry.instances.postInterest.exponential-backoff-multiplier=${FINERACT_PROCESS_POST_INTEREST_RETRY_EXPONENTIAL_BACKOFF_MULTIPLIER:2}
|
||||
resilience4j.retry.instances.postInterest.retryExceptions=${FINERACT_PROCESS_POST_INTEREST_RETRY_EXCEPTIONS:org.springframework.dao.ConcurrencyFailureException,org.eclipse.persistence.exceptions.OptimisticLockException,jakarta.persistence.OptimisticLockException,org.springframework.orm.jpa.JpaOptimisticLockingFailureException}
|
||||
|
||||
# business date
|
||||
|
||||
resilience4j.retry.instances.commandBusinessDateUpdate.max-attempts=${FINERACT_PROCESS_COMMAND_BUSINESS_DATE_UPDATE_RETRY_MAX_ATTEMPTS:3}
|
||||
resilience4j.retry.instances.commandBusinessDateUpdate.wait-duration=${FINERACT_PROCESS_COMMAND_BUSINESS_DATE_UPDATE_RETRY_WAIT_DURATION:1s}
|
||||
resilience4j.retry.instances.commandBusinessDateUpdate.enable-exponential-backoff=${FINERACT_PROCESS_COMMAND_BUSINESS_DATE_UPDATE_RETRY_ENABLE_EXPONENTIAL_BACKOFF:true}
|
||||
resilience4j.retry.instances.commandBusinessDateUpdate.exponential-backoff-multiplier=${FINERACT_PROCESS_COMMAND_BUSINESS_DATE_UPDATE_RETRY_EXPONENTIAL_BACKOFF_MULTIPLIER:2}
|
||||
resilience4j.retry.instances.commandBusinessDateUpdate.retryExceptions=${FINERACT_PROCESS_COMMAND_BUSINESS_DATE_UPDATE_RETRY_EXCEPTIONS:org.springframework.dao.ConcurrencyFailureException,org.eclipse.persistence.exceptions.OptimisticLockException,jakarta.persistence.OptimisticLockException,org.springframework.orm.jpa.JpaOptimisticLockingFailureException}
|
||||
|
||||
# cache
|
||||
|
||||
resilience4j.retry.instances.commandCacheSwitch.max-attempts=${FINERACT_PROCESS_COMMAND_CACHE_SWITCH_RETRY_MAX_ATTEMPTS:3}
|
||||
resilience4j.retry.instances.commandCacheSwitch.wait-duration=${FINERACT_PROCESS_COMMAND_CACHE_SWITCH_RETRY_WAIT_DURATION:1s}
|
||||
resilience4j.retry.instances.commandCacheSwitch.enable-exponential-backoff=${FINERACT_PROCESS_COMMAND_CACHE_SWITCH_RETRY_ENABLE_EXPONENTIAL_BACKOFF:true}
|
||||
resilience4j.retry.instances.commandCacheSwitch.exponential-backoff-multiplier=${FINERACT_PROCESS_COMMAND_CACHE_SWITCH_RETRY_EXPONENTIAL_BACKOFF_MULTIPLIER:2}
|
||||
resilience4j.retry.instances.commandCacheSwitch.retryExceptions=${FINERACT_PROCESS_COMMAND_CACHE_SWITCH_RETRY_EXCEPTIONS:org.springframework.dao.ConcurrencyFailureException,org.eclipse.persistence.exceptions.OptimisticLockException,jakarta.persistence.OptimisticLockException,org.springframework.orm.jpa.JpaOptimisticLockingFailureException}
|
||||
|
||||
# currency
|
||||
|
||||
resilience4j.retry.instances.commandCurrencyUpdate.max-attempts=${FINERACT_PROCESS_COMMAND_CURRENCY_UPDATE_RETRY_MAX_ATTEMPTS:3}
|
||||
resilience4j.retry.instances.commandCurrencyUpdate.wait-duration=${FINERACT_PROCESS_COMMAND_CURRENCY_UPDATE_RETRY_WAIT_DURATION:1s}
|
||||
resilience4j.retry.instances.commandCurrencyUpdate.enable-exponential-backoff=${FINERACT_PROCESS_COMMAND_CURRENCY_UPDATE_RETRY_ENABLE_EXPONENTIAL_BACKOFF:true}
|
||||
resilience4j.retry.instances.commandCurrencyUpdate.exponential-backoff-multiplier=${FINERACT_PROCESS_COMMAND_CURRENCY_UPDATE_RETRY_EXPONENTIAL_BACKOFF_MULTIPLIER:2}
|
||||
resilience4j.retry.instances.commandCurrencyUpdate.retryExceptions=${FINERACT_PROCESS_COMMAND_CURRENCY_UPDATE_RETRY_EXCEPTIONS:org.springframework.dao.ConcurrencyFailureException,org.eclipse.persistence.exceptions.OptimisticLockException,jakarta.persistence.OptimisticLockException,org.springframework.orm.jpa.JpaOptimisticLockingFailureException}
|
||||
|
||||
# external event configuration
|
||||
|
||||
resilience4j.retry.instances.commandExternalEventConfigurationUpdate.max-attempts=${FINERACT_PROCESS_COMMAND_EXTERNAL_EVENT_CONFIGURATION_UPDATE_RETRY_MAX_ATTEMPTS:3}
|
||||
resilience4j.retry.instances.commandExternalEventConfigurationUpdate.wait-duration=${FINERACT_PROCESS_COMMAND_EXTERNAL_EVENT_CONFIGURATION_UPDATE_RETRY_WAIT_DURATION:1s}
|
||||
resilience4j.retry.instances.commandExternalEventConfigurationUpdate.enable-exponential-backoff=${FINERACT_PROCESS_COMMAND_EXTERNAL_EVENT_CONFIGURATION_UPDATE_RETRY_ENABLE_EXPONENTIAL_BACKOFF:true}
|
||||
resilience4j.retry.instances.commandExternalEventConfigurationUpdate.exponential-backoff-multiplier=${FINERACT_PROCESS_COMMAND_EXTERNAL_EVENT_CONFIGURATION_UPDATE_RETRY_EXPONENTIAL_BACKOFF_MULTIPLIER:2}
|
||||
resilience4j.retry.instances.commandExternalEventConfigurationUpdate.retryExceptions=${FINERACT_PROCESS_COMMAND_EXTERNAL_EVENT_CONFIGURATION_UPDATE_RETRY_EXCEPTIONS:org.springframework.dao.ConcurrencyFailureException,org.eclipse.persistence.exceptions.OptimisticLockException,jakarta.persistence.OptimisticLockException,org.springframework.orm.jpa.JpaOptimisticLockingFailureException}
|
||||
|
||||
# note
|
||||
|
||||
resilience4j.retry.instances.commandNoteCreate.max-attempts=${FINERACT_PROCESS_COMMAND_NOTE_CREATE_RETRY_MAX_ATTEMPTS:3}
|
||||
resilience4j.retry.instances.commandNoteCreate.wait-duration=${FINERACT_PROCESS_COMMAND_NOTE_CREATE_RETRY_WAIT_DURATION:1s}
|
||||
resilience4j.retry.instances.commandNoteCreate.enable-exponential-backoff=${FINERACT_PROCESS_COMMAND_NOTE_CREATE_RETRY_ENABLE_EXPONENTIAL_BACKOFF:true}
|
||||
resilience4j.retry.instances.commandNoteCreate.exponential-backoff-multiplier=${FINERACT_PROCESS_COMMAND_NOTE_CREATE_RETRY_EXPONENTIAL_BACKOFF_MULTIPLIER:2}
|
||||
resilience4j.retry.instances.commandNoteCreate.retryExceptions=${FINERACT_PROCESS_COMMAND_NOTE_CREATE_RETRY_EXCEPTIONS:org.springframework.dao.ConcurrencyFailureException,org.eclipse.persistence.exceptions.OptimisticLockException,jakarta.persistence.OptimisticLockException,org.springframework.orm.jpa.JpaOptimisticLockingFailureException}
|
||||
|
||||
resilience4j.retry.instances.commandNoteUpdate.max-attempts=${FINERACT_PROCESS_COMMAND_NOTE_UPDATE_RETRY_MAX_ATTEMPTS:3}
|
||||
resilience4j.retry.instances.commandNoteUpdate.wait-duration=${FINERACT_PROCESS_COMMAND_NOTE_UPDATE_RETRY_WAIT_DURATION:1s}
|
||||
resilience4j.retry.instances.commandNoteUpdate.enable-exponential-backoff=${FINERACT_PROCESS_COMMAND_NOTE_UPDATE_RETRY_ENABLE_EXPONENTIAL_BACKOFF:true}
|
||||
resilience4j.retry.instances.commandNoteUpdate.exponential-backoff-multiplier=${FINERACT_PROCESS_COMMAND_NOTE_UPDATE_RETRY_EXPONENTIAL_BACKOFF_MULTIPLIER:2}
|
||||
resilience4j.retry.instances.commandNoteUpdate.retryExceptions=${FINERACT_PROCESS_COMMAND_NOTE_UPDATE_RETRY_EXCEPTIONS:org.springframework.dao.ConcurrencyFailureException,org.eclipse.persistence.exceptions.OptimisticLockException,jakarta.persistence.OptimisticLockException,org.springframework.orm.jpa.JpaOptimisticLockingFailureException}
|
||||
|
||||
resilience4j.retry.instances.commandNoteDelete.max-attempts=${FINERACT_PROCESS_COMMAND_NOTE_DELETE_RETRY_MAX_ATTEMPTS:3}
|
||||
resilience4j.retry.instances.commandNoteDelete.wait-duration=${FINERACT_PROCESS_COMMAND_NOTE_DELETE_RETRY_WAIT_DURATION:1s}
|
||||
resilience4j.retry.instances.commandNoteDelete.enable-exponential-backoff=${FINERACT_PROCESS_COMMAND_NOTE_DELETE_RETRY_ENABLE_EXPONENTIAL_BACKOFF:true}
|
||||
resilience4j.retry.instances.commandNoteDelete.exponential-backoff-multiplier=${FINERACT_PROCESS_COMMAND_NOTE_DELETE_RETRY_EXPONENTIAL_BACKOFF_MULTIPLIER:2}
|
||||
resilience4j.retry.instances.commandNoteDelete.retryExceptions=${FINERACT_PROCESS_COMMAND_NOTE_DELETE_RETRY_EXCEPTIONS:org.springframework.dao.ConcurrencyFailureException,org.eclipse.persistence.exceptions.OptimisticLockException,jakarta.persistence.OptimisticLockException,org.springframework.orm.jpa.JpaOptimisticLockingFailureException}
|
||||
|
||||
fineract.command.enabled=true
|
||||
fineract.command.executor=${FINERACT_COMMAND_EXECUTOR:sync}
|
||||
fineract.command.ring-buffer-size=${FINERACT_COMMAND_RING_BUFFER_SIZE:1024}
|
||||
@@ -518,6 +546,10 @@ fineract.command.producer-type=${FINERACT_COMMAND_PRODUCER_TYPE:single}
|
||||
fineract.command.auditable=${FINERACT_COMMAND_AUDITABLE:true}
|
||||
# this is duplicated on purpose to keep fineract-command independent; once all modules are migrated we clean up
|
||||
fineract.command.idempotency-key-header-name=${FINERACT_IDEMPOTENCY_KEY_HEADER_NAME:Idempotency-Key}
|
||||
fineract.command.file-dead-letter-queue-enabled=${FINERACT_FILE_DEAD_LETTER_QUEUE_ENABLED:false}
|
||||
fineract.command.file-dead-letter-queue-path=${FINERACT_FILE_DEAD_LETTER_QUEUE_PATH:/tmp/fineract-command-audit}
|
||||
|
||||
# command
|
||||
|
||||
resilience4j.retry.instances.commandAuditProcessing.max-attempts=${FINERACT_PROCESS_COMMAND_AUDIT_PROCESSING_RETRY_MAX_ATTEMPTS:3}
|
||||
resilience4j.retry.instances.commandAuditProcessing.wait-duration=${FINERACT_PROCESS_COMMAND_AUDIT_PROCESSING_RETRY_WAIT_DURATION:1s}
|
||||
|
||||
@@ -53,3 +53,8 @@ org.apache.fineract.reage.start-date.not-blank=The parameter 'startDate' is mand
|
||||
org.apache.fineract.reage.number-of-installments.not-blank=The parameter 'numberOfInstallments' is mandatory.
|
||||
org.apache.fineract.reage.number-of-installments.min=The parameter 'numberOfInstallments' must be at least 1.
|
||||
org.apache.fineract.frequency-type.invalid=The parameter 'frequencyType' must be valid PeriodFrequencyType value. Provided value: '${validatedValue}'.
|
||||
|
||||
# Note
|
||||
|
||||
org.apache.fineract.portfolio.note.note.size=The parameter 'note' cannot exceed 1000 characters
|
||||
org.apache.fineract.portfolio.note.note.not-null=The parameter 'note' cannot be empty
|
||||
|
||||
@@ -28,8 +28,6 @@ import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import org.apache.fineract.client.models.NoteData;
|
||||
import org.apache.fineract.client.models.PostResourceTypeResourceIdNotesResponse;
|
||||
import org.apache.fineract.integrationtests.common.ClientHelper;
|
||||
import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
|
||||
import org.apache.fineract.integrationtests.common.GroupHelper;
|
||||
@@ -41,6 +39,8 @@ import org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtens
|
||||
import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
|
||||
import org.apache.fineract.integrationtests.common.savings.SavingsAccountHelper;
|
||||
import org.apache.fineract.integrationtests.common.savings.SavingsProductHelper;
|
||||
import org.apache.fineract.portfolio.note.data.NoteCreateResponse;
|
||||
import org.apache.fineract.portfolio.note.data.NoteData;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -217,8 +217,7 @@ public class NotesTest {
|
||||
|
||||
// Notes
|
||||
final String payload = "{\"note\": \"" + noteText + "\"}";
|
||||
final PostResourceTypeResourceIdNotesResponse postNoteResponse = NotesHelper.createSavingsNote(requestSpec, responseSpec, savingsId,
|
||||
payload);
|
||||
final NoteCreateResponse postNoteResponse = NotesHelper.createSavingsNote(requestSpec, responseSpec, savingsId, payload);
|
||||
Assertions.assertNotNull(postNoteResponse);
|
||||
Assertions.assertNotNull(postNoteResponse.getResourceId());
|
||||
|
||||
|
||||
+5
-5
@@ -21,9 +21,9 @@ package org.apache.fineract.integrationtests.common;
|
||||
import com.google.gson.Gson;
|
||||
import io.restassured.specification.RequestSpecification;
|
||||
import io.restassured.specification.ResponseSpecification;
|
||||
import org.apache.fineract.client.models.NoteData;
|
||||
import org.apache.fineract.client.models.PostResourceTypeResourceIdNotesResponse;
|
||||
import org.apache.fineract.client.util.JSON;
|
||||
import org.apache.fineract.portfolio.note.data.NoteCreateResponse;
|
||||
import org.apache.fineract.portfolio.note.data.NoteData;
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public final class NotesHelper {
|
||||
@@ -210,11 +210,11 @@ public final class NotesHelper {
|
||||
// Example: org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper.disburseLoan(java.lang.Long,
|
||||
// org.apache.fineract.client.models.PostLoansLoanIdRequest)
|
||||
@Deprecated(forRemoval = true)
|
||||
public static PostResourceTypeResourceIdNotesResponse createSavingsNote(RequestSpecification requestSpec,
|
||||
ResponseSpecification responseSpec, Integer savingsId, String request) {
|
||||
public static NoteCreateResponse createSavingsNote(RequestSpecification requestSpec, ResponseSpecification responseSpec,
|
||||
Integer savingsId, String request) {
|
||||
final String noteURL = SAVINGS_URL + "/" + savingsId + "/notes?" + Utils.TENANT_IDENTIFIER;
|
||||
final String response = Utils.performServerPost(requestSpec, responseSpec, noteURL, request);
|
||||
return GSON.fromJson(response, PostResourceTypeResourceIdNotesResponse.class);
|
||||
return GSON.fromJson(response, NoteCreateResponse.class);
|
||||
}
|
||||
|
||||
public static NoteData retrieveSavingsNote(RequestSpecification requestSpec, ResponseSpecification responseSpec, Integer savingsId,
|
||||
|
||||
Reference in New Issue
Block a user