Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
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.ws.rs.Consumes;
import jakarta.ws.rs.DELETE;
Expand Down Expand Up @@ -54,9 +53,12 @@

@Path("/v1/charges")
@Component
@Tag(name = "Charges", description = "Its typical for MFIs to add extra costs for their financial products. These are typically Fees or Penalties.\n"
+ "\n" + "A Charge on fineract platform is what we use to model both Fees and Penalties.\n" + "\n"
+ "At present we support defining charges for use with Client accounts and both loan and saving products.")
@Tag(name = "Charges", description = """
Its typical for MFIs to add extra costs for their financial products. These are typically Fees or Penalties.

A Charge on fineract platform is what we use to model both Fees and Penalties.

At present we support defining charges for use with Client accounts and both loan and saving products.""")
@RequiredArgsConstructor
public class ChargesApiResource {

Expand All @@ -71,8 +73,12 @@ public class ChargesApiResource {
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Retrieve Charges", description = "Returns the list of defined charges.\n" + "\n" + "Example Requests:\n" + "\n"
+ "charges")
@Operation(summary = "Retrieve Charges", description = """
Returns the list of defined charges.

Example Requests:

charges""")
public List<ChargeData> retrieveAllCharges() {
context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
return readPlatformService.retrieveAllCharges();
Expand All @@ -82,10 +88,13 @@ public List<ChargeData> retrieveAllCharges() {
@Path("{chargeId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Retrieve a Charge", description = "Returns the details of a defined Charge.\n" + "\n" + "Example Requests:\n"
+ "\n" + "charges/1")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ChargesApiResourceSwagger.GetChargesResponse.class))) })
@Operation(summary = "Retrieve a Charge", description = """
Returns the details of a defined Charge.

Example Requests:

charges/1""")
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ChargesApiResourceSwagger.GetChargesResponse.class)))
public ChargeData retrieveCharge(@PathParam("chargeId") @Parameter(description = "chargeId") final Long chargeId,
@Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
Expand All @@ -104,8 +113,15 @@ public ChargeData retrieveCharge(@PathParam("chargeId") @Parameter(description =
@Path("template")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Retrieve Charge Template", description = "This is a convenience resource. It can be useful when building maintenance user interface screens for client applications. The template data returned consists of any or all of:\n"
+ "\n" + "Field Defaults\n" + "Allowed description Lists\n" + "Example Request:\n" + "\n" + "charges/template\n")
@Operation(summary = "Retrieve Charge Template", description = """
This is a convenience resource. It can be useful when building maintenance user interface screens for client applications. The template data returned consists of any or all of:

Field Defaults
Allowed description Lists
Example Request:

charges/template
""")
public ChargeData retrieveNewChargeDetails() {
context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
return readPlatformService.retrieveNewChargeDetails();
Expand All @@ -116,8 +132,7 @@ public ChargeData retrieveNewChargeDetails() {
@Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Create/Define a Charge", description = "Define a new charge that can later be associated with loans and savings through their respective product definitions or directly on each account instance.")
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = ChargeRequest.class)))
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ChargesApiResourceSwagger.PostChargesResponse.class))) })
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ChargesApiResourceSwagger.PostChargesResponse.class)))
public CommandProcessingResult createCharge(@Parameter(hidden = true) ChargeRequest chargeRequest) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().createCharge()
.withJson(toApiJsonSerializer.serialize(chargeRequest)).build();
Expand All @@ -130,8 +145,7 @@ public CommandProcessingResult createCharge(@Parameter(hidden = true) ChargeRequ
@Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Update a Charge", description = "Updates the details of a Charge.")
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = ChargeRequest.class)))
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ChargesApiResourceSwagger.PutChargesChargeIdResponse.class))) })
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ChargesApiResourceSwagger.PutChargesChargeIdResponse.class)))
public CommandProcessingResult updateCharge(@PathParam("chargeId") @Parameter(description = "chargeId") final Long chargeId,
@Parameter(hidden = true) ChargeRequest chargeRequest) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateCharge(chargeId)
Expand All @@ -143,8 +157,7 @@ public CommandProcessingResult updateCharge(@PathParam("chargeId") @Parameter(de
@Path("{chargeId}")
@Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Delete a Charge", description = "Deletes a Charge.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ChargesApiResourceSwagger.DeleteChargesChargeIdResponse.class))) })
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ChargesApiResourceSwagger.DeleteChargesChargeIdResponse.class)))
public CommandProcessingResult deleteCharge(@PathParam("chargeId") @Parameter(description = "chargeId") final Long chargeId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteCharge(chargeId).build();
return commandsSourceWritePlatformService.logCommandSource(commandRequest);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public static Set<String> getAllValues() {

@Override
public String toString() {
return name().toString().replaceAll("_", " ");
return name().replace("_", " ");
}

public String getValue() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,32 +39,17 @@ public enum ClientStatus {

public static ClientStatus fromInt(final Integer statusValue) {

ClientStatus enumeration = ClientStatus.INVALID;
switch (statusValue) {
case 100:
enumeration = ClientStatus.PENDING;
break;
case 300:
enumeration = ClientStatus.ACTIVE;
break;
case 303:
enumeration = ClientStatus.TRANSFER_IN_PROGRESS;
break;
case 304:
enumeration = ClientStatus.TRANSFER_ON_HOLD;
break;
case 600:
enumeration = ClientStatus.CLOSED;
break;
case 700:
enumeration = ClientStatus.REJECTED;
break;
case 800:
enumeration = ClientStatus.WITHDRAWN;
break;
return switch (statusValue) {
case 100 -> ClientStatus.PENDING;
case 300 -> ClientStatus.ACTIVE;
case 303 -> ClientStatus.TRANSFER_IN_PROGRESS;
case 304 -> ClientStatus.TRANSFER_ON_HOLD;
case 600 -> ClientStatus.CLOSED;
case 700 -> ClientStatus.REJECTED;
case 800 -> ClientStatus.WITHDRAWN;
default -> ClientStatus.INVALID;
};

}
return enumeration;
}

public static ClientStatus fromString(final String clientString) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
Expand All @@ -61,15 +62,18 @@
@Table(name = "m_appuser", uniqueConstraints = @UniqueConstraint(columnNames = { "username" }, name = "username_org"))
public class AppUser extends AbstractPersistableCustom<Long> implements PlatformUser {

@Getter
@Column(name = "email", nullable = false, length = 100)
private String email;

@Column(name = "username", nullable = false, length = 100)
private String username;

@Getter
@Column(name = "firstname", nullable = false, length = 100)
private String firstname;

@Getter
@Column(name = "lastname", nullable = false, length = 100)
private String lastname;

Expand All @@ -94,27 +98,33 @@ public class AppUser extends AbstractPersistableCustom<Long> implements Platform
@Column(name = "is_deleted", nullable = false)
private boolean deleted;

@Getter
@ManyToOne
@JoinColumn(name = "office_id", nullable = false)
private Office office;

@Getter
@ManyToOne
@JoinColumn(name = "staff_id", nullable = true)
private Staff staff;

@Getter
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "m_appuser_role", joinColumns = @JoinColumn(name = "appuser_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles;

@Getter
@Column(name = "last_time_password_updated")
private LocalDate lastTimePasswordUpdated;

@Column(name = "password_never_expires", nullable = false)
private boolean passwordNeverExpires;

@Getter
@Column(name = "is_self_service_user", nullable = false)
private boolean isSelfServiceUser;

@Getter
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "appUser")
private Set<AppUserClientMapping> appUserClientMappings = new HashSet<>();

Expand Down Expand Up @@ -206,14 +216,13 @@ public Map<String, Object> changePassword(final JsonCommand command, final Platf

private void updatePassword(JsonCommand command, PlatformPasswordEncoder platformPasswordEncoder, Map<String, Object> actualChanges) {
final String passwordParamName = PASSWORD;
if (command.hasParameter(passwordParamName)) {
if (command.isChangeInPasswordParameterNamed(passwordParamName, this.password, platformPasswordEncoder, getId())) {
final String passwordEncodedValue = command.passwordValueOfParameterNamed(passwordParamName, platformPasswordEncoder,
getId());
actualChanges.put(passwordParamName, true);
updatePassword(passwordEncodedValue);
}
if (command.hasParameter(passwordParamName)
&& command.isChangeInPasswordParameterNamed(passwordParamName, this.password, platformPasswordEncoder, getId())) {
final String passwordEncodedValue = command.passwordValueOfParameterNamed(passwordParamName, platformPasswordEncoder, getId());
actualChanges.put(passwordParamName, true);
updatePassword(passwordEncodedValue);
}

}

public void updatePassword(final String encodePassword) {
Expand Down Expand Up @@ -303,20 +312,18 @@ public Map<String, Object> update(final JsonCommand command, final PlatformPassw

final String passwordNeverExpire = "passwordNeverExpires";

if (command.hasParameter(passwordNeverExpire)) {
if (command.isChangeInBooleanParameterNamed(passwordNeverExpire, this.passwordNeverExpires)) {
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(passwordNeverExpire);
actualChanges.put(passwordNeverExpire, newValue);
this.passwordNeverExpires = newValue;
}
if (command.hasParameter(passwordNeverExpire)
&& command.isChangeInBooleanParameterNamed(passwordNeverExpire, this.passwordNeverExpires)) {
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(passwordNeverExpire);
actualChanges.put(passwordNeverExpire, newValue);
this.passwordNeverExpires = newValue;
}

if (command.hasParameter(AppUserConstants.IS_SELF_SERVICE_USER)) {
if (command.isChangeInBooleanParameterNamed(AppUserConstants.IS_SELF_SERVICE_USER, this.isSelfServiceUser)) {
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(AppUserConstants.IS_SELF_SERVICE_USER);
actualChanges.put(AppUserConstants.IS_SELF_SERVICE_USER, newValue);
this.isSelfServiceUser = newValue;
}
if (command.hasParameter(AppUserConstants.IS_SELF_SERVICE_USER)
&& command.isChangeInBooleanParameterNamed(AppUserConstants.IS_SELF_SERVICE_USER, this.isSelfServiceUser)) {
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(AppUserConstants.IS_SELF_SERVICE_USER);
actualChanges.put(AppUserConstants.IS_SELF_SERVICE_USER, newValue);
this.isSelfServiceUser = newValue;
}

if (this.isSelfServiceUser && command.hasParameter(AppUserConstants.CLIENTS)) {
Expand Down Expand Up @@ -345,7 +352,7 @@ private String[] getRolesAsIdStringArray() {
roleIds.add(role.getId().toString());
}

return roleIds.toArray(new String[roleIds.size()]);
return roleIds.toArray(new String[0]);
}

/**
Expand All @@ -372,11 +379,7 @@ public boolean isDeleted() {

public boolean isSystemUser() {
// TODO Determine system user by ID not by user name
if (this.username.equals(AppUserConstants.SYSTEM_USER_NAME)) {
return true;
}

return false;
return this.username.equals(AppUserConstants.SYSTEM_USER_NAME);
}

@Override
Expand Down Expand Up @@ -440,38 +443,10 @@ public boolean isBypassUser() {
return hasAnyPermission("BYPASS_LOAN_WRITE_PROTECTION");
}

public String getFirstname() {
return this.firstname;
}

public String getLastname() {
return this.lastname;
}

public String getEmail() {
return this.email;
}

public Set<Role> getRoles() {
return this.roles;
}

public Office getOffice() {
return this.office;
}

public Staff getStaff() {
return this.staff;
}

public boolean getPasswordNeverExpires() {
return this.passwordNeverExpires;
}

public LocalDate getLastTimePasswordUpdated() {
return this.lastTimePasswordUpdated;
}

public boolean canNotApproveLoanInPast() {
return hasNotPermissionForAnyOf("ALL_FUNCTIONS", "APPROVEINPAST_LOAN");
}
Expand All @@ -494,11 +469,7 @@ public boolean canNotMakeRepaymentOnLoanInPast() {

public boolean hasNotPermissionForReport(final String reportName) {

if (hasNotPermissionForAnyOf("ALL_FUNCTIONS", "ALL_FUNCTIONS_READ", "REPORTING_SUPER_USER", "READ_" + reportName)) {
return true;
}

return false;
return hasNotPermissionForAnyOf("ALL_FUNCTIONS", "ALL_FUNCTIONS_READ", "REPORTING_SUPER_USER", "READ_" + reportName);
}

public boolean hasNotPermissionForDatatable(final String datatable, final String accessType) {
Expand All @@ -507,18 +478,10 @@ public boolean hasNotPermissionForDatatable(final String datatable, final String

if (accessType.equalsIgnoreCase("READ")) {

if (hasNotPermissionForAnyOf("ALL_FUNCTIONS", "ALL_FUNCTIONS_READ", matchPermission)) {
return true;
}

return false;
}

if (hasNotPermissionForAnyOf("ALL_FUNCTIONS", matchPermission)) {
return true;
return hasNotPermissionForAnyOf("ALL_FUNCTIONS", "ALL_FUNCTIONS_READ", matchPermission);
}

return false;
return hasNotPermissionForAnyOf("ALL_FUNCTIONS", matchPermission);
}

public boolean hasNotPermissionForAnyOf(final String... permissionCodes) {
Expand Down Expand Up @@ -696,12 +659,11 @@ public String getEncodedPassword(final JsonCommand command, final PlatformPasswo
passwordEncodedValue = command.passwordValueOfParameterNamed(passwordParamName, platformPasswordEncoder, getId());

}
} else if (command.hasParameter(passwordEncodedParamName)) {
if (command.isChangeInStringParameterNamed(passwordEncodedParamName, this.password)) {
} else if (command.hasParameter(passwordEncodedParamName)
&& command.isChangeInStringParameterNamed(passwordEncodedParamName, this.password)) {

passwordEncodedValue = command.stringValueOfParameterNamed(passwordEncodedParamName);
passwordEncodedValue = command.stringValueOfParameterNamed(passwordEncodedParamName);

}
}

return passwordEncodedValue;
Expand All @@ -711,17 +673,9 @@ public boolean isNotEnabled() {
return !isEnabled();
}

public boolean isSelfServiceUser() {
return this.isSelfServiceUser;
}

public Set<AppUserClientMapping> getAppUserClientMappings() {
return this.appUserClientMappings;
}

private Set<AppUserClientMapping> createAppUserClientMappings(Collection<Client> clients) {
Set<AppUserClientMapping> newAppUserClientMappings = null;
if (clients != null && clients.size() > 0) {
if (clients != null && !clients.isEmpty()) {
newAppUserClientMappings = new HashSet<>();
for (Client client : clients) {
newAppUserClientMappings.add(new AppUserClientMapping(this, client));
Expand Down
Loading
Loading