Merge branch 'develop' into patch-1

This commit is contained in:
Michael Vorburger ⛑️
2019-02-16 00:20:20 +01:00
committed by GitHub
303 changed files with 25508 additions and 1784 deletions
Executable → Regular
+18 -6
View File
@@ -1,5 +1,3 @@
#!/bin/bash
#
# 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
@@ -17,10 +15,24 @@
# specific language governing permissions and limitations
# under the License.
#
language: java
jdk:
- openjdk8
# https://docs.travis-ci.com/user/languages/java/#caching
before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
cache:
directories:
- $HOME/.gradle/caches/
- $HOME/.gradle/wrapper/
- $HOME/.m2
cd fineract-provider
# NOTE: The --info, while quite a bit more verbose, is VERY useful to understand failures on Travis,
# where you do not have access to any files like build/reports/tests/index.html, only the Console.
# where you do not have access to any files like build/reports/tests/index.html, only the Console.
# @see http://mrhaki.blogspot.ch/2013/05/gradle-goodness-show-more-information.html
# @see http://forums.gradle.org/gradle/topics/whats_new_in_gradle_1_1_test_logging for alternative
./gradlew --info clean licenseMain licenseTest licenseIntegrationTest test
# @see http://forums.gradle.org/gradle/topics/whats_new_in_gradle_1_1_test_logging for alternative
script:
- ./gradlew --info licenseMain licenseTest licenseIntegrationTest test
+19 -9
View File
@@ -1,20 +1,22 @@
Apache Fineract: A Platform for Microfinance
Apache Fineract: A Platform for Microfinance [![Build Status](https://travis-ci.org/apache/fineract.svg?branch=develop)](https://travis-ci.org/apache/fineract)
============
The next evolution of Apache Fineract focuses on being faster, lighter and cheaper to change (than the existing Mifos) so that it is more responsive to the needs of Microfinance Institutions and Integrators.
Requirements
============
* Java >= 1.8 (Oracle JVMS have been tested)
* Java >= 1.8 (Oracle JVMs have been tested)
* gradle-wrapper.jar version 2.10
* MySQL 5.5
Instructions to download gradle wrapper
============
By running following command, it will download the gradle wrapper from Fineract git repository and puts under fineract-provider/gradle/wrapper
By running following command, it will download the gradle wrapper from Fineract git repository and put it under fineract-provider/gradle/wrapper
wget --no-check-certificate -P fineract-provider/gradle/wrapper https://github.com/apache/incubator-fineract/raw/develop/fineract-provider/gradle/wrapper/gradle-wrapper.jar
(or)
curl --insecure -L https://github.com/apache/incubator-fineract/raw/develop/fineract-provider/gradle/wrapper/gradle-wrapper.jar > fineract-provider/gradle/wrapper/gradle-wrapper.jar
Instructions to run Apache RAT (Release Audit Tool)
@@ -32,41 +34,49 @@ Instructions to build a war file
Instructions to execute Integration tests
============
1. Login to mysql DB using `mysql -u root -pmysql`
2. Create the mifosplatform-tenants database using `CREATE DATABASE mifosplatform-tenants`.
3. Create the default tenant database using `CREATE DATABASE mifostenant-default`.
1. Login to mysql DB using `mysql -u root -p mysql`
> Note that if this is the first time to access MySQL DB, then you may need to reset your password.
2. Create the mifosplatform-tenants database using `CREATE DATABASE mifosplatform_tenants`.
3. Create the default tenant database using `CREATE DATABASE mifostenant_default`.
4. Download gradle-wrapper.jar version 2.10 and place it in the fineract-provider/gradle/wrapper folder. See 'Instructions to download gradle wrapper' above.
5. Run the following commands:
1. `./gradlew migrateTenantListDB -PdbName=mifosplatform-tenants`
2. `./gradlew migrateTenantDB -PdbName=mifostenant-default`
6. Run `./gradlew clean integrationTest`
7. Run `./gradlew tomcatRunWar`
Version
============
The latest stable release can be viewed on the develop branch: [Latest Release on Develop](https://github.com/apache/incubator-fineract/tree/develop "Latest Release"), [View change log](https://github.com/apache/incubator-fineract/blob/develop/CHANGELOG.md "Latest release changelog")
The latest stable release can be viewed on the develop branch: [Latest Release on Develop](https://github.com/apache/incubator-fineract/tree/develop "Latest Release").
The progress of this project can be viewed here: [View change log](https://github.com/apache/incubator-fineract/blob/develop/CHANGELOG.md "Latest release change log")
License
============
This project is licensed under Apache License Version 2.0. See <https://github.com/apache/incubator-fineract/blob/develop/LICENSE.md>.
This project is licensed under Apache License Version 2.0. See <https://github.com/apache/incubator-fineract/blob/develop/LICENSE.md> for referece.
Apache Fineract Platform API
============
The API for the Fineract-platform (project named 'Apache Fineract') is documented in the API-docs under <b>Full API Matrix</b> and can be viewed [here](https://demo.openmf.org/api-docs/apiLive.htm "API Documentation").
The API for the Fineract-platform (project named 'Apache Fineract') is documented in the API-docs under <b><i>Full API Matrix</i></b> and can be viewed [here](https://demo.openmf.org/api-docs/apiLive.htm "API Documentation").
Online Demos
============
* [Community App](https://demo.openmf.org "Reference Client App")
> For this demo, a demo account is also provided for users to experience the functionality of this Community App. Users can use "mifos" for USERNAME and "password" for PASSWORD(without quotation marks).
Developers
============
Please see <https://cwiki.apache.org/confluence/display/FINERACT/Contributor%27s+Zone> for the developers wiki page.
Please refer to <https://cwiki.apache.org/confluence/display/FINERACT/Fineract+101> for first time contribution for this project.
Please see <https://cwiki.apache.org/confluence/display/FINERACT/How-to+articles> for technical details to get started.
Roadmap
============
+1831 -2
View File
File diff suppressed because it is too large Load Diff
-27
View File
@@ -1,27 +0,0 @@
#!/bin/bash
#
# 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.
#
set -e
# https://developer.cloudbees.com/bin/view/DEV/Node+Builds
curl -s -o use-node https://repository-cloudbees.forge.cloudbees.com/distributions/ci-addons/node/use-node
NODE_VERSION=0.11.12 . ./use-node
./build.sh
-38
View File
@@ -1,38 +0,0 @@
#!/bin/bash
#
# 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.
#
# Exit the script if any command returns a non-true return value (http://www.davidpashley.com/articles/writing-robust-shell-scripts/)
set -e
git --version
# TODO UNCOMMENT THIS once https://github.com/openMF/mifosx/pull/1291 is merged!
# git pull
# This does NOT get the most recent revision from the submodule repository.
# Instead, it only gets the revision of the submodule that is recorded in the revision of the main repository.
## NOT git submodule update --remote
# The following is very important, because even if the main (API) repo is latest,
# the sub-module initially will be a fixed old rev. and only this grabs real latest:
git submodule foreach 'git checkout develop && git pull --ff-only origin develop'
cd apps/community-app
./build.sh
cd ../../fineract-provider/
./gradlew -Penv=dev clean dist
+23 -21
View File
@@ -77,7 +77,7 @@ openjpa {
files = fileTree(sourceSets.main.output.classesDir).matching {
include '**/AbstractPersistableCustom.class'
include '**/domain/*.class'
}
enforcePropertyRestrictions = true
}
@@ -86,7 +86,7 @@ rat {
xmlOutput = false
htmlOutput = false
plainOutput = true
verbose = false
verbose = false
// inputDir = './..'
reportDir = new File(buildDir,'reports/rat')
excludes = [
@@ -109,7 +109,9 @@ rat {
'**/*.iml',
//Notice files
'**/NOTICE_RELEASE',
'**/NOTICE_SOURCE',
'**/NOTICE_SOURCE',
// Swagger License
'**/src/main/resources/swagger-ui/**',
// gradle
'**/.gradle/**',
'**/gradlew',
@@ -120,8 +122,8 @@ rat {
'**/native/**',
'**/wrapper/**',
'**/build/**',
//Api Docs
//Api Docs
'**/api-docs/*.*',
'**/docs/system-architecture/.htaccess',
'**/docs/system-architecture/404.html',
@@ -129,14 +131,14 @@ rat {
'**/docs/system-architecture/**/*.xml',
'**/bootstrap-3.0.0/assets/application.js',
'**/system-architecture/js/plugins.js',
//Apache License
'**/bootstrap-3.0.0/assets/less.js',
'**/css/bootstrap-3.0.0/**/*.*',
//Public Domain See http://www.JSON.org/js.html
'**/bootstrap-3.0.0/assets/json2.js.htm',
// MIT License
'**/modernizr-2.6.2.min.js',
'**/css/normalize.css',
@@ -151,7 +153,7 @@ rat {
'**/system-architecture/js/vendor/toc-0.1.2/jquery.toc.min.js',
'**/assets/respond.min.js',
'**/assets/html5shiv.js',
//BSD License
'**/assets/uglify.js'
]
@@ -254,7 +256,7 @@ task dist(type:Zip){
include '**/*'
into('database/migrations')
}
from war.outputs.files
into(baseName + '-' + version)
}
@@ -268,7 +270,7 @@ pmd {
}
findbugs {
ignoreFailures = true
sourceSets = [sourceSets.main]
sourceSets = [sourceSets.main]
}
war {
@@ -283,7 +285,7 @@ war {
}
rename ('LICENSE_RELEASE', 'LICENSE')
rename ('NOTICE_RELEASE', 'NOTICE')
from('../DISCLAIMER') { // notice the parens
into "WEB-INF/" // no leading slash
}
@@ -292,7 +294,7 @@ war {
license {
header rootProject.file('../APACHE_LICENSETEXT.md')
excludes(["**/*.html", "**/*.mustache", "**/package-info.java", "**/keystore.jks"])
excludes(["**/*.html", "**/*.mustache", "**/package-info.java", "**/keystore.jks", "**/swagger-ui/**"])
strictCheck true
}
@@ -437,7 +439,7 @@ task migrateTenantDB<<{
if (rootProject.hasProperty("dbName")) {
tenantDbName = rootProject.getProperty("dbName")
}
flyway.url= "jdbc:mysql:thin://localhost:3306/$tenantDbName"
flyway.driver = "org.drizzle.jdbc.DrizzleDriver"
flyway.locations= [filePath]
@@ -448,13 +450,13 @@ task migrateTenantDB<<{
task showTenantDBInfo<<{
description="Shows the migration info for a Tenant DB. Optionally can pass dbName. Defaults to 'mifostenant-default' (Example: -PdbName=someTenantDBname)"
def filePath = "filesystem:$projectDir" + '/src/main/resources/sql/migrations/core_db'
def tenantDbName = 'mifostenant-default';
if (rootProject.hasProperty("dbName")) {
tenantDbName = rootProject.getProperty("dbName")
}
flyway.url= "jdbc:mysql:thin://localhost:3306/$tenantDbName"
flyway.driver = "org.drizzle.jdbc.DrizzleDriver"
flyway.locations= [filePath]
@@ -470,7 +472,7 @@ task migrateTenantListDB<<{
if (rootProject.hasProperty("dbName")) {
tenantsDbName = rootProject.getProperty("dbName")
}
flyway.url= "jdbc:mysql:thin://localhost:3306/$tenantsDbName"
flyway.driver = "org.drizzle.jdbc.DrizzleDriver"
flyway.locations= [filePath]
@@ -480,13 +482,13 @@ task migrateTenantListDB<<{
task showTenantListDBInfo<<{
description="Shows the migration info for a List DB. Optionally can pass dbName. Defaults to 'mifosplatform-tenants' (Example: -PdbName=someDBname)"
def filePath = "filesystem:$projectDir" + '/src/main/resources/sql/migrations/list_db'
def tenantsDbName = 'mifosplatform-tenants';
if (rootProject.hasProperty("dbName")) {
tenantsDbName = rootProject.getProperty("dbName")
}
flyway.url= "jdbc:mysql:thin://localhost:3306/$tenantsDbName"
flyway.driver = "org.drizzle.jdbc.DrizzleDriver"
flyway.locations= [filePath]
@@ -495,13 +497,13 @@ task showTenantListDBInfo<<{
task repairTenantDB<<{
description="repair migrate"
def filePath = "filesystem:$projectDir" + '/src/main/resources/sql/migrations/list_db'
def tenantsDbName = 'mifosplatform-tenants';
if (rootProject.hasProperty("dbName")) {
tenantsDbName = rootProject.getProperty("dbName")
}
flyway.url= "jdbc:mysql:thin://localhost:3306/$tenantsDbName"
flyway.driver = "org.drizzle.jdbc.DrizzleDriver"
flyway.locations= [filePath]
+3 -1
View File
@@ -91,10 +91,12 @@ dependencies {
[group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.3.5'],
// Once we've switched to Java 8 this dep can be removed.
//[group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.0']
[group: 'io.swagger', name: 'swagger-jersey-jaxrs', version: '1.5.15'],
[group: 'org.springframework', name:'spring-jms'],
[group: 'org.apache.activemq', name: 'activemq-broker']
)
)
testCompile 'junit:junit:4.11',
'junit:junit-dep:4.11',
'org.mockito:mockito-core:1.9.5',
+4 -1
View File
@@ -90,9 +90,12 @@ dependencies {
[group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.3.5'],
// Once we've switched to Java 8 this dep can be removed.
//[group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.0']
[group: 'io.swagger', name: 'swagger-jersey-jaxrs', version: '1.5.15'],
[group: 'org.springframework', name:'spring-jms'],
[group: 'org.apache.activemq', name: 'activemq-broker']
)
)
testCompile 'junit:junit:4.11',
'junit:junit-dep:4.11',
'org.mockito:mockito-core:1.9.5',
@@ -24,6 +24,8 @@ import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import io.swagger.annotations.*;
// import org.apache.fineract.accounting.accrual.swagger.runaccuralPost;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
@@ -36,6 +38,7 @@ import org.springframework.stereotype.Component;
@Path("/runaccruals")
@Component
@Scope("singleton")
@Api(value = "Periodic Accrual Accounting", description = "Periodic Accrual is to accrue the loan income till the specific date or till batch job scheduled time.\n\n ")
public class AccrualAccountingApiResource {
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
@@ -52,7 +55,10 @@ public class AccrualAccountingApiResource {
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String executePeriodicAccrualAccounting(final String jsonRequestBody) {
@ApiOperation(value = "Executes Periodic Accrual Accounting", httpMethod = "POST", notes = "Mandatory Fields\n" + "\n" + "tillDate\n")
@ApiImplicitParams({@ApiImplicitParam(paramType = "body", required = true, type = "body", dataTypeClass = AccrualAccountingApiResourceSwagger.PostRunaccrualsRequest.class, value = "Request Body\n" + "\n" + "Field Descriptions: \n" + "tillDate: \n" + "which specifies periodic accruals should happen till the given Date" )})
@ApiResponses({@ApiResponse(code = 200, message = "OK")})
public String executePeriodicAccrualAccounting( @ApiParam(hidden = true) final String jsonRequestBody) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().excuteAccrualAccounting().withJson(jsonRequestBody).build();
@@ -0,0 +1,46 @@
/**
* 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.accounting.accrual.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
* Created by sanyam on 24/7/17.
*/
final class AccrualAccountingApiResourceSwagger {
private AccrualAccountingApiResourceSwagger() {
// don't allow to instantiate; use only for live API documentation
}
@ApiModel(value = "runaccrualsRequest")
public static final class PostRunaccrualsRequest {
private PostRunaccrualsRequest() {
// don't allow to instantiate; use only for live API documentation
}
@ApiModelProperty(example = "en")
public String locale;
@ApiModelProperty(example = "dd MMMM yyyy")
public String dateFormat;
@ApiModelProperty(example = "04 June 2014", notes = "which specifies periodic accruals should happen till the given Date", required = true)
public String tillDate;
}
}
@@ -36,6 +36,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
import org.apache.fineract.accounting.closure.data.GLClosureData;
import org.apache.fineract.accounting.closure.service.GLClosureReadPlatformService;
import org.apache.fineract.commands.domain.CommandWrapper;
@@ -54,6 +55,7 @@ import org.springframework.stereotype.Component;
@Path("/glclosures")
@Component
@Scope("singleton")
@Api(value = "Accounting Closure", description = "An accounting closure indicates that no more journal entries may be logged (or reversed) in the system, either manually or via the portfolio with an entry date prior to the defined closure date\n" + "\n" + "Field Descriptions\n" + "closingDate\n" + "The date for which the accounting closure is defined\n" + "officeId\n" + "The identifer of the branch for which accounting has been closed\n" + "comments\n" + "Description associated with an Accounting closure")
public class GLClosuresApiResource {
private static final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList("id", "officeId", "officeName",
@@ -85,7 +87,9 @@ public class GLClosuresApiResource {
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveAllClosures(@Context final UriInfo uriInfo, @QueryParam("officeId") final Long officeId) {
@ApiOperation(value = "List Accounting closures", notes = "Example Requests:\n" + "\n" + "glclosures")
@ApiResponses({@ApiResponse(code = 200, response = GLClosuresApiResourceSwagger.GetGlClosureResponse.class, message = "", responseContainer = "list")})
public String retrieveAllClosures(@Context final UriInfo uriInfo, @QueryParam("officeId") @ApiParam(value = "officeId") final Long officeId) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermission);
final List<GLClosureData> glClosureDatas = this.glClosureReadPlatformService.retrieveAllGLClosures(officeId);
@@ -98,7 +102,9 @@ public class GLClosuresApiResource {
@Path("{glClosureId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retreiveClosure(@PathParam("glClosureId") final Long glClosureId, @Context final UriInfo uriInfo) {
@ApiOperation(value = "Retrieve an Accounting Closure", notes = "Example Requests:\n" + "\n" + "glclosures/1\n" + "\n" + "\n" + "/glclosures/1?fields=officeName,closingDate")
@ApiResponses({@ApiResponse(code = 200, message = "", response = GLClosuresApiResourceSwagger.GetGlClosureResponse.class)})
public String retreiveClosure(@PathParam("glClosureId") @ApiParam(value = "glClosureId") final Long glClosureId, @Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermission);
@@ -112,10 +118,14 @@ public class GLClosuresApiResource {
return this.apiJsonSerializerService.serialize(settings, glClosureData, RESPONSE_DATA_PARAMETERS);
}
// NOTE: proposal slight changes @Aleks
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String createGLClosure(final String jsonRequestBody) {
@ApiOperation(value = "Create an Accounting Closure", notes = "Mandatory Fields\n" + "officeId,closingDate")
@ApiImplicitParams({@ApiImplicitParam(paramType = "body", required = true, type = "body", dataTypeClass = GLClosuresApiResourceSwagger.PostGlClosuresRequest.class, value = "Request Body")})
@ApiResponses({@ApiResponse(code = 200, message = "", response = GLClosuresApiResourceSwagger.PostGlClosuresResponse.class)})
public String createGLClosure(@ApiParam(hidden = true) final String jsonRequestBody) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().createGLClosure().withJson(jsonRequestBody).build();
@@ -128,7 +138,10 @@ public class GLClosuresApiResource {
@Path("{glClosureId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String updateGLClosure(@PathParam("glClosureId") final Long glClosureId, final String jsonRequestBody) {
@ApiOperation(value = "Update an Accounting closure", notes = "Once an accounting closure is created, only the comments associated with it may be edited")
@ApiImplicitParams({@ApiImplicitParam(paramType = "body", value = "Request body", dataType = "body", dataTypeClass = GLClosuresApiResourceSwagger.PutGlClosuresRequest.class, required = true)})
@ApiResponses({@ApiResponse(code = 200, message = "", response = GLClosuresApiResourceSwagger.PutGlClosuresResponse.class)})
public String updateGLClosure(@PathParam("glClosureId") @ApiParam(value = "glClosureId") final Long glClosureId, @ApiParam(hidden = true) final String jsonRequestBody) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateGLClosure(glClosureId).withJson(jsonRequestBody).build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
@@ -140,7 +153,9 @@ public class GLClosuresApiResource {
@Path("{glClosureId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String deleteGLClosure(@PathParam("glClosureId") final Long glClosureId) {
@ApiOperation(value = "Delete an accounting closure", notes = "Note: Only the latest accounting closure associated with a branch may be deleted.")
@ApiResponses({@ApiResponse(code = 200, message = "", response = GLClosuresApiResourceSwagger.DeleteGlClosuresResponse.class)})
public String deleteGLClosure(@PathParam("glClosureId") @ApiParam(value = "glclosureId") final Long glClosureId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteGLClosure(glClosureId).build();
@@ -0,0 +1,133 @@
/**
* 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.accounting.closure.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.joda.time.LocalDate;
import java.lang.reflect.Array;
import java.util.ArrayList;
final class GLClosuresApiResourceSwagger {
private GLClosuresApiResourceSwagger() {
// don't allow to instantiate; use only for live API documentation
}
/**
* TODO: describe where this belongs: {@link GLClosuresApiResource }
* {@Link GLClosuresApiResource}
*/
// Check !!
@ApiModel(value = "GetGLClosureResponse")
public static final class GetGlClosureResponse {
private GetGlClosureResponse() {
// dont allow to initiatiate
}
@ApiModelProperty(example = "7")
public Long id;
@ApiModelProperty(example = "1")
public Long officeId;
@ApiModelProperty(example = "Head Office")
public String officeName;
@ApiModelProperty(example = "2013,1,2")
public LocalDate closingDate;
@ApiModelProperty(example = "false")
public boolean deleted;
@ApiModelProperty(example = "2013,1,3")
public LocalDate createdDate;
@ApiModelProperty(example = "2013,1,3")
public LocalDate lastUpdatedDate;
@ApiModelProperty(example = "1")
public Long createdByUserId;
@ApiModelProperty(example = "mifos")
public String createdByUsername;
@ApiModelProperty(example = "1")
public Long lastUpdatedByUserId;
@ApiModelProperty(example = "mifos")
public String lastUpdatedByUsername;
@ApiModelProperty(example = "closed")
public String comments;
}
@ApiModel(value = "PostGLCLosuresRequest")
public static final class PostGlClosuresRequest {
private PostGlClosuresRequest() {
// don't allow to instantiate; use only for live API documentation
}
@ApiModelProperty(example = "1")
public Long officeId;
@ApiModelProperty(example = "06 December 2012")
public LocalDate closingDate;
@ApiModelProperty(example = "The accountants are heading for a carribean vacation")
public String comments;
@ApiModelProperty(example = "en")
public String locale;
@ApiModelProperty(example = "dd MMMM yyyy")
public String dateFormat;
}
@ApiModel(value = "PostGlClosuresResponse")
public static final class PostGlClosuresResponse {
private PostGlClosuresResponse() {
// don't allow to instantiate; use only for live API documentation
}
@ApiModelProperty(example = "1")
public Long officeId;
@ApiModelProperty(example = "9")
public Long resourceId;
}
@ApiModel(value = "PutGlClosuresRequest")
public static final class PutGlClosuresRequest {
private PutGlClosuresRequest() {
// don't allow to instantiate; use only for live API documentation
}
@ApiModelProperty(example = "All transactions verified by Johnny Cash")
public String comments;
}
@ApiModel(value = "PutGlClosuresResponse")
public static final class PutGlClosuresResponse{
private PutGlClosuresResponse() {
// don't allow to instantiate; use only for live API documentation
}
@ApiModelProperty(example = "1")
public Long officeId;
@ApiModelProperty(example = "9")
public Long resourceId;
@ApiModelProperty(example = "All transactions verified by Johnny Cash")
public String comments;
}
@ApiModel(value = "DeleteGlClosuresResponse")
public static final class DeleteGlClosuresResponse{
private DeleteGlClosuresResponse(){
}
@ApiModelProperty(example = "1")
public Long officeId;
@ApiModelProperty(example = "9")
public Long resourceId;
}
}
@@ -32,7 +32,9 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
import org.apache.fineract.accounting.financialactivityaccount.data.FinancialActivityAccountData;
import org.apache.fineract.accounting.financialactivityaccount.data.FinancialActivityData;
import org.apache.fineract.accounting.financialactivityaccount.service.FinancialActivityAccountReadPlatformService;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
@@ -49,6 +51,7 @@ import org.springframework.stereotype.Component;
@Path("/financialactivityaccounts")
@Component
@Scope("singleton")
@Api(value = "Mapping Financial Activities to Accounts", description = "Organization Level Financial Activities like Asset and Liability Transfer can be mapped to GL Account. Integrated accounting takes these accounts into consideration when an Account transfer is made between a savings to loan/savings account and vice-versa\n" + "\n" +"\nField Descriptions\n" +"financialActivityId\n" +"The identifier of the Financial Activity\n" +"glAccountId\n" +"The identifier of a GL Account ( Ledger Account) which shall be used as the default account for the selected Financial Activity")
public class FinancialActivityAccountsApiResource {
private final FinancialActivityAccountReadPlatformService financialActivityAccountReadPlatformService;
@@ -89,6 +92,8 @@ public class FinancialActivityAccountsApiResource {
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@ApiOperation(value = "List Financial Activities to Accounts Mappings", notes = "Example Requests:\n" + "\n" + "financialactivityaccounts")
@ApiResponses({@ApiResponse(code = 200, message = "", response = FinancialActivityAccountsApiResourceSwagger.GetFinancialActivityAccountsResponse.class, responseContainer = "list" )})
public String retrieveAll(@Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(FinancialActivityAccountsConstants.resourceNameForPermission);
@@ -103,7 +108,9 @@ public class FinancialActivityAccountsApiResource {
@Path("{mappingId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retreive(@PathParam("mappingId") final Long mappingId, @Context final UriInfo uriInfo) {
@ApiOperation(value = "Retrieve a Financial Activity to Account Mapping\n", notes = "Example Requests:\n" + "\n" + "financialactivityaccounts/1")
@ApiResponses({@ApiResponse(code = 200, message = "", response = FinancialActivityAccountsApiResourceSwagger.GetFinancialActivityAccountsResponse.class)})
public String retreive(@PathParam("mappingId") @ApiParam(value = "mappingId") final Long mappingId, @Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(FinancialActivityAccountsConstants.resourceNameForPermission);
@@ -121,7 +128,10 @@ public class FinancialActivityAccountsApiResource {
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String createGLAccount(final String jsonRequestBody) {
@ApiOperation(value = "Create a new Financial Activity to Accounts Mapping", notes = "Mandatory Fields\n" + "financialActivityId, glAccountId")
@ApiImplicitParams({@ApiImplicitParam(value = "Request body", paramType = "body", dataType = "body", dataTypeClass = FinancialActivityAccountsApiResourceSwagger.PostFinancialActivityAccountsRequest.class)})
@ApiResponses({@ApiResponse(code = 200, message = "", response = FinancialActivityAccountsApiResourceSwagger.PostFinancialActivityAccountsResponse.class)})
public String createGLAccount(@ApiParam(hidden = true) final String jsonRequestBody) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().createOfficeToGLAccountMapping().withJson(jsonRequestBody)
.build();
@@ -135,7 +145,10 @@ public class FinancialActivityAccountsApiResource {
@Path("{mappingId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String updateGLAccount(@PathParam("mappingId") final Long mappingId, final String jsonRequestBody) {
@ApiOperation(value = "Update a Financial Activity to Account Mapping", notes = "the API updates the Ledger account linked to a Financial Activity \n")
@ApiImplicitParams({@ApiImplicitParam(value = "Request body", dataType = "body", paramType = "body", dataTypeClass = FinancialActivityAccountsApiResourceSwagger.PostFinancialActivityAccountsRequest.class)})
@ApiResponses({@ApiResponse(code = 200, message = "", response = FinancialActivityAccountsApiResourceSwagger.PutFinancialActivityAccountsResponse.class)})
public String updateGLAccount(@PathParam("mappingId") @ApiParam(value = "mappingId") final Long mappingId, @ApiParam(hidden = true) final String jsonRequestBody) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateOfficeToGLAccountMapping(mappingId)
.withJson(jsonRequestBody).build();
@@ -149,7 +162,9 @@ public class FinancialActivityAccountsApiResource {
@Path("{mappingId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String deleteGLAccount(@PathParam("mappingId") final Long mappingId) {
@ApiOperation(value = "Delete a Financial Activity to Account Mapping")
@ApiResponses({@ApiResponse(code = 200, message = "OK", response = FinancialActivityAccountsApiResourceSwagger.DeleteFinancialActivityAccountsResponse.class)})
public String deleteGLAccount(@PathParam("mappingId") @ApiParam(value = "mappingId") final Long mappingId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteOfficeToGLAccountMapping(mappingId).build();
@@ -0,0 +1,103 @@
/**
* 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.accounting.financialactivityaccount.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.fineract.accounting.financialactivityaccount.data.FinancialActivityData;
import org.apache.fineract.accounting.glaccount.data.GLAccountData;
import java.util.List;
import java.util.Map;
/**
* Created by sanyam on 24/7/17.
*/
final class FinancialActivityAccountsApiResourceSwagger {
private FinancialActivityAccountsApiResourceSwagger() {
}
@ApiModel(value = "GetFinancialActivityAccountsResponse")
public static final class GetFinancialActivityAccountsResponse{
private GetFinancialActivityAccountsResponse() {
}
@ApiModelProperty(example = "1")
public Long id;
public FinancialActivityData financialActivityData;
public GLAccountData glAccountData;
}
@ApiModel(value = "PostFinancialActivityAccountsRequest")
public static final class PostFinancialActivityAccountsRequest{
private PostFinancialActivityAccountsRequest() {
}
@ApiModelProperty(example = "200")
public Long financialActivityId;
@ApiModelProperty(example = "2")
public Long glAccountId;
}
@ApiModel(value = "PostFinancialActivityAccountsResponse")
public static final class PostFinancialActivityAccountsResponse{
private PostFinancialActivityAccountsResponse() {
}
@ApiModelProperty(example = "1")
public Long resourceId;
}
@ApiModel(value = "PutFinancialActivityAccountsRequest")
public static final class PutFinancialActivityAccountsRequest{
private PutFinancialActivityAccountsRequest() {
}
@ApiModelProperty(example = "200")
public Long financialActivityId;
@ApiModelProperty(example = "3")
public Long glAccountId;
}
@ApiModel(value = "PutFinancialActivityAccountsResponse")
public static final class PutFinancialActivityAccountsResponse{
private PutFinancialActivityAccountsResponse() {
}
public final class PutFinancialActivityAccountscommentsSwagger{
private PutFinancialActivityAccountscommentsSwagger(){}
@ApiModelProperty(example = "1")
public Long glAccountId;
}
@ApiModelProperty(example = "1")
public Long resourceId;
public PutFinancialActivityAccountscommentsSwagger comments;
}
@ApiModel(value = "DeleteFinancialActivityAccountsResponse")
public static final class DeleteFinancialActivityAccountsResponse{
private DeleteFinancialActivityAccountsResponse() {
}
@ApiModelProperty(example = "1")
public Long resourceId;
}
}
@@ -39,6 +39,8 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
import io.swagger.models.parameters.HeaderParameter;
import com.sun.jersey.core.header.FormDataContentDisposition;
import com.sun.jersey.multipart.FormDataParam;
import org.apache.fineract.accounting.common.AccountingConstants;
@@ -68,6 +70,7 @@ import org.springframework.stereotype.Component;
@Path("/glaccounts")
@Component
@Scope("singleton")
@Api(value = "General Ledger Account", description = "Ledger accounts represent an Individual account within an Organizations Chart Of Accounts(COA) and are assigned a name and unique number by which they can be identified. \n" + "All transactions relating to a company's assets, liabilities, owners' equity, revenue and expenses are recorded against these accounts")
public class GLAccountsApiResource {
private static final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList("id", "name", "parentId", "glCode",
@@ -113,7 +116,9 @@ public class GLAccountsApiResource {
@Path("template")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveNewAccountDetails(@Context final UriInfo uriInfo, @QueryParam("type") final Integer type) {
@ApiOperation(value = "Retrieve GL Accounts Template", notes = "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 Value Lists\n" + "Example Request:\n" + "\n" + "glaccounts/template\n" + "glaccounts/template?type=1\n" + "\n" + "type is optional and integer value from 1 to 5.\n" + "\n" + "1.Assets \n" + "2.Liabilities \n" + "3.Equity \n" + "4.Income \n" + "5.Expenses")
@ApiResponses({@ApiResponse(code = 200, message = "", response = GLAccountsApiResourceSwagger.GetGLAccountsTemplateResponse.class)})
public String retrieveNewAccountDetails(@Context final UriInfo uriInfo, @QueryParam("type") @ApiParam(value = "type") final Integer type) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermission);
@@ -127,10 +132,12 @@ public class GLAccountsApiResource {
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveAllAccounts(@Context final UriInfo uriInfo, @QueryParam("type") final Integer type,
@QueryParam("searchParam") final String searchParam, @QueryParam("usage") final Integer usage,
@QueryParam("manualEntriesAllowed") final Boolean manualEntriesAllowed, @QueryParam("disabled") final Boolean disabled,
@QueryParam("fetchRunningBalance") final boolean runningBalance) {
@ApiOperation(value = "List General Ledger Accounts", notes = "ARGUMENTS\n" + "type Integer optional manualEntriesAllowed boolean optional usage Integer optional disabled boolean optional parentId Long optional tagId Long optional\n" + "Example Requests:\n" + "\n" + "glaccounts\n" + "\n" + "\n" + "glaccounts?type=1&manualEntriesAllowed=true&usage=1&disabled=false\n" + "\n" + "glaccounts?fetchRunningBalance=true")
@ApiResponses({@ApiResponse(code = 200, message = "", response = GLAccountsApiResourceSwagger.GetGLAccountsResponse.class, responseContainer = "list")})
public String retrieveAllAccounts(@Context final UriInfo uriInfo, @QueryParam("type") @ApiParam(value = "type") final Integer type,
@QueryParam("searchParam") @ApiParam(value = "searchParam") final String searchParam, @QueryParam("usage") @ApiParam(value = "usage") final Integer usage,
@QueryParam("manualEntriesAllowed") @ApiParam(value = "manualEntriesAllowed") final Boolean manualEntriesAllowed, @QueryParam("disabled") @ApiParam(value = "disabled") final Boolean disabled,
@QueryParam("fetchRunningBalance") @ApiParam(value = "fetchRunningBalance") final boolean runningBalance) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermission);
JournalEntryAssociationParametersData associationParametersData = new JournalEntryAssociationParametersData(false, runningBalance);
@@ -145,8 +152,10 @@ public class GLAccountsApiResource {
@Path("{glAccountId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retreiveAccount(@PathParam("glAccountId") final Long glAccountId, @Context final UriInfo uriInfo,
@QueryParam("fetchRunningBalance") final boolean runningBalance) {
@ApiOperation(value = "Retrieve a General Ledger Account", notes = "Example Requests:\n" + "\n" + "glaccounts/1\n" + "\n" + "\n" + "glaccounts/1?template=true\n" + "\n" + "\n" + "glaccounts/1?fields=name,glCode\n" + "\n" + "\n" + "glaccounts/1?fetchRunningBalance=true")
@ApiResponses({@ApiResponse(code = 200, message = "", response = GLAccountsApiResourceSwagger.GetGLAccountsResponse.class)})
public String retreiveAccount(@PathParam("glAccountId") @ApiParam(value = "glAccountId") final Long glAccountId, @Context final UriInfo uriInfo,
@QueryParam("fetchRunningBalance") @ApiParam(value = "fetchRunningBalance") final boolean runningBalance) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermission);
@@ -163,7 +172,10 @@ public class GLAccountsApiResource {
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String createGLAccount(final String jsonRequestBody) {
@ApiOperation(value = "Create a General Ledger Account", notes = "Note: You may optionally create Hierarchical Chart of Accounts by using the \"parentId\" property of an Account\n" + "Mandatory Fields: \n" + "name, glCode, type, usage and manualEntriesAllowed")
@ApiImplicitParams({@ApiImplicitParam(paramType = "body", value = "body", dataType = "body", dataTypeClass = GLAccountsApiResourceSwagger.PostGLAccountsRequest.class )})
@ApiResponses({@ApiResponse(code = 200, message = "", response = GLAccountsApiResourceSwagger.PostGLAccountsResponse.class)})
public String createGLAccount(@ApiParam(hidden = true) final String jsonRequestBody) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().createGLAccount().withJson(jsonRequestBody).build();
@@ -176,7 +188,10 @@ public class GLAccountsApiResource {
@Path("{glAccountId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String updateGLAccount(@PathParam("glAccountId") final Long glAccountId, final String jsonRequestBody) {
@ApiOperation(value = "Update an Accounting closure", notes = "Once an accounting closure is created, only the comments associated with it may be edited\n" + "\n")
@ApiImplicitParams({@ApiImplicitParam(paramType = "body", value = "body", dataType = "body", dataTypeClass = GLAccountsApiResourceSwagger.PutGLAccountsRequest.class)})
@ApiResponses({@ApiResponse(code = 200, message = "", response = GLAccountsApiResourceSwagger.PutGLAccountsResponse.class)})
public String updateGLAccount(@PathParam("glAccountId") @ApiParam(value = "glAccountId") final Long glAccountId, @ApiParam(hidden = true) final String jsonRequestBody) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateGLAccount(glAccountId).withJson(jsonRequestBody).build();
@@ -189,7 +204,9 @@ public class GLAccountsApiResource {
@Path("{glAccountId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String deleteGLAccount(@PathParam("glAccountId") final Long glAccountId) {
@ApiOperation(value = "Delete an accounting closure", notes = "Note: Only the latest accounting closure associated with a branch may be deleted.")
@ApiResponses({@ApiResponse(code = 200, message = "", response = GLAccountsApiResourceSwagger.DeleteGLAccountsRequest.class)})
public String deleteGLAccount(@PathParam("glAccountId") @ApiParam(value = "glAccountId") final Long glAccountId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteGLAccount(glAccountId).build();
@@ -0,0 +1,190 @@
/**
* 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.accounting.glaccount.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.fineract.accounting.glaccount.data.GLAccountData;
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
import java.util.Collection;
import java.util.List;
/**
* Created by sanyam on 24/7/17.
*/
final class GLAccountsApiResourceSwagger {
private GLAccountsApiResourceSwagger() {
}
@ApiModel(value = "GetGLAccountsResponse")
public static final class GetGLAccountsResponse{
private GetGLAccountsResponse(){
}
@ApiModelProperty(example = "16")
public Long id;
@ApiModelProperty(example = "Cash")
public String name;
@ApiModelProperty(example = "1")
public Long parentId;
@ApiModelProperty(example = "100001")
public String glCode;
@ApiModelProperty(example = "false")
public Boolean disabled;
@ApiModelProperty(example = "true")
public Boolean manualEntriesAllowed;
public EnumOptionData type;
public EnumOptionData usage;
@ApiModelProperty(example = "Desc")
public String description;
@ApiModelProperty(example = "....Cash")
public String nameDecorated;
public CodeValueData tagId;
@ApiModelProperty(example = "118437")
public Long organizationRunningBalance;
}
@ApiModel(value = "GetGLAccountsTemplateResponse")
public static final class GetGLAccountsTemplateResponse{
private GetGLAccountsTemplateResponse(){
}
@ApiModelProperty(example = "false")
public Boolean disabled;
@ApiModelProperty(example = "true")
public Boolean manualEntriesAllowed;
public EnumOptionData type;
public EnumOptionData usage;
public List<EnumOptionData> accountTypeOptions;
public List<EnumOptionData> usageOptions;
public List<GLAccountData> assetHeaderAccountOptions;
public List<GLAccountData> liabilityHeaderAccountOptions;
public List<GLAccountData> equityHeaderAccountOptions;
public List<GLAccountData> expenseHeaderAccountOptions;
public Collection<CodeValueData> allowedAssetsTagOptions;
public Collection<CodeValueData> allowedLiabilitiesTagOptions;
public Collection<CodeValueData> allowedEquityTagOptions;
public Collection<CodeValueData> allowedIncomeTagOptions;
public Collection<CodeValueData> allowedExpensesTagOptions;
}
@ApiModel(value = "PostGLAccountsRequest")
public static final class PostGLAccountsRequest{
private PostGLAccountsRequest(){
}
@ApiModelProperty(example = "Cash at Bangalore")
public String name;
@ApiModelProperty(example = "100001")
public String glCode;
@ApiModelProperty(example = "true")
public Boolean manualEntriesAllowed;
@ApiModelProperty(example = "1")
public String type;
@ApiModelProperty(example = "10")
public String tagId;
@ApiModelProperty(example = "1")
public Long parentId;
@ApiModelProperty(example = "1")
public EnumOptionData usage;
@ApiModelProperty(example = "Desc")
public String description;
}
@ApiModel(value = "PostGLAccountsResponse")
public static final class PostGLAccountsResponse{
private PostGLAccountsResponse() {
}
@ApiModelProperty(example = "22")
public int resourceId;
}
@ApiModel(value = "PutGLAccountsRequest")
public static final class PutGLAccountsRequest{
private PutGLAccountsRequest() {
}
@ApiModelProperty(example = "Cash at Bangalore")
public String name;
}
@ApiModel(value = "PutGLAccountsResponse")
public static final class PutGLAccountsResponse{
private PutGLAccountsResponse() {
}
@ApiModel
public static final class PutGLAccountsResponsechangesSwagger{
private PutGLAccountsResponsechangesSwagger(){}
@ApiModelProperty(example = "Cash at Bangalore")
public String name;
}
@ApiModelProperty(example = "1")
public int resourceId;
public PutGLAccountsResponsechangesSwagger changes;
}
@ApiModel(value = "DeleteGLAccountsRequest")
public static final class DeleteGLAccountsRequest{
private DeleteGLAccountsRequest() {
}
private static final class DeleteGLAccountsRequestchangesSwagger{
private DeleteGLAccountsRequestchangesSwagger(){}
}
@ApiModelProperty(example = "1")
public int resourceId;
private DeleteGLAccountsRequestchangesSwagger changes;
}
}
@@ -0,0 +1,108 @@
/**
* 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.accounting.glaccount.domain;
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
import javax.persistence.*;
import java.math.BigDecimal;
import java.util.Date;
@Entity
@Table(name = "m_trial_balance")
public class TrialBalance extends AbstractPersistableCustom<Long> {
@Column(name = "office_id", nullable = false)
private Long officeId;
@Column(name = "account_id", nullable = false)
private Long glAccountId;
@Column(name = "amount", nullable = false)
private BigDecimal amount;
@Column(name = "entry_date", nullable = false)
@Temporal(TemporalType.DATE)
private Date entryDate;
@Column(name = "created_date", nullable = true)
@Temporal(TemporalType.DATE)
private Date transactionDate;
@Column(name = "closing_balance", nullable = false)
private BigDecimal closingBalance;
public static TrialBalance getInstance(final Long officeId, final Long glAccountId,
final BigDecimal amount, final Date entryDate, final Date transactionDate) {
return new TrialBalance(officeId, glAccountId, amount, entryDate, transactionDate);
}
private TrialBalance(final Long officeId, final Long glAccountId,
final BigDecimal amount, final Date entryDate, final Date transactionDate) {
this.officeId = officeId;
this.glAccountId = glAccountId;
this.amount = amount;
this.entryDate = entryDate;
this.transactionDate = transactionDate;
}
protected TrialBalance() {
}
public Long getOfficeId() {
return officeId;
}
public Date getTransactionDate() {
return transactionDate;
}
public BigDecimal getAmount() {
return amount;
}
public void setClosingBalance(final BigDecimal closingBalance) {
this.closingBalance = closingBalance;
}
public Date getEntryDate() {
return entryDate;
}
public Long getGlAccountId() {
return glAccountId;
}
@Override
public boolean equals(Object obj) {
if (!obj.getClass().equals(getClass())) return false;
TrialBalance trialBalance = (TrialBalance) obj;
return trialBalance.getOfficeId().equals(this.getOfficeId())
&& trialBalance.getGlAccountId().equals(this.getGlAccountId())
&& trialBalance.getEntryDate().equals(this.getEntryDate())
&& trialBalance.getTransactionDate().equals(this.getTransactionDate());
}
}
@@ -0,0 +1,33 @@
/**
* 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.accounting.glaccount.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
public interface TrialBalanceRepository extends JpaRepository<TrialBalance, Long>, JpaSpecificationExecutor<TrialBalance> {
@Query(value = "select * from m_trial_balance where office_id=:officeId and account_id=:accountId and closing_balance is null order by created_date, entry_date", nativeQuery = true)
List<TrialBalance> findNewByOfficeAndAccount(@Param("officeId") final Long officeId,
@Param("accountId") final Long accountId);
}
@@ -0,0 +1,47 @@
/**
* 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.accounting.glaccount.domain;
import org.apache.fineract.accounting.trialbalance.exception.TrialBalanceNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class TrialBalanceRepositoryWrapper {
private final TrialBalanceRepository repository;
@Autowired
public TrialBalanceRepositoryWrapper(final TrialBalanceRepository repository){
this.repository=repository;
}
public List<TrialBalance> findNewByOfficeAndAccount(final Long officeId, final Long accountId){
final List<TrialBalance> trialBalanceList=this.repository.findNewByOfficeAndAccount(officeId,accountId);
if (trialBalanceList==null)
throw new TrialBalanceNotFoundException(officeId,accountId);
return trialBalanceList;
}
public void save(final List<TrialBalance> tbRows){
this.repository.save(tbRows);
}
}
@@ -50,6 +50,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -177,10 +178,13 @@ public class GLAccountWritePlatformServiceJpaRepositoryImpl implements GLAccount
}
private void validateForAttachedProduct(Long glAccountId) {
String sql = "select count(*) from acc_product_mapping acc where acc.gl_account_id = "+glAccountId;
int count = this.jdbcTemplate.queryForObject(sql, Integer.class);
if(count>0){
throw new GLAccountDisableException();
String sql = "select count(*) from acc_product_mapping acc where acc.gl_account_id = ?";
try {
int count = this.jdbcTemplate.queryForObject(sql, Integer.class, glAccountId);
if (count > 0) {
throw new GLAccountDisableException();
}
} catch (EmptyResultDataAccessException e) {
}
}
@@ -36,9 +36,12 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
import com.sun.jersey.core.header.FormDataContentDisposition;
import com.sun.jersey.multipart.FormDataParam;
import org.apache.commons.lang.StringUtils;
import org.apache.fineract.accounting.journalentry.command.JournalEntryCommand;
import org.apache.fineract.accounting.journalentry.command.SingleDebitOrCreditEntryCommand;
import org.apache.fineract.accounting.journalentry.data.JournalEntryAssociationParametersData;
import org.apache.fineract.accounting.journalentry.data.JournalEntryData;
import org.apache.fineract.accounting.journalentry.data.OfficeOpeningBalancesData;
@@ -65,6 +68,7 @@ import org.springframework.stereotype.Component;
@Path("/journalentries")
@Component
@Scope("singleton")
@Api(value = "Journal Entries", description = "A journal entry refers to the logging of transactions against general ledger accounts. A journal entry may consist of several line items, each of which is either a \"debit\" or a \"credit\". The total amount of the debits must equal the total amount of the credits or the journal entry is said to be \"unbalanced\" \n" + "\n" + "A journal entry directly changes the account balances on the general ledger")
public class JournalEntriesApiResource {
private static final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList("id", "officeId", "officeName",
@@ -102,15 +106,17 @@ public class JournalEntriesApiResource {
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveAll(@Context final UriInfo uriInfo, @QueryParam("officeId") final Long officeId,
@QueryParam("glAccountId") final Long glAccountId, @QueryParam("manualEntriesOnly") final Boolean onlyManualEntries,
@QueryParam("fromDate") final DateParam fromDateParam, @QueryParam("toDate") final DateParam toDateParam,
@QueryParam("transactionId") final String transactionId, @QueryParam("entityType") final Integer entityType,
@QueryParam("offset") final Integer offset, @QueryParam("limit") final Integer limit,
@QueryParam("orderBy") final String orderBy, @QueryParam("sortOrder") final String sortOrder,
@QueryParam("locale") final String locale, @QueryParam("dateFormat") final String dateFormat,
@QueryParam("loanId") final Long loanId, @QueryParam("savingsId") final Long savingsId,
@QueryParam("runningBalance") final boolean runningBalance, @QueryParam("transactionDetails") final boolean transactionDetails) {
@ApiOperation(value = "List Journal Entries", notes = "The list capability of journal entries can support pagination and sorting.\n\n" + "Example Requests:\n" + "\n" + "journalentries\n" + "\n" + "journalentries?transactionId=PB37X8Y21EQUY4S\n" + "\n" + "journalentries?officeId=1&manualEntriesOnly=true&fromDate=1 July 2013&toDate=15 July 2013&dateFormat=dd MMMM yyyy&locale=en\n" + "\n" + "journalentries?fields=officeName,glAccountName,transactionDate\n" + "\n" + "journalentries?offset=10&limit=50\n" + "\n" + "journalentries?orderBy=transactionId&sortOrder=DESC\n" + "\n" + "journalentries?runningBalance=true\n" + "\n" + "journalentries?transactionDetails=true\n" + "\n" + "journalentries?loanId=12\n" + "\n" + "journalentries?savingsId=24")
@ApiResponses({@ApiResponse(code = 200, message = "", response = JournalEntryData.class, responseContainer = "list")})
public String retrieveAll(@Context final UriInfo uriInfo, @QueryParam("officeId") @ApiParam(value = "officeId") final Long officeId,
@QueryParam("glAccountId") @ApiParam(value = "glAccountId") final Long glAccountId, @QueryParam("manualEntriesOnly") @ApiParam(value = "manualEntriesOnly") final Boolean onlyManualEntries,
@QueryParam("fromDate") @ApiParam(value = "fromDate") final DateParam fromDateParam, @QueryParam("toDate") @ApiParam(value = "toDate") final DateParam toDateParam,
@QueryParam("transactionId") @ApiParam(value = "transactionId") final String transactionId, @QueryParam("entityType") @ApiParam(value = "entityType") final Integer entityType,
@QueryParam("offset") @ApiParam(value = "offset") final Integer offset, @QueryParam("limit") @ApiParam(value = "limit") final Integer limit,
@QueryParam("orderBy") @ApiParam(value = "orderBy") final String orderBy, @QueryParam("sortOrder") @ApiParam(value = "sortOrder") final String sortOrder,
@QueryParam("locale") @ApiParam(value = "locale") final String locale, @QueryParam("dateFormat") @ApiParam(value = "dateFormat") final String dateFormat,
@QueryParam("loanId") @ApiParam(value = "loanId") final Long loanId, @QueryParam("savingsId") @ApiParam(value = "savingsId") final Long savingsId,
@QueryParam("runningBalance") @ApiParam(value = "runningBalance") final boolean runningBalance, @QueryParam("transactionDetails") @ApiParam(value = "transactionDetails") final boolean transactionDetails) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermission);
@@ -138,8 +144,10 @@ public class JournalEntriesApiResource {
@Path("{journalEntryId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retreiveJournalEntryById(@PathParam("journalEntryId") final Long journalEntryId, @Context final UriInfo uriInfo,
@QueryParam("runningBalance") final boolean runningBalance, @QueryParam("transactionDetails") final boolean transactionDetails) {
@ApiOperation(value = "Retrieve a single Entry", notes = "Example Requests:\n" + "\n" + "journalentries/1\n" + "\n" + "\n" + "\n" + "journalentries/1?fields=officeName,glAccountId,entryType,amount\n" + "\n" + "journalentries/1?runningBalance=true\n" + "\n" + "journalentries/1?transactionDetails=true")
@ApiResponses({@ApiResponse(code = 200, message = "", response = JournalEntryData.class)})
public String retreiveJournalEntryById(@PathParam("journalEntryId") @ApiParam(value = "journalEntryId") final Long journalEntryId, @Context final UriInfo uriInfo,
@QueryParam("runningBalance") @ApiParam(value = "runningBalance") final boolean runningBalance, @QueryParam("transactionDetails") @ApiParam(value = "transactionDetails") final boolean transactionDetails) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermission);
JournalEntryAssociationParametersData associationParametersData = new JournalEntryAssociationParametersData(transactionDetails,
@@ -154,7 +162,10 @@ public class JournalEntriesApiResource {
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String createGLJournalEntry(final String jsonRequestBody, @QueryParam("command") final String commandParam) {
@ApiOperation(value = "Create \"Balanced\" Journal Entries", notes = "Note: A Balanced (simple) Journal entry would have atleast one \"Debit\" and one \"Credit\" entry whose amounts are equal \n" + "Compound Journal entries may have \"n\" debits and \"m\" credits where both \"m\" and \"n\" are greater than 0 and the net sum or all debits and credits are equal \n\n" + "\n" + "Mandatory Fields\n" + "officeId, transactionDate\n\n" + "\ncredits- glAccountId, amount, comments\n\n " + "\ndebits- glAccountId, amount, comments\n\n " + "\n" + "Optional Fields\n" + "paymentTypeId, accountNumber, checkNumber, routingCode, receiptNumber, bankNumber")
@ApiImplicitParams({@ApiImplicitParam(paramType = "body", value = "body", dataType = "body", dataTypeClass = JournalEntryCommand.class)})
@ApiResponses({@ApiResponse(code = 200, message = "", response = JournalEntriesApiResourceSwagger.PostJournalEntriesResponse.class)})
public String createGLJournalEntry(@ApiParam(hidden = true) final String jsonRequestBody, @QueryParam("command") @ApiParam(value = "command") final String commandParam) {
CommandProcessingResult result = null;
if (is(commandParam, "updateRunningBalance")) {
@@ -176,8 +187,11 @@ public class JournalEntriesApiResource {
@Path("{transactionId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String createReversalJournalEntry(final String jsonRequestBody, @PathParam("transactionId") final String transactionId,
@QueryParam("command") final String commandParam) {
@ApiOperation(value = "Update Running balances for Journal Entries", notes = "This API calculates the running balances for office. If office ID not provided this API calculates running balances for all offices. \n" + "Mandatory Fields\n" + "officeId")
@ApiImplicitParams({@ApiImplicitParam(paramType = "body", value = "body", dataType = "body", dataTypeClass = JournalEntriesApiResourceSwagger.PostJournalEntriesTransactionIdRequest.class)})
@ApiResponses({@ApiResponse(code = 200, message = "", response = JournalEntriesApiResourceSwagger.PostJournalEntriesTransactionIdResponse.class)})
public String createReversalJournalEntry(@ApiParam(hidden = true) final String jsonRequestBody, @PathParam("transactionId") @ApiParam(value = "transactionId") final String transactionId,
@QueryParam("command") @ApiParam(value = "command") final String commandParam) {
CommandProcessingResult result = null;
if (is(commandParam, "reverse")) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().reverseJournalEntry(transactionId).withJson(jsonRequestBody)
@@ -201,14 +215,14 @@ public class JournalEntriesApiResource {
SearchParameters params = SearchParameters.forPagination(offset, limit) ;
Page<JournalEntryData> entries = this.journalEntryReadPlatformService.retrieveAll(params, null, null, null, null, transactionId, PortfolioProductType.PROVISIONING.getValue(), null) ;
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.apiJsonSerializerService.serialize(settings, entries, RESPONSE_DATA_PARAMETERS);
return this.apiJsonSerializerService.serialize(settings, entries, RESPONSE_DATA_PARAMETERS);
}
@GET
@Path("openingbalance")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@Path("openingbalance")
public String retrieveOpeningBalance(@Context final UriInfo uriInfo, @QueryParam("officeId") final Long officeId,
@QueryParam("currencyCode") final String currencyCode) {
@@ -0,0 +1,61 @@
/**
* 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.accounting.journalentry.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.joda.time.LocalDate;
/**
* Created by sanyam on 25/7/17.
*/
final class JournalEntriesApiResourceSwagger {
private JournalEntriesApiResourceSwagger(){}
@ApiModel(value = "PostJournalEntriesResponse")
public static final class PostJournalEntriesResponse {
private PostJournalEntriesResponse(){
}
@ApiModelProperty(value = "1")
public Long officeId;
@ApiModelProperty(value = "RS9MCISID4WK1ZM")
public String transactionId;
}
@ApiModel(value = "PostJournalEntriesTransactionIdRequest")
public static final class PostJournalEntriesTransactionIdRequest {
private PostJournalEntriesTransactionIdRequest() {
}
@ApiModelProperty(value = "1")
public Long officeId;
}
@ApiModel(value = "PostJournalEntriesTransactionIdResponse")
public static final class PostJournalEntriesTransactionIdResponse {
private PostJournalEntriesTransactionIdResponse() {
}
@ApiModelProperty(value = "1")
public Long officeId;
}
}
@@ -116,15 +116,20 @@ public class CashBasedAccountingProcessorForShares implements AccountingProcesso
CASH_ACCOUNTS_FOR_SHARES.SHARES_EQUITY.getValue(), shareProductId, paymentTypeId, shareAccountId, transactionId,
transactionDate, amountForJE);
} else if (transactionDTO.getTransactionStatus().isRejected()) {
BigDecimal amountForJE = amount;
if (chargeAmount != null && chargeAmount.compareTo(BigDecimal.ZERO) == 1) {
amountForJE = amount.subtract(chargeAmount);
/*this.helper.revertCashBasedJournalEntryForSharesCharges(office, currencyCode, CASH_ACCOUNTS_FOR_SHARES.INCOME_FROM_FEES,
shareProductId, shareAccountId, transactionId, transactionDate, chargeAmount, feePayments);*/
this.helper.revertCashBasedJournalEntryForSharesCharges(office, currencyCode, CASH_ACCOUNTS_FOR_SHARES.INCOME_FROM_FEES,
shareProductId, shareAccountId, transactionId, transactionDate, chargeAmount, feePayments);
this.helper.createDebitJournalEntryForShares(office, currencyCode, CASH_ACCOUNTS_FOR_SHARES.SHARES_SUSPENSE.getValue(), shareProductId, paymentTypeId, shareAccountId,
transactionId, transactionDate, amount.subtract(chargeAmount));
this.helper.createCreditJournalEntryForShares(office, currencyCode, CASH_ACCOUNTS_FOR_SHARES.SHARES_REFERENCE.getValue(), shareProductId, paymentTypeId, shareAccountId,
transactionId, transactionDate, amount);
}else{
this.helper.createJournalEntriesForShares(office, currencyCode, CASH_ACCOUNTS_FOR_SHARES.SHARES_SUSPENSE.getValue(),
CASH_ACCOUNTS_FOR_SHARES.SHARES_REFERENCE.getValue(), shareProductId, paymentTypeId, shareAccountId, transactionId,
transactionDate, amount);
}
this.helper.createJournalEntriesForShares(office, currencyCode, CASH_ACCOUNTS_FOR_SHARES.SHARES_SUSPENSE.getValue(),
CASH_ACCOUNTS_FOR_SHARES.SHARES_REFERENCE.getValue(), shareProductId, paymentTypeId, shareAccountId, transactionId,
transactionDate, amountForJE);
}
}
@@ -29,6 +29,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
import org.apache.fineract.accounting.provisioning.constant.ProvisioningEntriesApiConstants;
import org.apache.fineract.accounting.provisioning.data.LoanProductProvisioningEntryData;
import org.apache.fineract.accounting.provisioning.data.ProvisioningEntryData;
@@ -55,6 +56,7 @@ import java.util.Set;
@Path("/provisioningentries")
@Component
@Scope("singleton")
@Api(value = "Provisioning Entries", description = "This defines the Provisioning Entries for all active loan products\n" + "\n" + "Field Descriptions\n" + "date\n" + "Date on which day provisioning entries should be created\n" + "createjournalentries\n" + "Boolean variable whether to add journal entries for generated provisioning entries\n")
public class ProvisioningEntriesApiResource {
private final PlatformSecurityContext platformSecurityContext;
@@ -84,7 +86,10 @@ public class ProvisioningEntriesApiResource {
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String createProvisioningEntries(final String apiRequestBodyAsJson) {
@ApiOperation(value = "Create new Provisioning Entries", notes = "Creates a new Provisioning Entries\n" + "\n" + "Mandatory Fields\n" + "date\n" + "dateFormat\n" + "locale\n" + "Optional Fields\n" + "createjournalentries")
@ApiImplicitParams({@ApiImplicitParam(paramType = "body", value = "body", dataType = "body", dataTypeClass = ProvisioningEntriesApiResourceSwagger.PostProvisioningEntriesRequest.class)})
@ApiResponses({@ApiResponse(code = 200, message = "", response = ProvisioningEntriesApiResourceSwagger.PostProvisioningEntriesResponse.class)})
public String createProvisioningEntries(@ApiParam(hidden = true) final String apiRequestBodyAsJson) {
CommandWrapper commandWrapper = null;
this.platformSecurityContext.authenticatedUser();
commandWrapper = new CommandWrapperBuilder().createProvisioningEntries().withJson(apiRequestBodyAsJson).build();
@@ -96,8 +101,11 @@ public class ProvisioningEntriesApiResource {
@Path("{entryId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String modifyProvisioningEntry(@PathParam("entryId") final Long entryId, @QueryParam("command") final String commandParam,
final String apiRequestBodyAsJson) {
@ApiOperation(value = "Recreates Provisioning Entry", notes = "Recreates Provisioning Entry | createjournalentry.")
@ApiImplicitParams({@ApiImplicitParam(paramType = "body", value = "body", dataType = "body", dataTypeClass = ProvisioningEntriesApiResourceSwagger.PutProvisioningEntriesRequest.class)})
@ApiResponses({@ApiResponse(code = 200, message = "", response = ProvisioningEntriesApiResourceSwagger.PutProvisioningEntriesResponse.class)})
public String modifyProvisioningEntry(@PathParam("entryId") @ApiParam(value = "entryId") final Long entryId, @QueryParam("command") @ApiParam(value = "command=createjournalentry\ncommand=recreateprovisioningentry") final String commandParam,
@ApiParam(hidden = true) final String apiRequestBodyAsJson) {
CommandWrapper commandWrapper = null;
this.platformSecurityContext.authenticatedUser();
if ("createjournalentry".equals(commandParam)) {
@@ -118,7 +126,9 @@ public class ProvisioningEntriesApiResource {
@Path("{entryId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveProvisioningEntry(@PathParam("entryId") final Long entryId, @Context final UriInfo uriInfo) {
@ApiOperation(value = "Retrieves a Provisioning Entry", notes = "Returns the details of a generated Provisioning Entry.")
@ApiResponses({@ApiResponse(code = 200, message = "", response = ProvisioningEntryData.class)})
public String retrieveProvisioningEntry(@PathParam("entryId") @ApiParam(value = "entryId") final Long entryId, @Context final UriInfo uriInfo) {
platformSecurityContext.authenticatedUser();
ProvisioningEntryData data = this.provisioningEntriesReadPlatformService.retrieveProvisioningEntryData(entryId);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
@@ -129,6 +139,7 @@ public class ProvisioningEntriesApiResource {
@Path("entries")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@ApiResponses({@ApiResponse(code = 200, message = "", response = LoanProductProvisioningEntryData.class)})
public String retrieveProviioningEntries(@QueryParam("entryId") final Long entryId, @QueryParam("offset") final Integer offset,
@QueryParam("limit") final Integer limit, @QueryParam("officeId") final Long officeId,
@QueryParam("productId") final Long productId, @QueryParam("categoryId") final Long categoryId, @Context final UriInfo uriInfo) {
@@ -142,7 +153,9 @@ public class ProvisioningEntriesApiResource {
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveAllProvisioningEntries(@QueryParam("offset") final Integer offset, @QueryParam("limit") final Integer limit,
@ApiOperation(value = "List all Provisioning Entries")
@ApiResponses({@ApiResponse(code = 200, message = "", response = ProvisioningEntryData.class, responseContainer = "list")})
public String retrieveAllProvisioningEntries(@QueryParam("offset") @ApiParam(value = "offset") final Integer offset, @QueryParam("limit") @ApiParam(value = "limit") final Integer limit,
@Context final UriInfo uriInfo) {
platformSecurityContext.authenticatedUser();
Page<ProvisioningEntryData> data = this.provisioningEntriesReadPlatformService.retrieveAllProvisioningEntries(offset, limit);
@@ -0,0 +1,80 @@
/**
* 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.accounting.provisioning.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
* Created by sanyam on 25/7/17.
*/
final class ProvisioningEntriesApiResourceSwagger {
private ProvisioningEntriesApiResourceSwagger() {
// only for Swagger Documentation
}
@ApiModel(value = "PostProvisioningEntriesRequest")
public static final class PostProvisioningEntriesRequest {
private PostProvisioningEntriesRequest() {
}
@ApiModelProperty(example = "16 October 2015")
public String date;
@ApiModelProperty(example = "en")
public String locale;
@ApiModelProperty(example = "dd MMMM yyyy")
public String dateFormat;
@ApiModelProperty(example = "true")
public String createjournalentries;
public String provisioningentry;
public String entries;
}
@ApiModel(value = "PostProvisioningEntriesResponse")
public static final class PostProvisioningEntriesResponse{
private PostProvisioningEntriesResponse() {
}
@ApiModelProperty(example = "1")
public Long resourceId;
}
@ApiModel(value = "PutProvisioningEntriesRequest")
public static final class PutProvisioningEntriesRequest{
private PutProvisioningEntriesRequest() {
}
@ApiModelProperty(example = "recreateprovisioningentry")
public String command;
}
@ApiModel(value = "PutProvisioningEntriesResponse")
public static final class PutProvisioningEntriesResponse{
private PutProvisioningEntriesResponse() {
}
@ApiModelProperty(example = "1")
public Long resourceId;
}
}
@@ -39,6 +39,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
import org.apache.fineract.accounting.common.AccountingConstants;
import org.apache.fineract.accounting.glaccount.data.GLAccountData;
import org.apache.fineract.accounting.glaccount.service.GLAccountReadPlatformService;
@@ -66,6 +67,7 @@ import org.springframework.stereotype.Component;
@Path("/accountingrules")
@Component
@Scope("singleton")
@Api(value = "Accounting Rules", description = "It is typical scenario in MFI's that non accountants pass journal entries on a regular basis. For Ex: A branch office might deposit their entire cash at hand to their Bank account at the end of a working day. The branch office users might not understand enough of accounting to figure out which account needs to get credited and which account needs to be debited to represent this transaction.\n" + "\n" + "Enter accounting rules, an abstraction on top of manual Journal entires for enabling simpler data entry. An accounting rule can define any of the following abstractions\n" + "\n" + "A Simple journal entry where both the credit and debit account have been preselected\n" + "A Simple journal entry where either credit or debit accounts have been limited to a pre-selected list of accounts (Ex: Debit account should be one of \"Bank of America\" of \"JP Morgan\" and credit account should be \"Cash\")\n" + "A Compound journal entry where multiple debits and / or multiple credits may be made amongst a set of preselected list of accounts (Ex: Credit account should be either \"Bank Of America\" or \"Cash\" and debit account can be \"Employee Salary\" and/or \"Miscellenous Expenses\")\n" + "An accounting rule can also be optionally associated with a branch, so that only a particular Branch's users have access to the rule")
public class AccountingRuleApiResource {
private static final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList("id", "officeId", "officeName",
@@ -105,6 +107,8 @@ public class AccountingRuleApiResource {
@Path("template")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@ApiOperation(value = "Retrieve Accounting Rule Details Template", notes = "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 Value Lists\n" + "Example Request:\n" + "\n" + "accountingrules/template")
@ApiResponses({@ApiResponse(code = 200, message = "", response = AccountingRuleApiResourceSwagger.GetAccountRulesTemplateResponse.class)})
public String retrieveTemplate(@Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermission);
@@ -119,6 +123,8 @@ public class AccountingRuleApiResource {
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@ApiOperation(value = "Retrieve Accounting Rules", notes = "Returns the list of defined accounting rules.\n" + "\n" + "Example Requests:\n" + "\n" + "accountingrules")
@ApiResponses({@ApiResponse(code = 200, message = "", response = AccountingRuleApiResourceSwagger.GetAccountRulesResponse.class, responseContainer = "list")})
public String retrieveAllAccountingRules(@Context final UriInfo uriInfo) {
final AppUser currentUser = this.context.authenticatedUser();
@@ -147,7 +153,9 @@ public class AccountingRuleApiResource {
@Path("{accountingRuleId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retreiveAccountingRule(@PathParam("accountingRuleId") final Long accountingRuleId, @Context final UriInfo uriInfo) {
@ApiOperation(value = "Retrieve a Accounting rule", notes = "Returns the details of a defined Accounting rule.\n" + "\n" + "Example Requests:\n" + "\n" + "accountingrules/1")
@ApiResponses({@ApiResponse(code = 200, message = "", response = AccountingRuleData.class)})
public String retreiveAccountingRule(@PathParam("accountingRuleId") @ApiParam(value = "accountingRuleId") final Long accountingRuleId, @Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermission);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
@@ -163,7 +171,10 @@ public class AccountingRuleApiResource {
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String createAccountingRule(final String jsonRequestBody) {
@ApiOperation(value = "Create/Define a Accounting rule", notes = "Define a new Accounting rule.\n" + "\n" + "Mandatory Fields\n" + "name, officeId,\n" + "accountToDebit OR debitTags,\n" + "accountToCredit OR creditTags.\n" + "\n" + "Optional Fields\n" + "description")
@ApiImplicitParams({@ApiImplicitParam(paramType = "body", value = "body", dataType = "body", dataTypeClass = AccountingRuleApiResourceSwagger.PostAccountingRulesRequest.class)})
@ApiResponses({@ApiResponse(code = 200, message = "", response = AccountingRuleApiResourceSwagger.PostAccountingRulesResponse.class)})
public String createAccountingRule(@ApiParam(hidden = true) final String jsonRequestBody) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().createAccountingRule().withJson(jsonRequestBody).build();
@@ -176,7 +187,10 @@ public class AccountingRuleApiResource {
@Path("{accountingRuleId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String updateAccountingRule(@PathParam("accountingRuleId") final Long accountingRuleId, final String jsonRequestBody) {
@ApiOperation(value = "Update a Accounting Rule", notes = "Updates the details of a Accounting rule.")
@ApiImplicitParams({@ApiImplicitParam(paramType = "body", value = "body", dataType = "body", dataTypeClass = AccountingRuleApiResourceSwagger.PutAccountingRulesRequest.class)})
@ApiResponses({@ApiResponse(code = 200, message = "", response = AccountingRuleApiResourceSwagger.PutAccountingRulesResponse.class)})
public String updateAccountingRule(@PathParam("accountingRuleId") @ApiParam(value = "accountingRuleId") final Long accountingRuleId,@ApiParam(hidden = true) final String jsonRequestBody) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateAccountingRule(accountingRuleId).withJson(jsonRequestBody)
.build();
@@ -189,7 +203,9 @@ public class AccountingRuleApiResource {
@Path("{accountingRuleId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String deleteAccountingRule(@PathParam("accountingRuleId") final Long accountingRuleId) {
@ApiOperation(value = "Delete a Accounting Rule", notes = "Deletes a Accounting rule.")
@ApiResponses({@ApiResponse(code = 200, message = "", response = AccountingRuleApiResourceSwagger.DeleteAccountingRulesResponse.class)})
public String deleteAccountingRule(@PathParam("accountingRuleId") @ApiParam(value = "accountingRuleId") final Long accountingRuleId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteAccountingRule(accountingRuleId).build();
@@ -0,0 +1,130 @@
/**
* 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.accounting.rule.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.fineract.accounting.glaccount.data.GLAccountData;
import org.apache.fineract.accounting.rule.data.AccountingTagRuleData;
import org.apache.fineract.organisation.office.data.OfficeData;
import java.util.ArrayList;
import java.util.List;
/**
* Created by sanyam on 26/7/17.
*/
final class AccountingRuleApiResourceSwagger {
private AccountingRuleApiResourceSwagger() {
// For Swagger Documentation
}
@ApiModel(value = "GetAccountRulesResponse")
public static final class GetAccountRulesResponse {
private GetAccountRulesResponse() {
}
public Long id;
public Long officeId;
public String officeName;
public String name;
public String description;
public boolean systemDefined;
public boolean allowMultipleDebitEntries;
public boolean allowMultipleCreditEntries;
public List<AccountingTagRuleData> creditTags;
public List<AccountingTagRuleData> debitTags;
}
@ApiModel(value = "GetAccountRulesTemplateResponse")
public static final class GetAccountRulesTemplateResponse {
private GetAccountRulesTemplateResponse() {
}
@ApiModelProperty(example = "false")
public boolean systemDefined;
public List<OfficeData> allowedOffices = new ArrayList<OfficeData>();
public List<GLAccountData> allowedAccounts = new ArrayList<GLAccountData>();
}
@ApiModel(value = "PostAccountingRulesRequest")
public static final class PostAccountingRulesRequest {
private PostAccountingRulesRequest() {
}
@ApiModelProperty(example = "test")
public String name;
@ApiModelProperty(example = "1")
public Long officeId;
@ApiModelProperty(example = "21")
public Long accountToDebit;
@ApiModelProperty(example = "9")
public Long accountToCredit;
@ApiModelProperty(example = "Employee salary")
public String description;
}
@ApiModel(value = "PostAccountingRulesResponse")
public static final class PostAccountingRulesResponse {
private PostAccountingRulesResponse() {
}
@ApiModelProperty(example = "1")
public Long officeId;
@ApiModelProperty(example = "1")
public Long resourceId;
}
@ApiModel(value = "PutAccountingRulesRequest")
public static final class PutAccountingRulesRequest {
private PutAccountingRulesRequest() {
}
@ApiModelProperty(example = "Employee Salary posting rule")
public String name;
}
@ApiModel(value = "PutAccountingRulesResponse")
public static final class PutAccountingRulesResponse {
private PutAccountingRulesResponse () {
}
public class PutAccountingRulesResponsechangesSwagger {
public PutAccountingRulesResponsechangesSwagger(){}
@ApiModelProperty(example = "Employee Salary posting rule")
public String name;
}
@ApiModelProperty(example = "1")
public Long resourceId;
public PutAccountingRulesResponsechangesSwagger changes;
}
@ApiModel(value = "DeleteAccountingRulesResponse")
public static final class DeleteAccountingRulesResponse {
private DeleteAccountingRulesResponse() {
}
@ApiModelProperty(example = "1")
public Long resourceId;
}
}
@@ -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.accounting.trialbalance.exception;
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
public class TrialBalanceNotFoundException extends AbstractPlatformResourceNotFoundException{
public TrialBalanceNotFoundException(final Long officeId,final Long accountId){
super("error.msg.trial.balance.invalid", "Trial balance with officeId " + officeId +"and accountId"+accountId+" does not exist");
}
}
@@ -31,6 +31,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
import org.apache.fineract.batch.domain.BatchRequest;
import org.apache.fineract.batch.domain.BatchResponse;
import org.apache.fineract.batch.serialization.BatchRequestJsonHelper;
@@ -59,6 +60,7 @@ import org.springframework.stereotype.Component;
@Path("/batches")
@Component
@Scope("singleton")
@Api(value = "Batch API", description = "The Apache Fineract Batch API enables a consumer to access significant amounts of data in a single call or to make changes to several objects at once. Batching allows a consumer to pass instructions for several operations in a single HTTP request. A consumer can also specify dependencies between related operations. Once all operations have been completed, a consolidated response will be passed back and the HTTP connection will be closed.\n" + "\n" + "The Batch API takes in an array of logical HTTP requests represented as JSON arrays - each request has a requestId (the id of a request used to specify the sequence and as a dependency between requests), a method (corresponding to HTTP method GET/PUT/POST/DELETE etc.), a relativeUrl (the portion of the URL after https://example.org/api/v2/), optional headers array (corresponding to HTTP headers), optional reference parameter if a request is dependent on another request and an optional body (for POST and PUT requests). The Batch API returns an array of logical HTTP responses represented as JSON arrays - each response has a requestId, a status code, an optional headers array and an optional body (which is a JSON encoded string).\n" + "\n" + "Batch API uses Json Path to handle dependent parameters. For example, if request '2' is referencing request '1' and in the \"body\" or in \"relativeUrl\" of request '2', there is a dependent parameter (which will look like \"$.parameter_name\"), then Batch API will internally substitute this dependent parameter from the response body of request '1'.\n" + "\n" + "Batch API is able to handle deeply nested dependent requests as well nested parameters. As shown in the example, requests are dependent on each other as, 1<--2<--6, i.e a nested dependency, where request '6' is not directly dependent on request '1' but still it is one of the nested child of request '1'. In the same way Batch API could handle a deeply nested dependent value, such as {..[..{..,$.parameter_name,..}..]}.")
public class BatchApiResource {
private final PlatformSecurityContext context;
@@ -97,8 +99,11 @@ public class BatchApiResource {
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String handleBatchRequests(@DefaultValue("false") @QueryParam("enclosingTransaction") final boolean enclosingTransaction,
final String jsonRequestString, @Context UriInfo uriInfo) {
@ApiOperation(value = "Batch requests in a single transaction", httpMethod = "POST", notes = "The Apache Fineract Batch API is also capable of executing all the requests in a single transaction, by setting a Query Parameter, \"enclosingTransaction=true\". So, if one or more of the requests in a batch returns an erroneous response all of the Data base transactions made by other successful requests will be rolled back.\n" + "\n" + "If there has been a rollback in a transaction then a single response will be provided, with a '400' status code and a body consisting of the error details of the first failed request.")
@ApiImplicitParams({@ApiImplicitParam(paramType = "body", dataType = "BatchRequest", required = true, type = "body", dataTypeClass = BatchApiResourceSwagger.PostBatchesRequest.class, value = "request body")})
@ApiResponses({@ApiResponse(code = 200, message = "Success", response = BatchResponse.class)})
public String handleBatchRequests(@DefaultValue("false") @QueryParam("enclosingTransaction") @ApiParam(value = "enclosingTransaction", defaultValue = "false") final boolean enclosingTransaction,
@ApiParam(hidden = true) final String jsonRequestString, @Context UriInfo uriInfo) {
// Handles user authentication
this.context.authenticatedUser();
@@ -0,0 +1,78 @@
/**
* 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.batch.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.fineract.batch.domain.Header;
import java.util.Set;
/**
* Created by sanyam on 26/7/17.
*/
final class BatchApiResourceSwagger {
private BatchApiResourceSwagger() {
}
@ApiModel(value = "PostBatchesRequest")
public static final class PostBatchesRequest{
private PostBatchesRequest() {
}
public static final class PostBodyRequestSwagger{
private PostBodyRequestSwagger() {
}
@ApiModelProperty(example = "1")
public Long officeId;
@ApiModelProperty(example = "\"Petra\"")
public String firstname;
@ApiModelProperty(example = "\"Yton\"")
public String lastname;
@ApiModelProperty(example = "\"ex_externalId1\"")
public String externalId;
@ApiModelProperty(example = "\"dd MMMM yyyy\"")
public String dateFormat;
@ApiModelProperty(example = "\"en\"")
public String locale;
@ApiModelProperty(example = "true")
public boolean active;
@ApiModelProperty(example = "\"04 March 2009\"")
public String activationDate;
@ApiModelProperty(example = "\"04 March 2009\"")
public String submittedOnDate;
}
@ApiModelProperty(example = "1")
public Long requestId;
@ApiModelProperty(example = "clients")
public String relativeUrl;
@ApiModelProperty(example = "POST")
public String method;
public Set<Header> headers;
@ApiModelProperty(example = "1")
public Long reference;
public PostBodyRequestSwagger body;
}
}
@@ -33,6 +33,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
import org.apache.commons.lang.StringUtils;
import org.apache.fineract.commands.data.AuditData;
import org.apache.fineract.commands.data.AuditSearchData;
@@ -51,6 +52,7 @@ import org.springframework.stereotype.Component;
@Path("/audits")
@Component
@Scope("singleton")
@Api(value = "Audits",description = "Every non-read Mifos API request is audited. A fully processed request can not be changed or deleted. See maker checker api for situations where an audit is not fully processed.\n" + "\n" + "Permissions: To search and look at audit entries a user needs to be attached to a role that has one of the ALL_FUNCTIONS, ALL_FUNCTIONS_READ or READ_AUDIT permissions.\n" + "\n" + "Data Scope: A user can only see audits that are within their data scope. However, 'head office' users can see all audits including those that aren't office/branch related e.g. Loan Product changes.")
public class AuditsApiResource {
private final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList("id", "actionName", "entityName", "resourceId",
@@ -79,17 +81,19 @@ public class AuditsApiResource {
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveAuditEntries(@Context final UriInfo uriInfo, @QueryParam("actionName") final String actionName,
@QueryParam("entityName") final String entityName, @QueryParam("resourceId") final Long resourceId,
@QueryParam("makerId") final Long makerId, @QueryParam("makerDateTimeFrom") final String makerDateTimeFrom,
@QueryParam("makerDateTimeTo") final String makerDateTimeTo, @QueryParam("checkerId") final Long checkerId,
@QueryParam("checkerDateTimeFrom") final String checkerDateTimeFrom,
@QueryParam("checkerDateTimeTo") final String checkerDateTimeTo,
@QueryParam("processingResult") final Integer processingResult, @QueryParam("officeId") final Integer officeId,
@QueryParam("groupId") final Integer groupId, @QueryParam("clientId") final Integer clientId,
@QueryParam("loanid") final Integer loanId, @QueryParam("savingsAccountId") final Integer savingsAccountId,
@QueryParam("paged") final Boolean paged, @QueryParam("offset") final Integer offset, @QueryParam("limit") final Integer limit,
@QueryParam("orderBy") final String orderBy, @QueryParam("sortOrder") final String sortOrder) {
@ApiOperation(value = "List Audits", notes = "Get a 200 list of audits that match the criteria supplied and sorted by audit id in descending order, and are within the requestors' data scope. Also it supports pagination and sorting\n" + "\n" + "Example Requests:\n" + "\n" + "audits\n" + "\n" + "audits?fields=madeOnDate,maker,processingResult\n" + "\n" + "audits?makerDateTimeFrom=2013-03-25 08:00:00&makerDateTimeTo=2013-04-04 18:00:00\n" + "\n" + "audits?officeId=1\n" + "\n" + "audits?officeId=1&includeJson=true")
@ApiResponses({@ApiResponse(code = 200, message = "", response = MakercheckersApiResourceSwagger.GetMakerCheckerResponse.class, responseContainer = "list")})
public String retrieveAuditEntries(@Context final UriInfo uriInfo, @QueryParam("actionName") @ApiParam(value = "actionName") final String actionName,
@QueryParam("entityName") @ApiParam(value = "entityName") final String entityName, @QueryParam("resourceId") @ApiParam(value = "resourceId") final Long resourceId,
@QueryParam("makerId") @ApiParam(value = "makerId") final Long makerId, @QueryParam("makerDateTimeFrom") @ApiParam(value = "makerDateTimeFrom") final String makerDateTimeFrom,
@QueryParam("makerDateTimeTo") @ApiParam(value = "makerDateTimeTo") final String makerDateTimeTo, @QueryParam("checkerId") @ApiParam(value = "checkerId") final Long checkerId,
@QueryParam("checkerDateTimeFrom") @ApiParam(value = "checkerDateTimeFrom") final String checkerDateTimeFrom,
@QueryParam("checkerDateTimeTo") @ApiParam(value = "checkerDateTimeTo") final String checkerDateTimeTo,
@QueryParam("processingResult") @ApiParam(value = "processingResult") final Integer processingResult, @QueryParam("officeId") @ApiParam(value = "officeId") final Integer officeId,
@QueryParam("groupId") @ApiParam(value = "groupId") final Integer groupId, @QueryParam("clientId") @ApiParam(value = "clientId") final Integer clientId,
@QueryParam("loanid") @ApiParam(value = "loanid") final Integer loanId, @QueryParam("savingsAccountId") @ApiParam(value = "savingsAccountId") final Integer savingsAccountId,
@QueryParam("paged") @ApiParam(value = "paged") final Boolean paged, @QueryParam("offset") @ApiParam(value = "offset") final Integer offset, @QueryParam("limit") @ApiParam(value = "limit") final Integer limit,
@QueryParam("orderBy") @ApiParam(value = "orderBy") final String orderBy, @QueryParam("sortOrder") @ApiParam(value = "sortOrder") final String sortOrder) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
final PaginationParameters parameters = PaginationParameters.instance(paged, offset, limit, orderBy, sortOrder);
@@ -114,7 +118,9 @@ public class AuditsApiResource {
@Path("{auditId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveAuditEntry(@PathParam("auditId") final Long auditId, @Context final UriInfo uriInfo) {
@ApiOperation(value = "Retrieve an Audit Entry", notes = "Example Requests:\n" + "\n" + "audits/20\n" + "audits/20?fields=madeOnDate,maker,processingResult")
@ApiResponses({@ApiResponse(code = 200, message = "", response = MakercheckersApiResourceSwagger.GetMakerCheckerResponse.class)})
public String retrieveAuditEntry(@PathParam("auditId") @ApiParam(value = "auditId") final Long auditId, @Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
@@ -128,6 +134,8 @@ public class AuditsApiResource {
@Path("/searchtemplate")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@ApiOperation(value = "Audit Search Template", notes = "This is a convenience resource. It can be useful when building an Audit Search UI. \"appUsers\" are data scoped to the office/branch the requestor is associated with.\n" + "\n" + "Example Requests:\n" + "\n" + "audits/searchtemplate\n" + "audits/searchtemplate?fields=actionNames")
@ApiResponses({@ApiResponse(code = 200, message = "", response = MakercheckersApiResourceSwagger.GetMakerCheckersSearchTemplateResponse.class)})
public String retrieveAuditSearchTemplate(@Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
@@ -35,6 +35,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
import org.apache.commons.lang.StringUtils;
import org.apache.fineract.commands.data.AuditData;
import org.apache.fineract.commands.data.AuditSearchData;
@@ -53,6 +54,7 @@ import org.springframework.stereotype.Component;
@Path("/makercheckers")
@Component
@Scope("singleton")
@Api(value = "Maker Checker (or 4-eye) functionality")
public class MakercheckersApiResource {
private final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList("id", "actionName", "entityName", "resourceId",
@@ -80,12 +82,14 @@ public class MakercheckersApiResource {
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveCommands(@Context final UriInfo uriInfo, @QueryParam("actionName") final String actionName,
@QueryParam("entityName") final String entityName, @QueryParam("resourceId") final Long resourceId,
@QueryParam("makerId") final Long makerId, @QueryParam("makerDateTimeFrom") final String makerDateTimeFrom,
@QueryParam("makerDateTimeTo") final String makerDateTimeTo, @QueryParam("officeId") final Integer officeId,
@QueryParam("groupId") final Integer groupId, @QueryParam("clientId") final Integer clientId,
@QueryParam("loanid") final Integer loanId, @QueryParam("savingsAccountId") final Integer savingsAccountId) {
@ApiOperation(value = "List Maker Checker Entries", notes = "Get a list of entries that can be checked by the requestor that match the criteria supplied.\n" + "\n" + "Example Requests:\n" + "\n" + "makercheckers\n" + "\n" + "makercheckers?fields=madeOnDate,maker,processingResult\n" + "\n" + "makercheckers?makerDateTimeFrom=2013-03-25 08:00:00&makerDateTimeTo=2013-04-04 18:00:00\n" + "\n" + "makercheckers?officeId=1\n" + "\n" + "makercheckers?officeId=1&includeJson=true")
@ApiResponses({@ApiResponse(code = 200, message = "", response = MakercheckersApiResourceSwagger.GetMakerCheckerResponse.class, responseContainer = "list")})
public String retrieveCommands(@Context final UriInfo uriInfo, @QueryParam("actionName") @ApiParam(value = "actionName") final String actionName,
@QueryParam("entityName") @ApiParam(value = "entityName") final String entityName, @QueryParam("resourceId") @ApiParam(value = "resourceId") final Long resourceId,
@QueryParam("makerId") @ApiParam(value = "makerId") final Long makerId, @QueryParam("makerDateTimeFrom") @ApiParam(value = "makerDateTimeFrom") final String makerDateTimeFrom,
@QueryParam("makerDateTimeTo") @ApiParam(value = "makerDateTimeTo") final String makerDateTimeTo, @QueryParam("officeId") @ApiParam(value = "officeId") final Integer officeId,
@QueryParam("groupId") @ApiParam(value = "groupId") final Integer groupId, @QueryParam("clientId") @ApiParam(value = "clientId") final Integer clientId,
@QueryParam("loanid") @ApiParam(value = "loanid") final Integer loanId, @QueryParam("savingsAccountId") @ApiParam(value = "savingsAccountId") final Integer savingsAccountId) {
final String extraCriteria = getExtraCriteria(actionName, entityName, resourceId, makerId, makerDateTimeFrom, makerDateTimeTo,
officeId, groupId, clientId, loanId, savingsAccountId);
@@ -102,6 +106,8 @@ public class MakercheckersApiResource {
@Path("/searchtemplate")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@ApiOperation(value = "Maker Checker Search Template", notes = "This is a convenience resource. It can be useful when building a Checker Inbox UI. \"appUsers\" are data scoped to the office/branch the requestor is associated with. \"actionNames\" and \"entityNames\" returned are those that the requestor has Checker approval permissions for.\n" + "\n" + "Example Requests:\n" + "\n" + "makercheckers/searchtemplate\n" + "makercheckers/searchtemplate?fields=entityNames")
@ApiResponses({@ApiResponse(code = 200, message = "", response = MakercheckersApiResourceSwagger.GetMakerCheckersSearchTemplateResponse.class)})
public String retrieveAuditSearchTemplate(@Context final UriInfo uriInfo) {
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
@@ -118,7 +124,9 @@ public class MakercheckersApiResource {
@Path("{auditId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String approveMakerCheckerEntry(@PathParam("auditId") final Long auditId, @QueryParam("command") final String commandParam) {
@ApiOperation(value = "Approve Maker Checker Entry | Reject Maker Checker Entry")
@ApiResponses({@ApiResponse(code = 200, message = "", response = MakercheckersApiResourceSwagger.PostMakerCheckersResponse.class)})
public String approveMakerCheckerEntry(@PathParam("auditId") @ApiParam(value = "auditId") final Long auditId, @QueryParam("command") @ApiParam(value = "command") final String commandParam) {
CommandProcessingResult result = null;
if (is(commandParam, "approve")) {
@@ -140,7 +148,9 @@ public class MakercheckersApiResource {
@Path("{auditId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String deleteMakerCheckerEntry(@PathParam("auditId") final Long auditId) {
@ApiOperation(value = "Delete Maker Checker Entry")
@ApiResponses({@ApiResponse(code = 200, message = "", response = MakercheckersApiResourceSwagger.PostMakerCheckersResponse.class)})
public String deleteMakerCheckerEntry(@PathParam("auditId") @ApiParam(value = "auditId") final Long auditId) {
final Long id = this.writePlatformService.deleteEntry(auditId);
@@ -0,0 +1,87 @@
/**
* 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.commands.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.fineract.commands.data.ProcessingResultLookup;
import org.apache.fineract.useradministration.data.AppUserData;
import org.joda.time.DateTime;
import java.util.Collection;
import java.util.List;
/**
* Created by sanyam on 27/7/17.
*/
final class MakercheckersApiResourceSwagger {
private MakercheckersApiResourceSwagger() {
// only to initialize swagger documentation
}
@ApiModel(value = "GetMakerCheckerResponse")
public static final class GetMakerCheckerResponse{
private GetMakerCheckerResponse() {
}
public Long id;
public String actionName;
public String entityName;
public Long resourceId;
public Long subresourceId;
public String maker;
public DateTime madeOnDate;
public String checker;
public DateTime checkedOnDate;
public String processingResult;
public String commandAsJson;
public String officeName;
public String groupLevelName;
public String groupName;
public String clientName;
public String loanAccountNo;
public String savingsAccountNo;
public Long clientId;
public Long loanId;
public String url;
}
@ApiModel(value = "GetMakerCheckersSearchTemplateResponse")
public static final class GetMakerCheckersSearchTemplateResponse{
private GetMakerCheckersSearchTemplateResponse() {
}
public Collection<AppUserData> appUsers;
public List<String> actionNames;
public List<String> entityNames;
public Collection<ProcessingResultLookup> processingResults;
}
@ApiModel(value = "PostMakerCheckersResponse")
public static final class PostMakerCheckersResponse{
private PostMakerCheckersResponse() {
}
@ApiModelProperty(example = "1")
public Long auditId;
}
}
@@ -35,6 +35,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
@@ -54,6 +55,7 @@ import org.springframework.stereotype.Component;
@Path(AccountNumberFormatConstants.resourceRelativeURL)
@Component
@Scope("singleton")
@Api(value = "Account number format", description = "Account number preferences are used to describe custom formats for account numbers associated with Customer, Loan and Savings accounts." )
public class AccountNumberFormatsApiResource {
private final PlatformSecurityContext context;
@@ -83,6 +85,8 @@ public class AccountNumberFormatsApiResource {
@Path("template")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@ApiOperation(value = "Retrieve Account number format Template", notes = "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 Value Lists\n" + "\n" + "Example Request:\n" + "\n" + "accountnumberformats/template")
@ApiResponses({@ApiResponse(code = 200, message = "", response = AccountNumberFormatsApiResourceSwagger.GetAccountNumberFormatsResponseTemplate.class)})
public String retrieveTemplate(@Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(AccountNumberFormatConstants.ENTITY_NAME);
@@ -98,6 +102,8 @@ public class AccountNumberFormatsApiResource {
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@ApiOperation(value = "List Account number formats", notes = "Example Requests:\n" + "\n" + "accountnumberformats\n" + "\n" + "\n" + "accountnumberformats?fields=accountType,prefixType", responseContainer = "List")
@ApiResponses({@ApiResponse(code = 200, message = "", response = AccountNumberFormatsApiResourceSwagger.GetAccountNumberFormatsIdResponse.class, responseContainer = "List")})
public String retrieveAll(@Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(AccountNumberFormatConstants.ENTITY_NAME);
@@ -114,7 +120,9 @@ public class AccountNumberFormatsApiResource {
@Path("{accountNumberFormatId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveOne(@Context final UriInfo uriInfo, @PathParam("accountNumberFormatId") final Long accountNumberFormatId) {
@ApiOperation(value = "Retrieve an Account number format", notes = "Example Requests:\n" + "\n" + "accountnumberformats/1\n" + "\n" + "\n" + "accountnumberformats/1?template=true\n" + "\n" + "\n" + "accountnumberformats/1?fields=accountType,prefixType")
@ApiResponses({@ApiResponse(code = 200, message = "", response = AccountNumberFormatsApiResourceSwagger.GetAccountNumberFormatsIdResponse.class)})
public String retrieveOne(@Context final UriInfo uriInfo, @PathParam("accountNumberFormatId") @ApiParam(value = "accountNumberFormatId") final Long accountNumberFormatId) {
this.context.authenticatedUser().validateHasReadPermission(AccountNumberFormatConstants.ENTITY_NAME);
@@ -135,7 +143,10 @@ public class AccountNumberFormatsApiResource {
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String create(final String apiRequestBodyAsJson) {
@ApiOperation(value = "Create an Account number format", notes = "Note: You may associate a single Account number format for a given account type\n" + "Mandatory Fields for Account number formats\n" + "accountType")
@ApiImplicitParams({@ApiImplicitParam(value = "body", paramType = "body", dataType = "body", format = "body", dataTypeClass = AccountNumberFormatsApiResourceSwagger.PostAccountNumberFormatsRequest.class)})
@ApiResponses({@ApiResponse(code = 200, message = "", response = AccountNumberFormatsApiResourceSwagger.PostAccountNumberFormatsResponse.class)})
public String create(@ApiParam(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
.createAccountNumberFormat() //
@@ -151,7 +162,10 @@ public class AccountNumberFormatsApiResource {
@Path("{accountNumberFormatId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String update(@PathParam("accountNumberFormatId") final Long accountNumberFormatId, final String apiRequestBodyAsJson) {
@ApiOperation(value = "Update an Account number format")
@ApiImplicitParams({@ApiImplicitParam(value = "body", required = true,paramType = "body", dataType = "body", format = "body", dataTypeClass = AccountNumberFormatsApiResourceSwagger.PutAccountNumberFormatsRequest.class )})
@ApiResponses({@ApiResponse(code = 200, message = "", response = AccountNumberFormatsApiResourceSwagger.PutAccountNumberFormatsResponse.class)})
public String update(@PathParam("accountNumberFormatId") @ApiParam(value = "accountNumberFormatId") final Long accountNumberFormatId, @ApiParam(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
.updateAccountNumberFormat(accountNumberFormatId) //
@@ -167,7 +181,9 @@ public class AccountNumberFormatsApiResource {
@Path("{accountNumberFormatId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String delete(@PathParam("accountNumberFormatId") final Long accountNumberFormatId) {
@ApiOperation(value = "Delete an Account number format", notes = "Note: Account numbers created while this format was active would remain unchanged.")
@ApiResponses({@ApiResponse(code = 200, message = "", response = AccountNumberFormatsApiResourceSwagger.DeleteAccountNumberFormatsResponse.class)})
public String delete(@PathParam("accountNumberFormatId") @ApiParam(value = "accountNumberFormatId") final Long accountNumberFormatId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
.deleteAccountNumberFormat(accountNumberFormatId) //
@@ -0,0 +1,129 @@
/**
* 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.infrastructure.accountnumberformat.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
import java.util.List;
import java.util.Map;
/**
* Created by sanyam on 28/7/17.
*/
final class AccountNumberFormatsApiResourceSwagger {
private AccountNumberFormatsApiResourceSwagger() {
// this class is only for Swagger implementation for Live Documentation
}
@ApiModel(value = "GetAccountNumberFormatsResponse")
public static final class GetAccountNumberFormatsResponse {
private GetAccountNumberFormatsResponse() {
}
// public List<GetAccountNumberFormatsIdResponse> _;
}
@ApiModel(value = "GetAccountNumberFormatsIdResponse")
public static final class GetAccountNumberFormatsIdResponse {
private GetAccountNumberFormatsIdResponse() {
}
@ApiModelProperty(example = "2")
public Long id;
public EnumOptionData accountType;
public EnumOptionData prefixType;
}
@ApiModel(value = "GetAccountNumberFormatsResponseTemplate")
public static final class GetAccountNumberFormatsResponseTemplate {
private GetAccountNumberFormatsResponseTemplate() {
}
public List<EnumOptionData> accountTypeOptions;
public Map<String, List<EnumOptionData>> prefixTypeOptions;
}
@ApiModel(value = "PostAccountNumberFormatsRequest")
public static final class PostAccountNumberFormatsRequest {
private PostAccountNumberFormatsRequest() {
}
@ApiModelProperty(example = "1")
public Long accountType;
@ApiModelProperty(example = "101")
public Long prefixType;
}
@ApiModel(value = "PostAccountNumberFormatsResponse")
public static final class PostAccountNumberFormatsResponse {
private PostAccountNumberFormatsResponse() {
}
@ApiModelProperty(example = "4")
public Long resourceId;
}
@ApiModel(value = "PutAccountNumberFormatsRequest")
public static final class PutAccountNumberFormatsRequest {
private PutAccountNumberFormatsRequest() {
}
@ApiModelProperty(example = "1")
public Long prefixType;
}
@ApiModel(value = "PutAccountNumberFormatsResponse")
public static final class PutAccountNumberFormatsResponse {
private PutAccountNumberFormatsResponse() {
}
public static final class PutAccountNumberFormatschangesSwagger {
private PutAccountNumberFormatschangesSwagger() {
}
@ApiModelProperty(example = "OFFICE_NAME")
public Long prefixType;
}
@ApiModelProperty(example = "2")
public Long resourceId;
public PutAccountNumberFormatschangesSwagger changes;
}
@ApiModel(value = "DeleteAccountNumberFormatsResponse")
public static final class DeleteAccountNumberFormatsResponse {
private DeleteAccountNumberFormatsResponse() {
}
@ApiModelProperty(example = "2")
public Long resourceId;
}
}
@@ -26,19 +26,22 @@ public class LoanRepaymentConstants {
public static final int LOAN_ACCOUNT_NO_COL = 3;//D
public static final int PRODUCT_COL = 4;//E
public static final int PRINCIPAL_COL = 5;//F
public static final int AMOUNT_COL = 6;//G
public static final int REPAID_ON_DATE_COL = 7;//H
public static final int REPAYMENT_TYPE_COL = 8;//I
public static final int ACCOUNT_NO_COL = 9;//J
public static final int CHECK_NO_COL = 10;//K
public static final int ROUTING_CODE_COL = 11;//L
public static final int RECEIPT_NO_COL = 12;//M
public static final int BANK_NO_COL = 13;//N
public static final int STATUS_COL = 14;//O
public static final int LOOKUP_CLIENT_NAME_COL = 15;//P
public static final int LOOKUP_CLIENT_EXTERNAL_ID = 16;//Q
public static final int LOOKUP_ACCOUNT_NO_COL = 17;//R
public static final int LOOKUP_PRODUCT_COL = 18;//S
public static final int LOOKUP_PRINCIPAL_COL = 19;//T
public static final int LOOKUP_LOAN_DISBURSEMENT_DATE_COL = 20;//U
public static final int TOTAL_OUTSTANDING_AMOUNT_COL=6;
public static final int LOAN_DISBURSEMENT_DATE_COL=7;
public static final int AMOUNT_COL = 8;//G
public static final int REPAID_ON_DATE_COL = 9;//H
public static final int REPAYMENT_TYPE_COL = 10;//I
public static final int ACCOUNT_NO_COL = 11;//J
public static final int CHECK_NO_COL = 12;//K
public static final int ROUTING_CODE_COL = 13;//L
public static final int RECEIPT_NO_COL = 14;//M
public static final int BANK_NO_COL = 15;//N
public static final int STATUS_COL = 16;//O
public static final int LOOKUP_CLIENT_NAME_COL = 17;//P
public static final int LOOKUP_CLIENT_EXTERNAL_ID = 18;//Q
public static final int LOOKUP_ACCOUNT_NO_COL = 19;//R
public static final int LOOKUP_PRODUCT_COL = 20;//S
public static final int LOOKUP_PRINCIPAL_COL = 21;//T
public static final int LOOKUP_TOTAL_OUTSTANDING_AMOUNT_COL=22;
public static final int LOOKUP_LOAN_DISBURSEMENT_DATE_COL = 23;//U
}
@@ -63,8 +63,13 @@ public class ImportHandlerUtils {
FormulaEvaluator eval = row.getSheet().getWorkbook().getCreationHelper().createFormulaEvaluator();
if(c.getCellType() == Cell.CELL_TYPE_FORMULA) {
if(eval!=null) {
CellValue val = eval.evaluate(c);
return ((Double) val.getNumberValue()).longValue();
CellValue val = null;
try {
val = eval.evaluate(c);
} catch (NullPointerException npe) {
return null;
}
return ((Double)val.getNumberValue()).longValue();
}
}
else if (c.getCellType()==Cell.CELL_TYPE_NUMERIC){
@@ -85,7 +90,13 @@ public class ImportHandlerUtils {
FormulaEvaluator eval = row.getSheet().getWorkbook().getCreationHelper().createFormulaEvaluator();
if(c.getCellType() == Cell.CELL_TYPE_FORMULA) {
if (eval!=null) {
CellValue val = eval.evaluate(c);
CellValue val = null;
try {
val = eval.evaluate(c);
} catch(NullPointerException npe) {
return null;
}
String res = trimEmptyDecimalPortion(val.getStringValue());
if (res!=null) {
if (!res.equals("")) {
@@ -136,7 +147,12 @@ public class ImportHandlerUtils {
FormulaEvaluator eval = row.getSheet().getWorkbook().getCreationHelper().createFormulaEvaluator();
if(c.getCellType() == Cell.CELL_TYPE_FORMULA) {
if(eval!=null) {
CellValue val = eval.evaluate(c);
CellValue val = null;
try {
val = eval.evaluate(c);
} catch (NullPointerException npe) {
return false;
}
return val.getBooleanValue();
}
return false;
@@ -158,8 +174,13 @@ public class ImportHandlerUtils {
FormulaEvaluator eval = row.getSheet().getWorkbook().getCreationHelper().createFormulaEvaluator();
if(c.getCellType() == Cell.CELL_TYPE_FORMULA) {
if(eval!=null) {
CellValue val = eval.evaluate(c);
return ((Double) val.getNumberValue()).intValue();
CellValue val = null;
try {
val = eval.evaluate(c);
} catch (NullPointerException npe) {
return null;
}
return ((Double)val.getNumberValue()).intValue();
}
return null;
}else if (c.getCellType()==Cell.CELL_TYPE_NUMERIC) {
@@ -176,7 +197,12 @@ public class ImportHandlerUtils {
FormulaEvaluator eval = row.getSheet().getWorkbook().getCreationHelper().createFormulaEvaluator();
if(c.getCellType() == Cell.CELL_TYPE_FORMULA) {
if (eval!=null) {
CellValue val = eval.evaluate(c);
CellValue val = null;
try {
val = eval.evaluate(c);
} catch (NullPointerException npe) {
return 0.0;
}
return val.getNumberValue();
}else {
return 0.0;
@@ -18,7 +18,11 @@
*/
package org.apache.fineract.infrastructure.bulkimport.importhandler.client;
import com.google.gson.GsonBuilder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
@@ -29,17 +33,19 @@ import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandler
import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandlerUtils;
import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.DateSerializer;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.exception.*;
import org.apache.fineract.portfolio.address.data.AddressData;
import org.apache.fineract.portfolio.client.data.ClientData;
import org.apache.fineract.portfolio.client.data.ClientNonPersonData;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import com.google.gson.GsonBuilder;
@Service
public class ClientEntityImportHandler implements ImportHandler {
@@ -134,6 +140,7 @@ public class ClientEntityImportHandler implements ImportHandler {
activationDate=submittedOn;
}
AddressData addressDataObj=null;
Collection<AddressData> addressList = null;
if (ImportHandlerUtils.readAsBoolean(ClientEntityConstants.ADDRESS_ENABLED,row)) {
String addressType = ImportHandlerUtils.readAsString(ClientEntityConstants.ADDRESS_TYPE_COL, row);
Long addressTypeId = null;
@@ -167,10 +174,12 @@ public class ClientEntityImportHandler implements ImportHandler {
}
addressDataObj = new AddressData(addressTypeId, street, addressLine1, addressLine2, addressLine3,
city, postalCode, isActiveAddress, stateProvinceId, countryId);
addressList = new ArrayList<AddressData>(Arrays.asList(addressDataObj));
}
return ClientData.importClientEntityInstance(legalFormId,row.getRowNum(),name,officeId,clientTypeId,clientClassicationId,
staffId,active,activationDate,submittedOn, externalId,incorportionDate,mobileNo,clientNonPersonData,addressDataObj,locale,dateFormat);
}
staffId, active, activationDate, submittedOn, externalId, incorportionDate, mobileNo,
clientNonPersonData, addressList, locale, dateFormat);
}
public Count importEntity(String dateFormat) {
Sheet clientSheet=workbook.getSheet(TemplatePopulateImportConstants.CLIENT_ENTITY_SHEET_NAME);
@@ -18,7 +18,11 @@
*/
package org.apache.fineract.infrastructure.bulkimport.importhandler.client;
import com.google.gson.GsonBuilder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
@@ -28,17 +32,18 @@ import org.apache.fineract.infrastructure.bulkimport.data.Count;
import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandler;
import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandlerUtils;
import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.DateSerializer;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.exception.*;
import org.apache.fineract.portfolio.address.data.AddressData;
import org.apache.fineract.portfolio.client.data.ClientData;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import com.google.gson.GsonBuilder;
@Service
public class ClientPersonImportHandler implements ImportHandler {
@@ -120,6 +125,7 @@ public class ClientPersonImportHandler implements ImportHandler {
Boolean isStaff = ImportHandlerUtils.readAsBoolean(ClientPersonConstants.IS_STAFF_COL, row);
AddressData addressDataObj=null;
Collection<AddressData> addressList = null;
if (ImportHandlerUtils.readAsBoolean(ClientPersonConstants.ADDRESS_ENABLED_COL,row)) {
String addressType=ImportHandlerUtils.readAsString(ClientPersonConstants.ADDRESS_TYPE_COL, row);
Long addressTypeId = null;
@@ -154,11 +160,13 @@ public class ClientPersonImportHandler implements ImportHandler {
}
addressDataObj = new AddressData(addressTypeId, street, addressLine1, addressLine2, addressLine3,
city, postalCode, isActiveAddress, stateProvinceId, countryId);
addressList = new ArrayList<AddressData>(Arrays.asList(addressDataObj));
}
return ClientData.importClientPersonInstance(legalFormId,row.getRowNum(),firstName,lastName,middleName,submittedOn,activationDate,active,externalId,
officeId,staffId,mobileNo,dob,clientTypeId,genderId,clientClassicationId,isStaff,addressDataObj,locale,dateFormat);
officeId, staffId, mobileNo, dob, clientTypeId, genderId, clientClassicationId, isStaff,
addressList, locale, dateFormat);
}
}
public Count importEntity(String dateFormat) {
Sheet clientSheet=workbook.getSheet(TemplatePopulateImportConstants.CLIENT_PERSON_SHEET_NAME);
@@ -174,7 +182,7 @@ public class ClientPersonImportHandler implements ImportHandler {
.createClient() //
.withJson(payload) //
.build(); //
final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
commandsSourceWritePlatformService.logCommandSource(commandRequest);
successCount++;
Cell statusCell = clientSheet.getRow(client.getRowIndex()).createCell(ClientPersonConstants.STATUS_COL);
statusCell.setCellValue(TemplatePopulateImportConstants.STATUS_CELL_IMPORTED);
@@ -18,8 +18,10 @@
*/
package org.apache.fineract.infrastructure.bulkimport.importhandler.loanrepayment;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
@@ -29,28 +31,32 @@ import org.apache.fineract.infrastructure.bulkimport.data.Count;
import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandler;
import org.apache.fineract.infrastructure.bulkimport.importhandler.ImportHandlerUtils;
import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.DateSerializer;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.exception.*;
import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionData;
import org.apache.poi.ss.usermodel.*;
import org.apache.fineract.portfolio.loanaccount.service.LoanReadPlatformService;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
@Service
public class LoanRepaymentImportHandler implements ImportHandler {
private Workbook workbook;
private List<LoanTransactionData> loanRepayments;
private Integer loanAccountId;
private Long loanAccountId;
private final LoanReadPlatformService loanReadPlatformService;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
@Autowired
public LoanRepaymentImportHandler(final PortfolioCommandSourceWritePlatformService
commandsSourceWritePlatformService) {
commandsSourceWritePlatformService, final LoanReadPlatformService loanReadPlatformService) {
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
this.loanReadPlatformService = loanReadPlatformService;
}
@Override
@@ -75,7 +81,7 @@ public class LoanRepaymentImportHandler implements ImportHandler {
String loanaccountInfo=ImportHandlerUtils.readAsString(LoanRepaymentConstants.LOAN_ACCOUNT_NO_COL, row);
if (loanaccountInfo!=null){
String loanAccountAr[]=loanaccountInfo.split("-");
loanAccountId=Integer.parseInt(loanAccountAr[0]);
loanAccountId = this.loanReadPlatformService.retrieveLoanIdByAccountNumber(loanAccountAr[0]);
}
BigDecimal repaymentAmount=null;
if (ImportHandlerUtils.readAsDouble(LoanRepaymentConstants.AMOUNT_COL, row)!=null)
@@ -107,10 +113,10 @@ public class LoanRepaymentImportHandler implements ImportHandler {
loanRepaymentJsonob.remove("manuallyReversed");
String payload=loanRepaymentJsonob.toString();
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
.loanRepaymentTransaction(loanRepayment.getAccountId().longValue()) //
.loanRepaymentTransaction(loanRepayment.getAccountId()) //
.withJson(payload) //
.build(); //
final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
commandsSourceWritePlatformService.logCommandSource(commandRequest);
successCount++;
Cell statusCell = loanRepaymentSheet.getRow(loanRepayment.getRowIndex()).createCell(LoanRepaymentConstants.STATUS_COL);
statusCell.setCellValue(TemplatePopulateImportConstants.STATUS_CELL_IMPORTED);
@@ -88,7 +88,7 @@ public abstract class AbstractWorkbookPopulator implements WorkbookPopulator {
}
protected void writeBigDecimal(int colIndex, Row row, BigDecimal value) {
row.createCell(colIndex).setCellValue(value.doubleValue());
row.createCell(colIndex).setCellValue(((value != null) ? value.doubleValue() : 0));
}
protected void setOfficeDateLookupTable(Sheet sheet, List<OfficeData> offices, int officeNameCol,
@@ -142,17 +142,20 @@ public abstract class AbstractWorkbookPopulator implements WorkbookPopulator {
}
}
if (groups!=null){
for (GroupGeneralData group : groups) {
Row row = sheet.getRow(++rowIndex);
if (row == null)
row = sheet.createRow(rowIndex);
writeString(nameCol, row, group.getName().replaceAll("[ )(] ", "_"));
if (groups != null) {
for (GroupGeneralData group : groups) {
Row row = sheet.getRow(++rowIndex);
if (row == null)
row = sheet.createRow(rowIndex);
writeString(nameCol, row, group.getName().replaceAll("[ )(] ", "_"));
date = inputFormat.parse(group.getActivationDate().toString());
writeDate(activationDateCol, row, outputFormat.format(date), dateCellStyle,dateFormat);
}
}
if (group.getActivationDate() != null) {
date = inputFormat.parse(group.getActivationDate().toString());
writeDate(activationDateCol, row, outputFormat.format(date), dateCellStyle, dateFormat);
}
}
}
} catch (ParseException e) {
e.printStackTrace();
}
@@ -179,7 +179,7 @@ public class FixedDepositTransactionWorkbookPopulator extends AbstractWorkbookPo
for(SavingsAccountData savingsAccount : savingsAccounts) {
row = savingsTransactionSheet.createRow(rowIndex++);
writeString(TransactionConstants.LOOKUP_CLIENT_NAME_COL, row, savingsAccount.getClientName() + "(" + savingsAccount.getClientId() + ")");
writeLong(TransactionConstants.LOOKUP_ACCOUNT_NO_COL, row, Long.parseLong(savingsAccount.getAccountNo()));
writeString(TransactionConstants.LOOKUP_ACCOUNT_NO_COL, row, savingsAccount.getAccountNo());
writeString(TransactionConstants.LOOKUP_PRODUCT_COL, row, savingsAccount.getSavingsProductName());
if(savingsAccount.getMinRequiredOpeningBalance() != null)
writeBigDecimal(TransactionConstants.LOOKUP_OPENING_BALANCE_COL, row, savingsAccount.getMinRequiredOpeningBalance());
@@ -131,7 +131,7 @@ public class GuarantorWorkbookPopulator extends AbstractWorkbookPopulator {
row=addGuarantorSheet.getRow(rowIndex++);
}
writeString(GuarantorConstants.LOOKUP_SAVINGS_CLIENT_NAME_COL, row, savingsAccount.getClientName() + "(" + savingsAccount.getClientId() + ")");
writeLong(GuarantorConstants.LOOKUP_SAVINGS_ACCOUNT_NO_COL, row, Long.parseLong(savingsAccount.getAccountNo()));
writeString(GuarantorConstants.LOOKUP_SAVINGS_ACCOUNT_NO_COL, row,savingsAccount.getAccountNo());
}
}
@@ -170,7 +170,7 @@ public class LoanWorkbookPopulator extends AbstractWorkbookPopulator {
.createIntegerConstraint(DataValidationConstraint.OperatorType.GREATER_OR_EQUAL, "=$M1*$N1", null);
DataValidationConstraint interestFrequencyConstraint = validationHelper
.createFormulaListConstraint("INDIRECT(CONCATENATE(\"INTEREST_FREQUENCY_\",$E1))");
DataValidationConstraint interestConstraint = validationHelper.createIntegerConstraint(
DataValidationConstraint interestConstraint = validationHelper.createDecimalConstraint(
DataValidationConstraint.OperatorType.BETWEEN, "=INDIRECT(CONCATENATE(\"MIN_INTEREST_\",$E1))",
"=INDIRECT(CONCATENATE(\"MAX_INTEREST_\",$E1))");
DataValidationConstraint amortizationConstraint = validationHelper
@@ -562,4 +562,4 @@ public class LoanWorkbookPopulator extends AbstractWorkbookPopulator {
}
}
}
}
@@ -45,7 +45,7 @@ public class LoanRepaymentWorkbookPopulator extends AbstractWorkbookPopulator {
private Map<Long,String> clientIdToClientExternalId;
public LoanRepaymentWorkbookPopulator(List<LoanAccountData> loans, OfficeSheetPopulator officeSheetPopulator,
ClientSheetPopulator clientSheetPopulator, ExtrasSheetPopulator extrasSheetPopulator) {
ClientSheetPopulator clientSheetPopulator, ExtrasSheetPopulator extrasSheetPopulator) {
this.allloans = loans;
this.officeSheetPopulator = officeSheetPopulator;
this.clientSheetPopulator = clientSheetPopulator;
@@ -62,7 +62,7 @@ public class LoanRepaymentWorkbookPopulator extends AbstractWorkbookPopulator {
setClientIdToClientExternalId();
populateLoansTable(loanRepaymentSheet,dateFormat);
setRules(loanRepaymentSheet,dateFormat);
setDefaults(loanRepaymentSheet);
setDefaults(loanRepaymentSheet,dateFormat);
}
private void setClientIdToClientExternalId() {
@@ -70,27 +70,41 @@ public class LoanRepaymentWorkbookPopulator extends AbstractWorkbookPopulator {
List<ClientData>allclients=clientSheetPopulator.getClients();
for (ClientData client: allclients) {
if (client.getExternalId()!=null)
clientIdToClientExternalId.put(client.getId(),client.getExternalId());
clientIdToClientExternalId.put(client.getId(),client.getExternalId());
}
}
private void setDefaults(Sheet worksheet) {
for (Integer rowNo = 1; rowNo < 3000; rowNo++) {
Row row = worksheet.getRow(rowNo);
if (row == null)
row = worksheet.createRow(rowNo);
writeFormula(LoanRepaymentConstants.CLIENT_EXTERNAL_ID, row,
"IF(ISERROR(VLOOKUP($B"+(rowNo+1)+",$P$2:$Q$"+(allloans.size()+1)+",2,FALSE))," +
"\"\",(VLOOKUP($B"+(rowNo+1)+",$P$2:$Q$"+(allloans.size()+1)+",2,FALSE)))");
writeFormula(LoanRepaymentConstants.PRODUCT_COL, row,
"IF(ISERROR(VLOOKUP($D" + (rowNo + 1) + ",$R$2:$T$" + (allloans.size() + 1)
+ ",2,FALSE)),\"\",VLOOKUP($D" + (rowNo + 1) + ",$R$2:$T$" + (allloans.size() + 1)
+ ",2,FALSE))");
writeFormula(LoanRepaymentConstants.PRINCIPAL_COL, row,
"IF(ISERROR(VLOOKUP($D" + (rowNo + 1) + ",$R$2:$T$" + (allloans.size() + 1)
+ ",3,FALSE)),\"\",VLOOKUP($D" + (rowNo + 1) + ",$R$2:$T$" + (allloans.size() + 1)
+ ",3,FALSE))");
}
private void setDefaults(Sheet worksheet,String dateFormat) {
for (Integer rowNo = 1; rowNo < 3000; rowNo++) {
Row row = worksheet.getRow(rowNo);
if (row == null)
row = worksheet.createRow(rowNo);
writeFormula(LoanRepaymentConstants.CLIENT_EXTERNAL_ID, row,
"IF(ISERROR(VLOOKUP($B"+(rowNo+1)+",$R$2:$S$"+(allloans.size()+1)+",2,FALSE))," +
"\"\",(VLOOKUP($B"+(rowNo+1)+",$R$2:$S$"+(allloans.size()+1)+",2,FALSE)))");
writeFormula(LoanRepaymentConstants.PRODUCT_COL, row,
"IF(ISERROR(VLOOKUP($D" + (rowNo + 1) + ",$T$2:$X$" + (allloans.size() + 1)
+ ",2,FALSE)),\"\",VLOOKUP($D" + (rowNo + 1) + ",$T$2:$X$" + (allloans.size() + 1)
+ ",2,FALSE))");
writeFormula(LoanRepaymentConstants.PRINCIPAL_COL, row,
"IF(ISERROR(VLOOKUP($D" + (rowNo + 1) + ",$T$2:$X$" + (allloans.size() + 1)
+ ",3,FALSE)),\"\",VLOOKUP($D" + (rowNo + 1) + ",$T$2:$X$" + (allloans.size() + 1)
+ ",3,FALSE))");
writeFormula(LoanRepaymentConstants.TOTAL_OUTSTANDING_AMOUNT_COL, row,
"IF(ISERROR(VLOOKUP($D" + (rowNo + 1) + ",$T$2:$X$" + (allloans.size() + 1)
+ ",4,FALSE)),\"\",VLOOKUP($D" + (rowNo + 1) + ",$T$2:$X$" + (allloans.size() + 1)
+ ",4,FALSE))");
writeFormula(LoanRepaymentConstants.LOAN_DISBURSEMENT_DATE_COL, row,
"IF(ISERROR(VLOOKUP($D" + (rowNo + 1) + ",$T$2:$X$" + (allloans.size() + 1)
+ ",5,FALSE)),\"\",VLOOKUP($D" + (rowNo + 1) + ",$T$2:$X$" + (allloans.size() + 1)
+ ",5,FALSE))");
Workbook workbook=worksheet.getWorkbook();
CellStyle dateCellStyle = workbook.createCellStyle();
short df = workbook.createDataFormat().getFormat(dateFormat);
dateCellStyle.setDataFormat(df);
row.getCell(LoanRepaymentConstants.LOAN_DISBURSEMENT_DATE_COL).setCellStyle(dateCellStyle);
}
}
private void setRules(Sheet worksheet,String dateFormat) {
@@ -117,7 +131,7 @@ public class LoanRepaymentWorkbookPopulator extends AbstractWorkbookPopulator {
DataValidationConstraint paymentTypeConstraint = validationHelper.createFormulaListConstraint("PaymentTypes");
DataValidationConstraint repaymentDateConstraint = validationHelper.createDateConstraint(
DataValidationConstraint.OperatorType.BETWEEN,
"=VLOOKUP($D1,$R$2:$U$" + (allloans.size() + 1) + ",4,FALSE)", "=TODAY()", dateFormat);
"=VLOOKUP($D1,$T$2:$X$" + (allloans.size() + 1) + ",4,FALSE)", "=TODAY()", dateFormat);
DataValidation officeValidation = validationHelper.createValidation(officeNameConstraint, officeNameRange);
DataValidation clientValidation = validationHelper.createValidation(clientNameConstraint, clientNameRange);
@@ -182,13 +196,13 @@ public class LoanRepaymentWorkbookPopulator extends AbstractWorkbookPopulator {
}
}
// Account Number Named after Clients
// Account Number Named after Clients
for (int j = 0; j < clientsWithActiveLoans.size(); j++) {
Name name = loanRepaymentWorkbook.createName();
name.setNameName("Account_" + clientsWithActiveLoans.get(j).replaceAll(" ", "_") + "_"
+ clientIdsWithActiveLoans.get(j) + "_");
name.setRefersToFormula(
TemplatePopulateImportConstants.LOAN_REPAYMENT_SHEET_NAME+"!$R$" + clientNameToBeginEndIndexes.get(clientsWithActiveLoans.get(j))[0] + ":$R$"
TemplatePopulateImportConstants.LOAN_REPAYMENT_SHEET_NAME+"!$T$" + clientNameToBeginEndIndexes.get(clientsWithActiveLoans.get(j))[0] + ":$T$"
+ clientNameToBeginEndIndexes.get(clientsWithActiveLoans.get(j))[1]);
}
@@ -213,9 +227,11 @@ public class LoanRepaymentWorkbookPopulator extends AbstractWorkbookPopulator {
row = loanRepaymentSheet.createRow(rowIndex++);
writeString(LoanRepaymentConstants.LOOKUP_CLIENT_NAME_COL, row, loan.getClientName() + "(" + loan.getClientId() + ")");
writeString(LoanRepaymentConstants.LOOKUP_CLIENT_EXTERNAL_ID,row, clientIdToClientExternalId.get(loan.getClientId()));
writeString(LoanRepaymentConstants.LOOKUP_ACCOUNT_NO_COL, row, Long.parseLong(loan.getAccountNo())+"-"+loan.getStatusStringValue());
writeString(LoanRepaymentConstants.LOOKUP_ACCOUNT_NO_COL, row, loan.getAccountNo()+"-"+loan.getStatusStringValue());
writeString(LoanRepaymentConstants.LOOKUP_PRODUCT_COL, row, loan.getLoanProductName());
writeDouble(LoanRepaymentConstants.LOOKUP_PRINCIPAL_COL, row, loan.getPrincipal().doubleValue());
if (loan.getTotalOutstandingAmount() != null)
writeBigDecimal(LoanRepaymentConstants.LOOKUP_TOTAL_OUTSTANDING_AMOUNT_COL, row, loan.getTotalOutstandingAmount());
if (loan.getDisbursementDate() != null) {
try {
date = inputFormat.parse(loan.getDisbursementDate().toString());
@@ -237,6 +253,8 @@ public class LoanRepaymentWorkbookPopulator extends AbstractWorkbookPopulator {
worksheet.setColumnWidth(LoanRepaymentConstants.LOAN_ACCOUNT_NO_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
worksheet.setColumnWidth(LoanRepaymentConstants.PRODUCT_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
worksheet.setColumnWidth(LoanRepaymentConstants.PRINCIPAL_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
worksheet.setColumnWidth(LoanRepaymentConstants.TOTAL_OUTSTANDING_AMOUNT_COL,TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
worksheet.setColumnWidth(LoanRepaymentConstants.LOAN_DISBURSEMENT_DATE_COL,TemplatePopulateImportConstants.MEDIUM_COL_SIZE);
worksheet.setColumnWidth(LoanRepaymentConstants.AMOUNT_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
worksheet.setColumnWidth(LoanRepaymentConstants.REPAID_ON_DATE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
worksheet.setColumnWidth(LoanRepaymentConstants.REPAYMENT_TYPE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
@@ -250,6 +268,7 @@ public class LoanRepaymentWorkbookPopulator extends AbstractWorkbookPopulator {
worksheet.setColumnWidth(LoanRepaymentConstants.LOOKUP_ACCOUNT_NO_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
worksheet.setColumnWidth(LoanRepaymentConstants.LOOKUP_PRODUCT_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
worksheet.setColumnWidth(LoanRepaymentConstants.LOOKUP_PRINCIPAL_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
worksheet.setColumnWidth(LoanRepaymentConstants.LOOKUP_TOTAL_OUTSTANDING_AMOUNT_COL,TemplatePopulateImportConstants.LARGE_COL_SIZE);
worksheet.setColumnWidth(LoanRepaymentConstants.LOOKUP_LOAN_DISBURSEMENT_DATE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE);
writeString(LoanRepaymentConstants.OFFICE_NAME_COL, rowHeader, "Office Name*");
writeString(LoanRepaymentConstants.CLIENT_NAME_COL, rowHeader, "Client Name*");
@@ -257,6 +276,8 @@ public class LoanRepaymentWorkbookPopulator extends AbstractWorkbookPopulator {
writeString(LoanRepaymentConstants.LOAN_ACCOUNT_NO_COL, rowHeader, "Loan Account No.*");
writeString(LoanRepaymentConstants.PRODUCT_COL, rowHeader, "Product Name");
writeString(LoanRepaymentConstants.PRINCIPAL_COL, rowHeader, "Principal");
writeString(LoanRepaymentConstants.TOTAL_OUTSTANDING_AMOUNT_COL,rowHeader,"Total Outstanding Amount");
writeString(LoanRepaymentConstants.LOAN_DISBURSEMENT_DATE_COL,rowHeader,"Loan Disbursement Date");
writeString(LoanRepaymentConstants.AMOUNT_COL, rowHeader, "Amount Repaid*");
writeString(LoanRepaymentConstants.REPAID_ON_DATE_COL, rowHeader, "Date*");
writeString(LoanRepaymentConstants.REPAYMENT_TYPE_COL, rowHeader, "Type*");
@@ -270,6 +291,7 @@ public class LoanRepaymentWorkbookPopulator extends AbstractWorkbookPopulator {
writeString(LoanRepaymentConstants.LOOKUP_ACCOUNT_NO_COL, rowHeader, "Lookup Account");
writeString(LoanRepaymentConstants.LOOKUP_PRODUCT_COL, rowHeader, "Lookup Product");
writeString(LoanRepaymentConstants.LOOKUP_PRINCIPAL_COL, rowHeader, "Lookup Principal");
writeString(LoanRepaymentConstants.LOOKUP_TOTAL_OUTSTANDING_AMOUNT_COL,rowHeader,"Lookup Total Outstanding amount");
writeString(LoanRepaymentConstants.LOOKUP_LOAN_DISBURSEMENT_DATE_COL, rowHeader, "Lookup Loan Disbursement Date");
}
@@ -185,7 +185,7 @@ public class RecurringDepositTransactionWorkbookPopulator extends AbstractWorkbo
for(SavingsAccountData savingsAccount : savingsAccounts) {
row = savingsTransactionSheet.createRow(rowIndex++);
writeString(TransactionConstants.LOOKUP_CLIENT_NAME_COL, row, savingsAccount.getClientName() + "(" + savingsAccount.getClientId() + ")");
writeLong(TransactionConstants.LOOKUP_ACCOUNT_NO_COL, row, Long.parseLong(savingsAccount.getAccountNo()));
writeString(TransactionConstants.LOOKUP_ACCOUNT_NO_COL, row, savingsAccount.getAccountNo());
writeString(TransactionConstants.LOOKUP_PRODUCT_COL, row, savingsAccount.getSavingsProductName());
if(savingsAccount.getMinRequiredOpeningBalance() != null)
writeBigDecimal(TransactionConstants.LOOKUP_OPENING_BALANCE_COL, row, savingsAccount.getMinRequiredOpeningBalance());
@@ -184,7 +184,7 @@ public class SavingsTransactionsWorkbookPopulator extends AbstractWorkbookPopula
for(SavingsAccountData savingsAccount : savingsAccounts) {
row = savingsTransactionSheet.createRow(rowIndex++);
writeString(TransactionConstants.LOOKUP_CLIENT_NAME_COL, row, savingsAccount.getClientName() + "(" + savingsAccount.getClientId() + ")");
writeLong(TransactionConstants.LOOKUP_ACCOUNT_NO_COL, row, Long.parseLong(savingsAccount.getAccountNo()));
writeString(TransactionConstants.LOOKUP_ACCOUNT_NO_COL, row, savingsAccount.getAccountNo());
writeString(TransactionConstants.LOOKUP_PRODUCT_COL, row, savingsAccount.getSavingsProductName());
if(savingsAccount.getMinRequiredOpeningBalance() != null)
writeBigDecimal(TransactionConstants.LOOKUP_OPENING_BALANCE_COL, row, savingsAccount.getMinRequiredOpeningBalance());
@@ -32,6 +32,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
@@ -52,6 +53,7 @@ import org.springframework.stereotype.Component;
@Produces({ MediaType.APPLICATION_JSON })
@Component
@Scope("singleton")
@Api(value = "Cache", description = "The following settings are possible for cache:\n" + "\n" + "No Caching: caching turned off\n" + "Single node: caching on for single instance deployments of platorm (works for multiple tenants but only one tomcat)\n" + "By default caching is set to No Caching. Switching between caches results in the cache been clear e.g. from Single node to No cache and back again would clear down the single node cache.")
public class CacheApiResource {
private final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList("id"));
@@ -76,6 +78,8 @@ public class CacheApiResource {
}
@GET
@ApiOperation(value = "Retrieve Cache Types", notes = "Returns the list of caches.\n" + "\n" + "Example Requests:\n" + "\n" + "caches")
@ApiResponses({@ApiResponse(code = 200, message = "", response = CacheApiResourceSwagger.GetCachesResponse.class, responseContainer = "list")})
public String retrieveAll(@Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
@@ -87,7 +91,10 @@ public class CacheApiResource {
}
@PUT
public String switchCache(final String apiRequestBodyAsJson) {
@ApiOperation(value = "Switch Cache", notes = "Switches the cache to chosen one.")
@ApiImplicitParams({@ApiImplicitParam(value = "body", required = true, paramType = "body", dataType = "body", format = "body", dataTypeClass = CacheApiResourceSwagger.PutCachesRequest.class )})
@ApiResponses({@ApiResponse(code = 200, message = "", response = CacheApiResourceSwagger.PutCachesResponse.class)})
public String switchCache(@ApiParam(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateCache().withJson(apiRequestBodyAsJson).build();
@@ -0,0 +1,68 @@
/**
* 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.infrastructure.cache.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
/**
* Created by sanyam on 28/7/17.
*/
final class CacheApiResourceSwagger {
private CacheApiResourceSwagger() {
}
@ApiModel(value = "GetCachesResponse")
public static final class GetCachesResponse {
private GetCachesResponse() {
}
public EnumOptionData cacheType;
public boolean enabled;
}
@ApiModel(value = "PutCachesRequest")
public static final class PutCachesRequest {
private PutCachesRequest() {
}
@ApiModelProperty(example = "2")
public Long cacheType;
}
@ApiModel(value = "PutCachesResponse")
public static final class PutCachesResponse {
private PutCachesResponse() {
}
public static final class PutCachechangesSwagger{
private PutCachechangesSwagger() {
}
@ApiModelProperty(example = "2")
public Long cacheType;
}
public PutCachechangesSwagger cacheType;
}
}
@@ -33,6 +33,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
import org.apache.commons.lang.StringUtils;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
@@ -61,6 +62,7 @@ import com.google.gson.JsonElement;
@Path("/smscampaigns")
@Component
@Scope("singleton")
@Api(value = "SMS Campaigns")
public class SmsCampaignApiResource {
private final PlatformSecurityContext platformSecurityContext;
@@ -96,6 +98,8 @@ public class SmsCampaignApiResource {
@GET
@Path("template")
@ApiOperation(value = "Retrieve a SMS Campaign", notes = "Example Requests:\n" + "\n" + "smscampaigns/1\n" + "\n" + "\n" + "smscampaigns/1?template=true\n" + "\n" + "\n" + "smscampaigns/template")
@ApiResponse(code = 200, message = "", response = SmsCampaignData.class)
public String template(@Context final UriInfo uriInfo) {
this.platformSecurityContext.authenticatedUser().validateHasReadPermission(SmsCampaignConstants.RESOURCE_NAME);
final SmsCampaignData smsCampaignData = this.smsCampaignReadPlatformService.retrieveTemplate(CampaignType.SMS.name());
@@ -106,7 +110,10 @@ public class SmsCampaignApiResource {
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String createCampaign(final String apiRequestBodyAsJson) {
@ApiOperation(value = "Create a SMS Campaign", notes = "Mandatory Fields\n" + "campaignName, campaignType, triggerType, providerId, runReportId, message\n" + "\n" + "Mandatory Fields for Cash based on selected report id\n" + "paramValue in json format")
@ApiImplicitParams({@ApiImplicitParam(value = "body", required = true, paramType = "body", dataType = "body", format = "body", dataTypeClass =CommandWrapper.class)})
@ApiResponse(code = 200, message = "", response = CommandProcessingResult.class)
public String createCampaign(@ApiParam(hidden = true) final String apiRequestBodyAsJson) {
this.platformSecurityContext.authenticatedUser();
final CommandWrapper commandRequest = new CommandWrapperBuilder().createSmsCampaign().withJson(apiRequestBodyAsJson).build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
@@ -116,6 +123,8 @@ public class SmsCampaignApiResource {
@GET
@Path("{resourceId}")
@Produces({ MediaType.APPLICATION_JSON })
@ApiOperation(value = "Retrieve a SMS Campaign", notes = "Example Requests:\n" + "\n" + "smscampaigns/1\n")
@ApiResponse(code = 200, message = "", response = SmsCampaignData.class)
public String retrieveCampaign(@PathParam("resourceId") final Long resourceId, @Context final UriInfo uriInfo) {
this.platformSecurityContext.authenticatedUser().validateHasReadPermission(SmsCampaignConstants.RESOURCE_NAME);
SmsCampaignData smsCampaignData = this.smsCampaignReadPlatformService.retrieveOne(resourceId);
@@ -126,6 +135,8 @@ public class SmsCampaignApiResource {
@GET
@Produces({ MediaType.APPLICATION_JSON })
@ApiOperation(value = "List SMS Campaigns", notes = "Example Requests:\n" + "\n" + "smscampaigns")
@ApiResponse(code = 200, message = "", response = SmsCampaignData.class)
public String retrieveAllEmails(@QueryParam("sqlSearch") final String sqlSearch,
@QueryParam("offset") final Integer offset, @QueryParam("limit") final Integer limit,
@QueryParam("orderBy") final String orderBy, @QueryParam("sortOrder") final String sortOrder, @Context final UriInfo uriInfo) {
@@ -140,7 +151,10 @@ public class SmsCampaignApiResource {
@Path("{campaignId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String updateCampaign(@PathParam("campaignId") final Long campaignId, final String apiRequestBodyAsJson) {
@ApiOperation(value = "Update a Campaign")
@ApiImplicitParams({@ApiImplicitParam(value = "body", required = true, paramType = "body", dataType = "body", format = "body", dataTypeClass = CommandWrapper.class)})
@ApiResponse(code = 200, message = "", response = CommandProcessingResult.class)
public String updateCampaign(@PathParam("campaignId") final Long campaignId, @ApiParam(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateSmsCampaign(campaignId).withJson(apiRequestBodyAsJson)
.build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
@@ -151,8 +165,10 @@ public class SmsCampaignApiResource {
@Path("{campaignId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@ApiOperation(value = "SMS Campaign", notes = "Activates | Deactivates | Reactivates")
@ApiResponse(code = 200, message = "", response = CommandProcessingResult.class)
public String handleCommands(@PathParam("campaignId") final Long campaignId, @QueryParam("command") final String commandParam,
final String apiRequestBodyAsJson) {
@ApiParam(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
CommandProcessingResult result = null;
CommandWrapper commandRequest = null;
@@ -187,6 +203,8 @@ public class SmsCampaignApiResource {
@DELETE
@Path("{campaignId}")
@ApiOperation(value = "Delete a SMS Campaign", notes = "Note: Only closed SMS Campaigns can be deleted")
@ApiResponse(code = 200, message = "", response = CommandProcessingResult.class)
public String delete(@PathParam("campaignId") final Long campaignId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteSmsCampaign(campaignId).build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
@@ -35,6 +35,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
@@ -54,6 +55,7 @@ import org.springframework.stereotype.Component;
@Path("/codes/{codeId}/codevalues")
@Component
@Scope("singleton")
@Api(value = "Code Values", description = "Code and code values: Codes represent a specific category of data, their code values are a specific instance of that category.\n" + "\n" + "Codes are mostly system defined which means the code itself comes out of the box and cannot be modified however its code values can be. e.g. 'Customer Identifier', it defaults to a code value of 'Passport' but could be 'Drivers License, National Id' etc")
public class CodeValuesApiResource {
/**
@@ -86,7 +88,9 @@ public class CodeValuesApiResource {
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveAllCodeValues(@Context final UriInfo uriInfo, @PathParam("codeId") final Long codeId) {
@ApiOperation(value = "List Code Values", notes = "Returns the list of Code Values for a given Code\n" + "\n" + "Example Requests:\n" + "\n" + "codes/1/codevalues")
@ApiResponses({@ApiResponse(code = 200, message = "A List of Given response", response = CodeValuesApiResourceSwagger.GetCodeValuesDataResponse.class, responseContainer = "list")})
public String retrieveAllCodeValues(@Context final UriInfo uriInfo, @PathParam("codeId") @ApiParam(value = "codeId") final Long codeId) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
@@ -100,7 +104,9 @@ public class CodeValuesApiResource {
@Path("{codeValueId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveCodeValue(@Context final UriInfo uriInfo, @PathParam("codeValueId") final Long codeValueId) {
@ApiOperation(value = "Retrieve a Code Value", notes = "Returns the details of a Code Value\n" + "\n" + "Example Requests:\n" + "\n" + "codes/1/codevalues/1")
@ApiResponses({@ApiResponse(code = 200, message = "", response = CodeValuesApiResourceSwagger.GetCodeValuesDataResponse.class)})
public String retrieveCodeValue(@Context final UriInfo uriInfo, @PathParam("codeValueId") @ApiParam(value = "codeValueId") final Long codeValueId) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
@@ -113,7 +119,10 @@ public class CodeValuesApiResource {
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String createCodeValue(@PathParam("codeId") final Long codeId, final String apiRequestBodyAsJson) {
@ApiOperation(value = "Create a Code Value", notes = "")
@ApiImplicitParams({@ApiImplicitParam(value = "body", required = true, paramType = "body", dataType = "body", format = "body", dataTypeClass = CodeValuesApiResourceSwagger.PostCodeValuesDataRequest.class )})
@ApiResponses({@ApiResponse(code = 200, message = "", response = CodeValuesApiResourceSwagger.PostCodeValueDataResponse.class)})
public String createCodeValue(@PathParam("codeId") @ApiParam(value = "codeId") final Long codeId, @ApiParam(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().createCodeValue(codeId).withJson(apiRequestBodyAsJson).build();
@@ -127,8 +136,11 @@ public class CodeValuesApiResource {
@Path("{codeValueId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String updateCodeValue(@PathParam("codeId") final Long codeId, @PathParam("codeValueId") final Long codeValueId,
final String apiRequestBodyAsJson) {
@ApiOperation(value = "Update a Code Value", notes = "Updates the details of a code value.")
@ApiImplicitParams({@ApiImplicitParam(value = "body", required = true, paramType = "body", dataType = "body", format = "body", dataTypeClass = CodeValuesApiResourceSwagger.PutCodeValuesDataRequest.class )})
@ApiResponses({@ApiResponse(code = 200, message = "", response = CodeValuesApiResourceSwagger.PutCodeValueDataResponse.class)})
public String updateCodeValue(@PathParam("codeId") @ApiParam(value = "codeId") final Long codeId, @PathParam("codeValueId") @ApiParam(value = "codeValueId") final Long codeValueId,
@ApiParam(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateCodeValue(codeId, codeValueId)
.withJson(apiRequestBodyAsJson).build();
@@ -142,7 +154,9 @@ public class CodeValuesApiResource {
@Path("{codeValueId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String deleteCodeValue(@PathParam("codeId") final Long codeId, @PathParam("codeValueId") final Long codeValueId) {
@ApiOperation(value = "Delete a Code Value", notes = "Deletes a code value")
@ApiResponses({@ApiResponse(code = 200, message = "", response = CodeValuesApiResourceSwagger.DeleteCodeValueDataResponse.class)})
public String deleteCodeValue(@PathParam("codeId") @ApiParam(value = "codeId") final Long codeId, @PathParam("codeValueId") @ApiParam(value = "codeValueId") final Long codeValueId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteCodeValue(codeId, codeValueId).build();
@@ -0,0 +1,109 @@
/**
* 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.infrastructure.codes.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
* Created by sanyam on 30/7/17.
*/
final class CodeValuesApiResourceSwagger {
private CodeValuesApiResourceSwagger() {
}
@ApiModel(value = "GetCodeValuesDataResponse")
public static final class GetCodeValuesDataResponse {
private GetCodeValuesDataResponse() {
}
@ApiModelProperty(example = "1")
public Long id;
@ApiModelProperty(example = "Passport")
public String name;
@ApiModelProperty(example = "Passport information")
public String description;
@ApiModelProperty(example = "0")
public Integer position;
}
@ApiModel(value = "PostCodeValuesDataRequest")
public static final class PostCodeValuesDataRequest {
private PostCodeValuesDataRequest() {
}
@ApiModelProperty(example = "Passport")
public String name;
@ApiModelProperty(example = "Passport information")
public String description;
@ApiModelProperty(example = "0")
public Integer position;
}
@ApiModel(value = "PostCodeValueDataResponse")
public static final class PostCodeValueDataResponse {
private PostCodeValueDataResponse() {
}
@ApiModelProperty(example = "4")
public Long resourceId;
}
@ApiModel(value = "PutCodeValuesDataRequest")
public static final class PutCodeValuesDataRequest {
private PutCodeValuesDataRequest() {
}
@ApiModelProperty(example = "Passport")
public String name;
@ApiModelProperty(example = "Passport information")
public String description;
@ApiModelProperty(example = "0")
public Integer position;
}
@ApiModel(value = "PutCodeValueDataResponse")
public static final class PutCodeValueDataResponse {
private PutCodeValueDataResponse() {
}
private final class PutCodeValuechangesSwagger{
private PutCodeValuechangesSwagger() {}
@ApiModelProperty(example = "Passport")
public String name;
@ApiModelProperty(example = "Passport information")
public String description;
@ApiModelProperty(example = "0")
public Integer position;
}
@ApiModelProperty(example = "4")
public Long resourceId;
public PutCodeValuechangesSwagger changes;
}
@ApiModel(value = "DeleteCodeValueDataResponse")
public static final class DeleteCodeValueDataResponse {
private DeleteCodeValueDataResponse() {
}
@ApiModelProperty(example = "4")
public Long resourceId;
}
}
@@ -35,6 +35,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
@@ -52,6 +53,7 @@ import org.springframework.stereotype.Component;
@Path("/codes")
@Component
@Scope("singleton")
@Api(value = "Codes", description = "Code and code values: Codes represent a specific category of data, their code values are a specific instance of that category.\n" + "\n" + "Codes are mostly system defined which means the code itself comes out of the box and cannot be modified however its code values can be. e.g. 'Customer Identifier', it defaults to a code value of 'Passport' but could be 'Drivers License, National Id' etc")
public class CodesApiResource {
/**
@@ -80,6 +82,8 @@ public class CodesApiResource {
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@ApiOperation(value = "Retrieve Codes", notes = "Returns the list of codes.\n" + "\n" + "Example Requests:\n" + "\n" + "codes")
@ApiResponses({@ApiResponse(code = 200, message = "", response = CodesApiResourceSwagger.GetCodesResponse.class, responseContainer = "list")})
public String retrieveCodes(@Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
@@ -93,7 +97,10 @@ public class CodesApiResource {
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String createCode(final String apiRequestBodyAsJson) {
@ApiOperation(value = "Create a Code", notes = "Creates a code. Codes created through api are always 'user defined' and so system defined is marked as false.")
@ApiImplicitParams({@ApiImplicitParam(value = "body", required = true, paramType = "body", dataType = "body", format = "body", dataTypeClass = CodesApiResourceSwagger.PostCodesRequest.class )})
@ApiResponses({@ApiResponse(code = 200, message = "", response = CodesApiResourceSwagger.PostCodesResponse.class)})
public String createCode(@ApiParam(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().createCode().withJson(apiRequestBodyAsJson).build();
@@ -106,7 +113,9 @@ public class CodesApiResource {
@Path("{codeId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveCode(@PathParam("codeId") final Long codeId, @Context final UriInfo uriInfo) {
@ApiOperation(value = "Retrieve a Code", notes = "Returns the details of a Code.\n" + "\n" + "Example Requests:\n" + "\n" + "codes/1")
@ApiResponses({@ApiResponse(code = 200, message = "", response = CodesApiResourceSwagger.GetCodesResponse.class)})
public String retrieveCode(@PathParam("codeId") @ApiParam(value = "codeId") final Long codeId, @Context final UriInfo uriInfo) {
final CodeData code = this.readPlatformService.retrieveCode(codeId);
@@ -118,7 +127,10 @@ public class CodesApiResource {
@Path("{codeId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String updateCode(@PathParam("codeId") final Long codeId, final String apiRequestBodyAsJson) {
@ApiOperation(value = "Update a Code", notes = "Updates the details of a code if it is not system defined.")
@ApiImplicitParams({@ApiImplicitParam(value = "body", required = true, paramType = "body", dataType = "body", format = "body", dataTypeClass = CodesApiResourceSwagger.PutCodesRequest.class )})
@ApiResponses({@ApiResponse(code = 200, message = "", response = CodesApiResourceSwagger.PutCodesResponse.class)})
public String updateCode(@PathParam("codeId") @ApiParam(value = "codeId") final Long codeId, @ApiParam(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateCode(codeId).withJson(apiRequestBodyAsJson).build();
@@ -131,7 +143,9 @@ public class CodesApiResource {
@Path("{codeId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String deleteCode(@PathParam("codeId") final Long codeId) {
@ApiOperation(value = "Delete a Code", notes = "Deletes a code if it is not system defined.")
@ApiResponses({@ApiResponse(code = 200, message = "", response = CodesApiResourceSwagger.DeleteCodesResponse.class)})
public String deleteCode(@PathParam("codeId") @ApiParam(value = "codeId") final Long codeId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteCode(codeId).build();
@@ -0,0 +1,95 @@
/**
* 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.infrastructure.codes.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
* Created by sanyam on 29/7/17.
*/
final class CodesApiResourceSwagger {
private CodesApiResourceSwagger() {
// this class is only for Swagger Live Documentation
}
@ApiModel(value = "GetCodesResponse")
public static final class GetCodesResponse {
private GetCodesResponse() {
}
@ApiModelProperty(example = "1")
public Long id;
@ApiModelProperty(example = "Education")
public String name;
@ApiModelProperty(example = "true")
public boolean systemDefined;
}
@ApiModel(value = "PostCodesRequest")
public static final class PostCodesRequest {
private PostCodesRequest() {
}
@ApiModelProperty(example = "MyNewCode")
public String name;
}
@ApiModel(value = "PostCodesResponse")
public static final class PostCodesResponse {
private PostCodesResponse() {
}
@ApiModelProperty(example = "4")
public Long resourceId;
}
@ApiModel(value = "PutCodesRequest")
public static final class PutCodesRequest {
private PutCodesRequest() {
}
@ApiModelProperty(example = "MyNewCode(changed)")
public String name;
}
@ApiModel(value = "PutCodesResponse")
public static final class PutCodesResponse {
private PutCodesResponse() {
}
private final class PutCodesApichangesSwagger{
private PutCodesApichangesSwagger() {}
@ApiModelProperty(example = "MyNewCode(changed)")
public String name;
}
@ApiModelProperty(example = "4")
public Long resourceId;
public PutCodesApichangesSwagger changes;
}
@ApiModel(value = "DeleteCodesResponse")
public static final class DeleteCodesResponse {
private DeleteCodesResponse() {
}
@ApiModelProperty(example = "4")
public Long resourceId;
}
}
@@ -30,6 +30,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
@@ -47,6 +48,7 @@ import org.springframework.stereotype.Component;
@Path("/externalservice")
@Component
@Scope("singleton")
@Api(value = "External Services", description = "External Services Configuration related to set of supported configurations for third party services like Amazon S3 and SMTP:\n" + "\n" + "S3 (Amazon S3):\n" + "s3_access_key -\n" + "s3_bucket_name -\n" + "s3_secret_key -\n" + "\n" + "\n" + "SMTP (Email Service):\n" + "username -\n" + "password -\n" + "host -\n" + "port -\n" + "useTLS -")
public class ExternalServicesConfigurationApiResource {
private final PlatformSecurityContext context;
@@ -75,7 +77,9 @@ public class ExternalServicesConfigurationApiResource {
@Path("{servicename}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveOne(@PathParam("servicename") final String serviceName, @Context final UriInfo uriInfo) {
@ApiOperation(value = "Retrieve External Services Configuration", notes = "Returns a external Service configurations based on the Service Name.\n" + "\n" + "Service Names supported are S3 and SMTP.\n" + "\n" + "Example Requests:\n" + "\n" + "externalservice/SMTP")
@ApiResponses({@ApiResponse(code = 200, message = "", response = ExternalServicesPropertiesData.class)})
public String retrieveOne(@PathParam("servicename") @ApiParam(value = "servicename") final String serviceName, @Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(ExternalServiceConfigurationApiConstant.EXTERNAL_SERVICE_RESOURCE_NAME);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
final Collection<ExternalServicesPropertiesData> externalServiceNVPs = this.externalServicePropertiesReadPlatformService
@@ -88,7 +92,11 @@ public class ExternalServicesConfigurationApiResource {
@Path("{servicename}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String updateExternalServiceProperties(@PathParam("servicename") final String serviceName, final String apiRequestBodyAsJson) {
@ApiOperation(value = "Update External Service", notes = "Updates the external Service Configuration for a Service Name.\n" + "\n" + "Example: \n" + "\n" + "externalservice/S3")
@ApiImplicitParams({@ApiImplicitParam(value = "body", required = true, paramType = "body", dataType = "body", format = "body", dataTypeClass = ExternalServicesConfigurationApiResourceSwagger.PutExternalServiceRequest.class )})
@ApiResponses({@ApiResponse(code = 200, message = "")})
public String updateExternalServiceProperties(@PathParam("servicename") @ApiParam(value = "servicename") final String serviceName,
@ApiParam(hidden = true) final String apiRequestBodyAsJson) {
// ExternalServicesData external =
// this.externalServiceReadPlatformService.getExternalServiceDetailsByServiceName(serviceName);
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateExternalServiceProperties(serviceName)
@@ -0,0 +1,42 @@
/**
* 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.infrastructure.configuration.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
* Created by sanyam on 30/7/17.
*/
final class ExternalServicesConfigurationApiResourceSwagger {
private ExternalServicesConfigurationApiResourceSwagger() {
}
@ApiModel(value = "PutExternalServiceRequest")
public static final class PutExternalServiceRequest{
private PutExternalServiceRequest() {
}
@ApiModelProperty(example = "test@mifos.org")
public String username;
@ApiModelProperty(example = "XXXX")
public String password;
}
}
@@ -27,6 +27,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
@@ -45,6 +46,7 @@ import org.springframework.stereotype.Component;
@Path("/configurations")
@Component
@Scope("singleton")
@Api(value = "Global Configuration", description = "Global configuration related to set of supported enable/disable configurations:\n" + "\n" + "maker-checker - defaults to false - if true turns on maker-checker functionality\n" + "reschedule-future-repayments - defaults to false - if true reschedules repayemnts which falls on a non-working day to configured repayment rescheduling rule\n" + "allow-transactions-on-non_workingday - defaults to false - if true allows transactions on non-working days\n" + "reschedule-repayments-on-holidays - defaults to false - if true reschedules repayemnts which falls on a non-working day to defined reschedule date\n" + "allow-transactions-on-holiday - defaults to false - if true allows transactions on holidays\n" + "savings-interest-posting-current-period-end - Set it at the database level before any savings interest is posted. When set as false(default), interest will be posted on the first date of next period. If set as true, interest will be posted on last date of current period. There is no difference in the interest amount posted.\n" + "financial-year-beginning-month - Set it at the database level before any savings interest is posted. Allowed values 1 - 12 (January - December). Interest posting periods are evaluated based on this configuration.\n" + "meetings-mandatory-for-jlg-loans - if set to true, enforces all JLG loans to follow a meeting schedule belonging to either the parent group or Center.")
public class GlobalConfigurationApiResource {
private final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList("globalConfiguration"));
@@ -76,7 +78,9 @@ public class GlobalConfigurationApiResource {
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveConfiguration(@Context final UriInfo uriInfo,@DefaultValue("false") @QueryParam("survey") final boolean survey) {
@ApiOperation(value = "Retrieve Global Configuration | Retrieve Global Configuration for surveys", notes = "Returns the list global enable/disable configurations.\n" + "\n" + "Example Requests:\n" + "\n" + "configurations\n\n" + "\n" + "Returns the list global enable/disable survey configurations.\n" + "\n" + "Example Requests:\n" + "\n" + "configurations/survey")
@ApiResponses({@ApiResponse(code = 200, message = "List of example \n response \nsurveys response \ngiven below", response = GlobalConfigurationApiResourceSwagger.GetGlobalConfigurationsResponse.class, responseContainer = "list")})
public String retrieveConfiguration(@Context final UriInfo uriInfo,@DefaultValue("false") @QueryParam("survey") @ApiParam(value = "survey") final boolean survey) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
@@ -90,7 +94,9 @@ public class GlobalConfigurationApiResource {
@Path("{configId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveOne(@PathParam("configId") final Long configId, @Context final UriInfo uriInfo) {
@ApiOperation(value = "Retrieve Global Configuration", notes = "Returns a global enable/disable configurations.\n" + "\n" + "Example Requests:\n" + "\n" + "configurations/1")
@ApiResponses({@ApiResponse(code = 200, message = "", response = GlobalConfigurationApiResourceSwagger.GetGlobalConfigurationsResponse.class)})
public String retrieveOne(@PathParam("configId") @ApiParam(value = "configId") final Long configId, @Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
@@ -105,7 +111,10 @@ public class GlobalConfigurationApiResource {
@Path("{configId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String updateConfiguration(@PathParam("configId") final Long configId, final String apiRequestBodyAsJson) {
@ApiOperation(value = "Update Global Configuration", notes = "Updates an enable/disable global configuration item.")
@ApiImplicitParams({@ApiImplicitParam(value = "body", required = true, paramType = "body", dataType = "body", format = "body", dataTypeClass = GlobalConfigurationApiResourceSwagger.PutGlobalConfigurationsRequest.class )})
@ApiResponses({@ApiResponse(code = 200, message = "", response = GlobalConfigurationApiResourceSwagger.PutGlobalConfigurationsResponse.class)})
public String updateConfiguration(@PathParam("configId") @ApiParam(value = "configId") final Long configId, @ApiParam(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
.updateGlobalConfiguration(configId) //
@@ -0,0 +1,63 @@
/**
* 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.infrastructure.configuration.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.fineract.infrastructure.configuration.data.GlobalConfigurationPropertyData;
import java.util.List;
/**
* Created by sanyam on 30/7/17.
*/
final class GlobalConfigurationApiResourceSwagger {
private GlobalConfigurationApiResourceSwagger() {
}
@ApiModel(value = "GetGlobalConfigurationsResponse")
public static final class GetGlobalConfigurationsResponse {
private GetGlobalConfigurationsResponse(){}
public List<GlobalConfigurationPropertyData> globalConfiguration;
}
@ApiModel(value = "PutGlobalConfigurationsRequest")
public static final class PutGlobalConfigurationsRequest {
private PutGlobalConfigurationsRequest(){}
@ApiModelProperty(example = "true")
public boolean enabled;
@ApiModelProperty(example = "2")
public Long value;
}
@ApiModel(value = "PutGlobalConfigurationsResponse")
public static final class PutGlobalConfigurationsResponse {
private PutGlobalConfigurationsResponse(){}
final class PutGlobalConfigurationsResponsechangesSwagger{
private PutGlobalConfigurationsResponsechangesSwagger() {}
@ApiModelProperty(example = "true")
public boolean enabled;
}
@ApiModelProperty(example = "4")
public Long resourceId;
public PutGlobalConfigurationsResponsechangesSwagger changes;
}
}
@@ -35,6 +35,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.Api;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
@@ -58,6 +59,7 @@ import org.springframework.stereotype.Component;
@Path("/CreditBureauConfiguration")
@Component
@Scope("singleton")
@Api(value = "CreditBureau Configuration")
public class CreditBureauConfigurationAPI {
private final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>(
Arrays.asList("creditBureauId", "alias", "country", "creditBureauProductId", "startDate", "endDate", "isActive"));
@@ -85,10 +85,10 @@ public class CreditBureauReadConfigurationServiceImpl implements CreditBureauRea
this.context.authenticatedUser();
final CbConfigMapper rm = new CbConfigMapper();
final String sql = "select " + rm.schema() + " where cbconfig.organisation_creditbureau_id=" + id;
final String sql = "select " + rm.schema() + " where cbconfig.organisation_creditbureau_id= ?";
List<CreditBureauConfigurationData> config = (List<CreditBureauConfigurationData>) this.jdbcTemplate.query(sql,
rm, new Object[] {});
rm, new Object[] {id});
Map<String, String> configuration = new HashMap<String, String>();
for (CreditBureauConfigurationData data : config) {
configuration.put(data.getConfigurationKey(), data.getValue());
@@ -33,6 +33,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
@@ -55,6 +56,7 @@ import org.springframework.stereotype.Component;
@Path("/datatables")
@Component
@Scope("singleton")
@Api(value = "Data Tables", description = "The datatables API allows you to plug-in your own tables (MySql) that have a relationship to a Apache Fineract core table. For example, you might want to add some extra client fields and record information about each of the clients' family members. Via the API you can create, read, update and delete entries for each 'plugged-in' table. The API checks for permission and for 'data scoping' (only data within the users' office hierarchy can be managed by the user).\n" + "\n" + "The Apache Fineract Reference App uses a JQuery plug-in called stretchydatatables (which in turn uses this datatables resource) to provide a pretty flexible CRUD (Create, Read, Update, Delete) User Interface.")
public class DatatablesApiResource {
private final PlatformSecurityContext context;
@@ -79,7 +81,10 @@ public class DatatablesApiResource {
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String getDatatables(@QueryParam("apptable") final String apptable, @Context final UriInfo uriInfo) {
@ApiOperation(value = "List Data Tables", notes = "Lists registered data tables and the Apache Fineract Core application table they are registered to.\n" + "\n" + "ARGUMENTS\n" + "\n" + "apptable - optional" + "\n"+ "The Apache Fineract core application table.\n" + "\n" + "Example Requests:\n" + "\n" + "datatables?apptable=m_client\n" + "\n" + "\n" + "datatables",
responseContainer = "List", response = DatatablesApiResourceSwagger.GetDataTablesResponse.class)
@ApiResponses({@ApiResponse(code = 200, message = "", response = DatatablesApiResourceSwagger.GetDataTablesResponse.class, responseContainer = "list")})
public String getDatatables(@QueryParam("apptable") @ApiParam(value = "apptable") final String apptable, @Context final UriInfo uriInfo) {
final List<DatatableData> result = this.readWriteNonCoreDataService.retrieveDatatableNames(apptable);
@@ -90,7 +95,13 @@ public class DatatablesApiResource {
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String createDatatable(final String apiRequestBodyAsJson) {
@ApiOperation(value = "Create Data Table", notes = "Create a new data table and registers it with the Apache Fineract Core application table.\n" + "\n" + "Field Descriptions\n" + "\n" + "Mandatory - datatableName : \n"+ "\nThe name of the Data Table.\n" + "\n" + "Mandatory - apptableName\n" + "\n" + "Application table name. Must be one of the following:\n" + "\n" + "m_client\n" + "\n" + "m_group" +"\n" + "\n" + "m_loan" + "\n" + "\n" + "m_office" + "\n" + "\n" + "m_saving_account" + "\n" + "\n" + "m_product_loan" + "\n" + "\n" + "m_savings_product" + "\n" + "\n" + "Mandatory - columns " + "\n" + "An array of columns in the new Data Table." + "\n" + "\n" + "Optional - multiRow" + "\n" +
"\n" + "Allows to create multiple entries in the Data Table. Optional, defaults to false. If this property is not provided Data Table will allow only one entry." + "\n" + "\n" + "Field Descriptions - columns" + "\n" + "\n" + "Mandatory - name" + "\n" + "\n" + "Name of the created column. Can contain only alphanumeric characters, underscores and spaces, but cannot start with a number. Cannot start or end with an underscore or space." + "\n" + "\n" + "Mandatory - type" + "\n" + "\n" + "Column type. Must be one of the following:" + "\n" + "\n" + "Boolean" + "\n" + "\n" + "Date" + "\n" + "\n" + "DateTime" + "\n" + "\n" + "Decimal" + "\n" + "\n" + "Dropdown" + "\n" +
"\n" + "\n" + "Number" + "\n" + "\n" + "String" + "\n" + "\n" + "Text" + "\n" + "\n" + "Mandatory [type = Dropdown] - code" + "\n" + "\n" + "Used in Code Value fields. Column name becomes: code_cd_name. Mandatory if using type Dropdown, otherwise an error is returned." + "\n" + "\n" + "Optional - mandatory" + "\n" + "\n" +
"Determines whether this column must have a value in every entry. Optional, defaults to false." + "\n" + "\n" + "Mandatory [type = String] - length" + "\n" + "\n" + "Length of the text field. Mandatory if type String is used, otherwise an error is returned.")
@ApiImplicitParams({@ApiImplicitParam(value = "body", required = true, paramType = "body", dataType = "body", format = "body", dataTypeClass = DatatablesApiResourceSwagger.PostDataTablesRequest.class )})
@ApiResponses({@ApiResponse(code = 200, message = "", response = DatatablesApiResourceSwagger.PostDataTablesResponse.class)})
public String createDatatable(@ApiParam(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().createDBDatatable(apiRequestBodyAsJson).build();
@@ -102,7 +113,10 @@ public class DatatablesApiResource {
@Path("{datatableName}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String updateDatatable(@PathParam("datatableName") final String datatableName, final String apiRequestBodyAsJson) {
@ApiOperation(value = "Update Data Table", notes = "Modifies fields of a data table. If the apptableName parameter is passed, data table is deregistered and registered with the new application table.")
@ApiImplicitParams({@ApiImplicitParam(value = "body", required = true, paramType = "body", dataType = "body", format = "body", dataTypeClass = DatatablesApiResourceSwagger.PutDataTablesRequest.class )})
@ApiResponses({@ApiResponse(code = 200, message = "", response = DatatablesApiResourceSwagger.PutDataTablesResponse.class)})
public String updateDatatable(@PathParam("datatableName") @ApiParam(value = "datatableName") final String datatableName, @ApiParam(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateDBDatatable(datatableName, apiRequestBodyAsJson).build();
@@ -114,7 +128,9 @@ public class DatatablesApiResource {
@Path("{datatableName}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String deleteDatatable(@PathParam("datatableName") final String datatableName, final String apiRequestBodyAsJson) {
@ApiOperation(value = "Delete Data Table", notes = "Deletes a data table and deregisters it from the Apache Fineract Core application table.")
@ApiResponses({@ApiResponse(code = 200, message = "", response = DatatablesApiResourceSwagger.DeleteDataTablesResponse.class)})
public String deleteDatatable(@PathParam("datatableName") @ApiParam(value = "datatableName") final String datatableName, @ApiParam(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteDBDatatable(datatableName, apiRequestBodyAsJson).build();
@@ -126,8 +142,11 @@ public class DatatablesApiResource {
@Path("register/{datatable}/{apptable}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String registerDatatable(@PathParam("datatable") final String datatable, @PathParam("apptable") final String apptable,
final String apiRequestBodyAsJson) {
@ApiOperation(value = "Register Data Table", notes = "Registers a data table with the Apache Fineract Core application table. This allows the data table to be maintained through the API. In case the datatable is a PPI (survey table), a parameter category should be pass along with the request. The API currently support one category (200)")
@ApiImplicitParams({@ApiImplicitParam(value = "body", paramType = "body", dataType = "body", format = "body", dataTypeClass = DatatablesApiResourceSwagger.PostDataTablesRegisterDatatableAppTable.class )})
@ApiResponses({@ApiResponse(code = 200, message = "", response = DatatablesApiResourceSwagger.PutDataTablesResponse.class)})
public String registerDatatable(@PathParam("datatable") @ApiParam(value = "datatable") final String datatable, @PathParam("apptable") @ApiParam(value = "apptable") final String apptable,
@ApiParam(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().registerDBDatatable(datatable, apptable)
.withJson(apiRequestBodyAsJson).build();
@@ -141,7 +160,9 @@ public class DatatablesApiResource {
@Path("deregister/{datatable}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String deregisterDatatable(@PathParam("datatable") final String datatable) {
@ApiOperation(value = "Deregister Data Table", notes = "Deregisters a data table. It will no longer be available through the API.")
@ApiResponses({@ApiResponse(code = 200, message = "", response = DatatablesApiResourceSwagger.PutDataTablesResponse.class)})
public String deregisterDatatable(@PathParam("datatable") @ApiParam(value = "datatable") final String datatable) {
this.readWriteNonCoreDataService.deregisterDatatable(datatable);
@@ -154,7 +175,9 @@ public class DatatablesApiResource {
@Path("{datatable}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String getDatatable(@PathParam("datatable") final String datatable, @Context final UriInfo uriInfo) {
@ApiOperation(value = "Retrieve Data Table Details", notes = "Lists a registered data table details and the Apache Fineract Core application table they are registered to.")
@ApiResponses({@ApiResponse(code = 200, message = "", response = DatatablesApiResourceSwagger.GetDataTablesResponse.class)})
public String getDatatable(@PathParam("datatable") @ApiParam(value = "datatable") final String datatable, @Context final UriInfo uriInfo) {
final DatatableData result = this.readWriteNonCoreDataService.retrieveDatatable(datatable);
@@ -166,8 +189,10 @@ public class DatatablesApiResource {
@Path("{datatable}/{apptableId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String getDatatable(@PathParam("datatable") final String datatable, @PathParam("apptableId") final Long apptableId,
@QueryParam("order") final String order, @Context final UriInfo uriInfo) {
@ApiOperation(value = "Retrieve Entry(s) from Data Table", notes = "Gets the entry (if it exists) for data tables that are one to one with the application table. \n" + "Gets the entries (if they exist) for data tables that are one to many with the application table.\n" + "\n" + "Note: The 'fields' parameter is not available for datatables.\n" + "\n" + "ARGUMENTS\n" + "orderoptional Specifies the order in which data is returned.genericResultSetoptional, defaults to false If 'true' an optimised JSON format is returned suitable for tabular display of data. This format is used by the default data tables UI functionality.\n" + "Example Requests:\n" + "\n" + "datatables/extra_client_details/1\n" + "\n" + "\n" + "datatables/extra_family_details/1?order=`Date of Birth` desc\n" + "\n" + "\n" + "datatables/extra_client_details/1?genericResultSet=true")
@ApiResponses({@ApiResponse(code = 200, message = "", response = DatatablesApiResourceSwagger.GetDataTablesAppTableIdResponse.class)})
public String getDatatable(@PathParam("datatable") @ApiParam(value = "datatable") final String datatable, @PathParam("apptableId") @ApiParam(value = "apptableId") final Long apptableId,
@QueryParam("order") @ApiParam(value = "order") final String order, @Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasDatatableReadPermission(datatable);
@@ -216,8 +241,11 @@ public class DatatablesApiResource {
@Path("{datatable}/{apptableId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String createDatatableEntry(@PathParam("datatable") final String datatable, @PathParam("apptableId") final Long apptableId,
final String apiRequestBodyAsJson) {
@ApiOperation(value = "Create Entry in Data Table", notes = "Adds a row to the data table.\n" + "\n" + "Note that the default datatable UI functionality converts any field name containing spaces to underscores when using the API. This means the field name \"Business Description\" is considered the same as \"Business_Description\". So you shouldn't have both \"versions\" in any data table.")
@ApiImplicitParams({@ApiImplicitParam(value = "body", required = true, paramType = "body", dataType = "body", format = "body", dataTypeClass = DatatablesApiResourceSwagger.PostDataTablesAppTableIdRequest.class )})
@ApiResponses({@ApiResponse(code = 200, message = "", response = DatatablesApiResourceSwagger.PostDataTablesAppTableIdResponse.class)})
public String createDatatableEntry(@PathParam("datatable") @ApiParam(value = "datatable") final String datatable, @PathParam("apptableId") @ApiParam(value = "apptableId") final Long apptableId,
@ApiParam(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
.createDatatable(datatable, apptableId, null) //
@@ -233,8 +261,11 @@ public class DatatablesApiResource {
@Path("{datatable}/{apptableId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String updateDatatableEntryOnetoOne(@PathParam("datatable") final String datatable,
@PathParam("apptableId") final Long apptableId, final String apiRequestBodyAsJson) {
@ApiOperation(value = "Update Entry in Data Table (One to One)", notes = "Updates the row (if it exists) of the data table.")
@ApiImplicitParams({@ApiImplicitParam(value = "body", required = true, paramType = "body", dataType = "body", format = "body", dataTypeClass = DatatablesApiResourceSwagger.PutDataTablesAppTableIdRequest.class )})
@ApiResponses({@ApiResponse(code = 200, message = "", response = DatatablesApiResourceSwagger.PutDataTablesAppTableIdResponse.class)})
public String updateDatatableEntryOnetoOne(@PathParam("datatable") @ApiParam(value = "datatable") final String datatable,
@PathParam("apptableId") @ApiParam(value = "apptableId") final Long apptableId, @ApiParam(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
.updateDatatable(datatable, apptableId, null) //
@@ -250,9 +281,12 @@ public class DatatablesApiResource {
@Path("{datatable}/{apptableId}/{datatableId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String updateDatatableEntryOneToMany(@PathParam("datatable") final String datatable,
@PathParam("apptableId") final Long apptableId, @PathParam("datatableId") final Long datatableId,
final String apiRequestBodyAsJson) {
@ApiOperation(value = "Update Entry in Data Table (One to Many)", notes = "Updates the row (if it exists) of the data table.")
@ApiImplicitParams({@ApiImplicitParam(value = "body", required = true, paramType = "body", dataType = "body", format = "body", dataTypeClass = DatatablesApiResourceSwagger.PutDataTablesAppTableIdDatatableIdRequest.class )})
@ApiResponses({@ApiResponse(code = 200, message = "", response = DatatablesApiResourceSwagger.PutDataTablesAppTableIdDatatableIdResponse.class)})
public String updateDatatableEntryOneToMany(@PathParam("datatable") @ApiParam(value = "datatable") final String datatable,
@PathParam("apptableId") @ApiParam(value = "apptableId") final Long apptableId, @PathParam("datatableId") @ApiParam(value = "datatableId") final Long datatableId,
@ApiParam(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
.updateDatatable(datatable, apptableId, datatableId) //
@@ -268,7 +302,9 @@ public class DatatablesApiResource {
@Path("{datatable}/{apptableId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String deleteDatatableEntries(@PathParam("datatable") final String datatable, @PathParam("apptableId") final Long apptableId) {
@ApiOperation(value = "Delete Entry(s) in Data Table", notes = "Deletes the entry (if it exists) for data tables that are one-to-one with the application table. \n" + "Deletes the entries (if they exist) for data tables that are one-to-many with the application table.")
@ApiResponses({@ApiResponse(code = 200, message = "", response = DatatablesApiResourceSwagger.DeleteDataTablesDatatableAppTableIdResponse.class)})
public String deleteDatatableEntries(@PathParam("datatable") @ApiParam(value = "datatable") final String datatable, @PathParam("apptableId") @ApiParam(value = "apptableId") final Long apptableId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
.deleteDatatable(datatable, apptableId, null) //
@@ -283,8 +319,10 @@ public class DatatablesApiResource {
@Path("{datatable}/{apptableId}/{datatableId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String deleteDatatableEntries(@PathParam("datatable") final String datatable, @PathParam("apptableId") final Long apptableId,
@PathParam("datatableId") final Long datatableId) {
@ApiOperation(value = "Delete Entry in Datatable (One to Many)", notes = "Deletes the entry (if it exists) for data tables that are one to many with the application table.\n" + "\n")
@ApiResponses({@ApiResponse(code = 200, message = "", response = DatatablesApiResourceSwagger.DeleteDataTablesDatatableAppTableIdDatatableIdResponse.class)})
public String deleteDatatableEntries(@PathParam("datatable") @ApiParam(value = "datatable", type = "body", example = "{}") final String datatable, @PathParam("apptableId") @ApiParam(value = "apptableId") final Long apptableId,
@PathParam("datatableId") @ApiParam(value = "datatableId") final Long datatableId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
.deleteDatatable(datatable, apptableId, datatableId) //
@@ -0,0 +1,253 @@
/**
* 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.infrastructure.dataqueries.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.fineract.infrastructure.dataqueries.data.GenericResultsetData;
import org.apache.fineract.infrastructure.dataqueries.data.ResultsetColumnHeaderData;
import org.apache.fineract.infrastructure.dataqueries.data.ResultsetRowData;
import java.util.List;
/**
* Created by sanyam on 31/7/17.
*/
final class DatatablesApiResourceSwagger {
private DatatablesApiResourceSwagger() {
}
@ApiModel(value = "GetDataTablesResponse")
public static final class GetDataTablesResponse {
private GetDataTablesResponse() {
}
@ApiModelProperty(example = "m_client")
public String appTableName;
@ApiModelProperty(example = "extra_client_details")
public String datatableName;
public List<ResultsetColumnHeaderData> column;
}
@ApiModel(value = "PostDataTablesRequest")
public static final class PostDataTablesRequest{
private PostDataTablesRequest() {
}
@ApiModelProperty(example = "m_client")
public String applicationTableName;
@ApiModelProperty(example = "extra_client_details")
public String registeredTableName;
@ApiModelProperty(example = "true")
public boolean multiRow;
public List<ResultsetColumnHeaderData> columnHeaderData;
}
@ApiModel(value = "PostDataTablesResponse")
public static final class PostDataTablesResponse{
private PostDataTablesResponse() {
}
@ApiModelProperty(example = "extra_client_details")
public String resourceIdentifier;
}
@ApiModel(value = "PutDataTablesRequest")
public static final class PutDataTablesRequest{
private PutDataTablesRequest() {
}
final class PutDataTablesRequestDropColumns {
private PutDataTablesRequestDropColumns() {}
@ApiModelProperty(example = "Gender_cd_Question")
public String name;
}
final class PutDataTablesRequestAddColumns {
private PutDataTablesRequestAddColumns() {
}
@ApiModelProperty(example = "Question")
public String name;
@ApiModelProperty(example = "Dropdown")
public String type;
@ApiModelProperty(example = "Gender")
public String code;
@ApiModelProperty(example = "true")
public boolean mandatory;
}
final class PutDataTablesRequestChangeColumns {
private PutDataTablesRequestChangeColumns() {
}
@ApiModelProperty(example = "Question")
public String name;
@ApiModelProperty(example = "Question 2")
public String newName;
@ApiModelProperty(example = "Gender")
public String code;
@ApiModelProperty(example = "Gender2")
public String newCode;
@ApiModelProperty(example = "true")
public boolean mandatory;
}
@ApiModelProperty(example = "m_client")
public String appTableName;
public List<PutDataTablesRequestDropColumns> dropColumns;
public List<PutDataTablesRequestAddColumns> addColumns;
public List<PutDataTablesRequestChangeColumns> ChangeColumns;
}
@ApiModel(value = "PutDataTablesResponse")
public static final class PutDataTablesResponse{
private PutDataTablesResponse() {
}
@ApiModelProperty(example = "extra_client_details")
public String resourceIdentifier;
}
@ApiModel(value = "DeleteDataTablesResponse")
public static final class DeleteDataTablesResponse{
private DeleteDataTablesResponse() {
}
@ApiModelProperty(example = "extra_client_details")
public String resourceIdentifier;
}
@ApiModel(value = "PostDataTablesRegisterDatatableAppTable")
public static final class PostDataTablesRegisterDatatableAppTable {
private PostDataTablesRegisterDatatableAppTable () {}
}
@ApiModel(value = "PostDataTablesAppTableIdRequest")
public static final class PostDataTablesAppTableIdRequest{
private PostDataTablesAppTableIdRequest() {
}
@ApiModelProperty(example = "Livestock sales")
public String BusinessDescription;
@ApiModelProperty(example = "First comment made")
public String Comment;
@ApiModelProperty(example = "Primary")
public String Education_cv;
@ApiModelProperty(example = "6")
public Long Gender_cd;
@ApiModelProperty(example = "8.5")
public Double HighestRatePaid;
@ApiModelProperty(example = "01 October 2012")
public String NextVisit;
@ApiModelProperty(example = "5")
public Long YearsinBusiness;
@ApiModelProperty(example = "dd MMMM yyyy")
public String dateFormat;
@ApiModelProperty(example = "en")
public String locale;
}
@ApiModel(value = "PostDataTablesAppTableIdResponse ")
public static final class PostDataTablesAppTableIdResponse {
private PostDataTablesAppTableIdResponse () {
}
@ApiModelProperty(example = "1")
public Long resourceId;
}
@ApiModel(value = "GetDataTablesAppTableIdResponse")
public static final class GetDataTablesAppTableIdResponse {
private GetDataTablesAppTableIdResponse() {
}
public List<ResultsetColumnHeaderData> columnHeaders;
public List<ResultsetRowData> data;
}
@ApiModel(value = "PutDataTablesAppTableIdRequest")
public static final class PutDataTablesAppTableIdRequest{
private PutDataTablesAppTableIdRequest() {
}
@ApiModelProperty(example = "Livestock sales updated")
public String BusinessDescription;
}
@ApiModel(value = "PutDataTablesAppTableIdResponse")
public static final class PutDataTablesAppTableIdResponse {
private PutDataTablesAppTableIdResponse() {
}
final class PutDataTablesAppTableIdResponseChanges{
private PutDataTablesAppTableIdResponseChanges () {}
@ApiModelProperty(example = "Livestock sales updated")
public String BusinessDescription;
}
@ApiModelProperty(example = "1")
public Long resourceId;
public PutDataTablesAppTableIdResponseChanges changes;
}
@ApiModel(value = "PutDataTablesAppTableIdDatatableIdRequest")
public static final class PutDataTablesAppTableIdDatatableIdRequest{
private PutDataTablesAppTableIdDatatableIdRequest() {
}
@ApiModelProperty(example = "01 June 1982")
public String DateOfBirth;
@ApiModelProperty(example = "5")
public Long Education_cdHighest;
@ApiModelProperty(example = "June")
public String Name;
@ApiModelProperty(example = "More notes")
public String OtherNotes;
@ApiModelProperty(example = "20")
public Long PointsScore;
@ApiModelProperty(example = "dd MMMM yyyy")
public String dateFormat;
@ApiModelProperty(example = "en")
public String locale;
}
@ApiModel(value = "PutDataTablesAppTableIdDatatableIdResponse ")
public static final class PutDataTablesAppTableIdDatatableIdResponse {
private PutDataTablesAppTableIdDatatableIdResponse () {
}
@ApiModelProperty(example = "1")
public Long resourceId;
}
@ApiModel(value = "DeleteDataTablesDatatableAppTableIdResponse ")
public static final class DeleteDataTablesDatatableAppTableIdResponse {
private DeleteDataTablesDatatableAppTableIdResponse () {
}
@ApiModelProperty(example = "1")
public Long resourceId;
}
@ApiModel(value = "DeleteDataTablesDatatableAppTableIdDatatableIdResponse ")
public static final class DeleteDataTablesDatatableAppTableIdDatatableIdResponse {
private DeleteDataTablesDatatableAppTableIdDatatableIdResponse () {
}
@ApiModelProperty(example = "1")
public Long resourceId;
}
}
@@ -30,6 +30,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
@@ -52,6 +53,7 @@ import org.springframework.stereotype.Component;
@Path("/entityDatatableChecks")
@Component
@Scope("singleton")
@Api(value = "Entity-Datatable Checks", description = "This defines Entity-Datatable Check.")
public class EntityDatatableChecksApiResource {
private final PlatformSecurityContext context;
@@ -76,9 +78,11 @@ public class EntityDatatableChecksApiResource {
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveAll(@Context final UriInfo uriInfo, @QueryParam("status") final Long status,
@QueryParam("entity") final String entity, @QueryParam("productId") final Long productId,
@QueryParam("offset") final Integer offset, @QueryParam("limit") final Integer limit) {
@ApiOperation(value = "List Entity-Datatable Checks", notes = "The list capability of Entity-Datatable Checks can support pagination.\n" + "\n" + "OPTIONAL ARGUMENTS\n" + "offset Integer optional, defaults to 0 Indicates the result from which pagination startslimit Integer optional, defaults to 200 Restricts the size of results returned. To override the default and return all entries you must explicitly pass a non-positive integer value for limit e.g. limit=0, or limit=-1\n" + "Example Request:\n" + "\n" + "entityDatatableChecks?offset=0&limit=15")
@ApiResponses({@ApiResponse(code = 200, message = "", response = EntityDatatableChecksApiResourceSwagger.GetEntityDatatableChecksResponse.class, responseContainer = "list")})
public String retrieveAll(@Context final UriInfo uriInfo, @QueryParam("status") @ApiParam(value = "status") final Long status,
@QueryParam("entity") @ApiParam(value = "entity") final String entity, @QueryParam("productId") @ApiParam(value = "productId") final Long productId,
@QueryParam("offset") @ApiParam(value = "offset") final Integer offset, @QueryParam("limit") @ApiParam(value = "limit") final Integer limit) {
final SearchParameters searchParameters = SearchParameters.forPagination(offset, limit);
final Page<EntityDataTableChecksData> result = this.readEntityDatatableChecksService.retrieveAll(searchParameters, status, entity,
productId);
@@ -91,6 +95,8 @@ public class EntityDatatableChecksApiResource {
@Path("template")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@ApiOperation(value = "Retrieve Entity-Datatable Checks Template", notes = "This is a convenience resource useful for building maintenance user interface screens for Entity-Datatable Checks applications. The template data returned consists of:\n" + "\n" + "Allowed Value Lists\n" + "Example Request:\n" + "\n" + "entityDatatableChecks/template")
@ApiResponses({@ApiResponse(code = 200, message = "", response = EntityDatatableChecksApiResourceSwagger.GetEntityDatatableChecksTemplateResponse.class)})
public String getTemplate(@Context final UriInfo uriInfo) {
final EntityDataTableChecksTemplateData result = this.readEntityDatatableChecksService.retrieveTemplate();
@@ -102,7 +108,10 @@ public class EntityDatatableChecksApiResource {
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String createEntityDatatableCheck(final String apiRequestBodyAsJson) {
@ApiOperation(value = "Create Entity-Datatable Checks", notes = "Mandatory Fields : \n" + "entity, status, datatableName\n" + "\n" + "Non-Mandatory Fields : \n" + "productId")
@ApiImplicitParams({@ApiImplicitParam(value = "body", required = true, paramType = "body", dataType = "body", format = "body", dataTypeClass = EntityDatatableChecksApiResourceSwagger.PostEntityDatatableChecksTemplateRequest.class )})
@ApiResponses({@ApiResponse(code = 200, message = "", response = EntityDatatableChecksApiResourceSwagger.PostEntityDatatableChecksTemplateResponse.class)})
public String createEntityDatatableCheck(@ApiParam(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().createEntityDatatableChecks(apiRequestBodyAsJson).build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
@@ -113,7 +122,9 @@ public class EntityDatatableChecksApiResource {
@Path("{entityDatatableCheckId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String deleteDatatable(@PathParam("entityDatatableCheckId") final long entityDatatableCheckId, final String apiRequestBodyAsJson) {
@ApiOperation(value = "Delete Entity-Datatable Checks", notes = "Deletes an existing Entity-Datatable Check")
@ApiResponses({@ApiResponse(code = 200, message = "", response = EntityDatatableChecksApiResourceSwagger.DeleteEntityDatatableChecksTemplateResponse.class)})
public String deleteDatatable(@PathParam("entityDatatableCheckId") @ApiParam(value = "entityDatatableCheckId") final long entityDatatableCheckId, final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteEntityDatatableChecks(entityDatatableCheckId,
apiRequestBodyAsJson).build();
@@ -0,0 +1,101 @@
/**
* 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.infrastructure.dataqueries.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
import org.apache.fineract.infrastructure.dataqueries.data.DatatableCheckStatusData;
import org.apache.fineract.infrastructure.dataqueries.data.DatatableChecksData;
import org.apache.fineract.portfolio.loanproduct.data.LoanProductData;
import org.apache.fineract.portfolio.savings.data.SavingsProductData;
import java.util.Collection;
import java.util.List;
/**
* Created by sanyam on 31/7/17.
*/
final class EntityDatatableChecksApiResourceSwagger {
private EntityDatatableChecksApiResourceSwagger() {
}
@ApiModel(value = "GetEntityDatatableChecksResponse")
public static final class GetEntityDatatableChecksResponse {
private GetEntityDatatableChecksResponse(){}
public long id;
public String entity;
public EnumOptionData status;
public String datatableName;
public boolean systemDefined;
public Long order;
public Long productId;
public String productName;
}
@ApiModel(value = "GetEntityDatatableChecksTemplateResponse")
public static final class GetEntityDatatableChecksTemplateResponse {
private GetEntityDatatableChecksTemplateResponse(){}
public List<String> entities;
public List<DatatableCheckStatusData> statusClient;
public List<DatatableCheckStatusData> statusGroup;
public List<DatatableCheckStatusData> statusSavings;
public List<DatatableCheckStatusData> statusLoans;
public List<DatatableChecksData> datatables;
public Collection<LoanProductData> loanProductDatas;
public Collection<SavingsProductData> savingsProductDatas;
}
@ApiModel(value = "PostEntityDatatableChecksTemplateRequest")
public static final class PostEntityDatatableChecksTemplateRequest{
private PostEntityDatatableChecksTemplateRequest() {
}
@ApiModelProperty(example = "m_loan")
public String entity;
@ApiModelProperty(example = "100")
public Long status;
@ApiModelProperty(example = "Additional Details")
public String datatableName;
@ApiModelProperty(example = "1")
public Long productId;
}
@ApiModel(value = "PostEntityDatatableChecksTemplateResponse")
public static final class PostEntityDatatableChecksTemplateResponse{
private PostEntityDatatableChecksTemplateResponse() {
}
@ApiModelProperty(example = "1")
public Long resourceId;
}
@ApiModel(value = "DeleteEntityDatatableChecksTemplateResponse")
public static final class DeleteEntityDatatableChecksTemplateResponse{
private DeleteEntityDatatableChecksTemplateResponse() {
}
@ApiModelProperty(example = "1")
public Long resourceId;
}
}
@@ -35,6 +35,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
@@ -52,6 +53,7 @@ import org.springframework.stereotype.Component;
@Path("/reports")
@Component
@Scope("singleton")
@Api(value = "Reports", description = "Non-core reports can be added, updated and deleted.")
public class ReportsApiResource {
private final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList("id", "reportName", "reportType", "reportSubType",
@@ -79,6 +81,8 @@ public class ReportsApiResource {
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@ApiOperation(value = "List Reports", notes = "Lists all reports and their parameters.\n" + "\n" + "Example Request:\n" + "\n" + "reports", responseContainer = "List", response = ReportsApiResourceSwagger.GetReportsResponse.class)
@ApiResponses({@ApiResponse(code = 200, message = "")})
public String retrieveReportList(@Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
@@ -93,7 +97,9 @@ public class ReportsApiResource {
@Path("{id}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveReport(@PathParam("id") final Long id, @Context final UriInfo uriInfo) {
@ApiOperation(value = "Retrieve a Report\n", notes = "Example Requests:\n" + "\n" + "reports/1\n" + "\n" + "\n" + "reports/1?template=true")
@ApiResponses({@ApiResponse(code = 200, message = "", response = ReportsApiResourceSwagger.GetReportsResponse.class)})
public String retrieveReport(@PathParam("id") @ApiParam(value = "id") final Long id, @Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
@@ -111,6 +117,8 @@ public class ReportsApiResource {
@Path("template")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@ApiOperation(value = "Retrieve Report Template", notes = "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 Value Lists\n" + "\n" + "Example Request : \n" + "\n" + "reports/template")
@ApiResponses({@ApiResponse(code = 200, message = "", response = ReportsApiResourceSwagger.GetReportsTemplateResponse.class)})
public String retrieveOfficeTemplate(@Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
@@ -125,7 +133,10 @@ public class ReportsApiResource {
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String createReport(final String apiRequestBodyAsJson) {
@ApiOperation(value = "Create a Report", notes = "")
@ApiImplicitParams({@ApiImplicitParam(value = "body", required = true, paramType = "body", dataType = "body", format = "body", dataTypeClass = ReportsApiResourceSwagger.PostRepostRequest.class )})
@ApiResponses({@ApiResponse(code = 200, message = "", response = ReportsApiResourceSwagger.PostReportsResponse.class)})
public String createReport(@ApiParam(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().createReport().withJson(apiRequestBodyAsJson).build();
@@ -138,7 +149,10 @@ public class ReportsApiResource {
@Path("{id}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String updateReport(@PathParam("id") final Long id, final String apiRequestBodyAsJson) {
@ApiOperation(value = "Update a Report", notes = "Only the useReport value can be updated for core reports.")
@ApiImplicitParams({@ApiImplicitParam(value = "body", required = true, paramType = "body", dataType = "body", format = "body", dataTypeClass = ReportsApiResourceSwagger.PutReportRequest.class )})
@ApiResponses({@ApiResponse(code = 200, message = "", response = ReportsApiResourceSwagger.PutReportResponse.class)})
public String updateReport(@PathParam("id") @ApiParam(value = "id") final Long id, @ApiParam(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateReport(id).withJson(apiRequestBodyAsJson).build();
@@ -151,7 +165,9 @@ public class ReportsApiResource {
@Path("{id}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String deleteReport(@PathParam("id") final Long id) {
@ApiOperation(value = "Delete a Report", notes = "Only non-core reports can be deleted.")
@ApiResponses({@ApiResponse(code = 200, message = "", response = ReportsApiResourceSwagger.DeleteReportsResponse.class)})
public String deleteReport(@PathParam("id") @ApiParam(value = "id") final Long id) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteReport(id).build();
@@ -0,0 +1,139 @@
/**
* 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.infrastructure.dataqueries.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.fineract.infrastructure.dataqueries.data.ReportParameterData;
import java.util.Collection;
import java.util.List;
/**
* Created by sanyam on 4/8/17.
*/
final class ReportsApiResourceSwagger {
private ReportsApiResourceSwagger() {
}
@ApiModel(value = "GetReportsResponse")
public static final class GetReportsResponse {
private GetReportsResponse() {
}
@ApiModelProperty(example = "1")
public Long id;
@ApiModelProperty(example = "Client Listing")
public String reportName;
@ApiModelProperty(example = "Table")
public String reportType;
public String reportSubType;
@ApiModelProperty(example = "Client")
public String reportCategory;
@ApiModelProperty(example = "Individual Client Report Lists the small number of defined fields on the client table. Would expect to copy this report and add any one to one additional data for specific tenant needs. Can be run for any size MFI but you expect it only to be run within a branch for larger ones. Depending on how many columns are displayed, there is probably is a limit of about 20/50k clients returned for html display (export to excel doesnt have that client browser/memory impact).")
public String description;
@ApiModelProperty(example = "")
public String reportSql;
@ApiModelProperty(example = "true")
public Boolean coreReport;
@ApiModelProperty(example = "true")
public Boolean useReport;
public Collection<ReportParameterData> reportParameters;
}
@ApiModel(value = "GetReportsTemplateResponse")
public static final class GetReportsTemplateResponse {
private GetReportsTemplateResponse(){
}
public List<String> allowedReportTypes;
public List<String> allowedReportSubTypes;
public Collection<ReportParameterData> allowedParameters;
}
@ApiModel(value = "PostRepostRequest")
public static final class PostRepostRequest {
private PostRepostRequest() {
}
@ApiModelProperty(example = "Completely New Report")
public String reportName;
@ApiModelProperty(example = "Table")
public String reportType;
@ApiModelProperty(example = "")
public String reportSubType;
@ApiModelProperty(example = "Loan")
public String reportCategory;
@ApiModelProperty(example = "Just An Example")
public String description;
@ApiModelProperty(example = "select 'very good sql' as AComment")
public String reportSql;
public Collection<ReportParameterData> reportParameters;
}
@ApiModel(value = "PostReportsResponse")
public static final class PostReportsResponse {
private PostReportsResponse(){
}
@ApiModelProperty(example = "132")
public long resourceId;
}
@ApiModel(value = "PutReportRequest")
public static final class PutReportRequest {
private PutReportRequest() {
}
@ApiModelProperty(example = "Completely New Report")
public String reportName;
public Collection<ReportParameterData> reportParameters;
}
@ApiModel(value = "PutReportResponse")
public static final class PutReportResponse {
private PutReportResponse() {
}
final class PutReportResponseChanges{
private PutReportResponseChanges() {
}
@ApiModelProperty(example = "Changed New Report")
public String reportName;
public Collection<ReportParameterData> reportParameters;
}
@ApiModelProperty(example = "132")
public long resourceId;
public PutReportResponseChanges changes;
}
@ApiModel(value = "DeleteReportsResponse")
public static final class DeleteReportsResponse {
private DeleteReportsResponse(){
}
@ApiModelProperty(example = "132")
public long resourceId;
}
}
@@ -24,10 +24,12 @@ import java.util.Map;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
@@ -36,6 +38,7 @@ import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.StreamingOutput;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
import org.apache.fineract.infrastructure.core.api.ApiParameterHelper;
import org.apache.fineract.infrastructure.core.serialization.ToApiJsonSerializer;
import org.apache.fineract.infrastructure.dataqueries.data.GenericResultsetData;
@@ -46,6 +49,7 @@ import org.apache.fineract.infrastructure.report.provider.ReportingProcessServic
import org.apache.fineract.infrastructure.report.service.ReportingProcessService;
import org.apache.fineract.infrastructure.security.exception.NoAuthorizationException;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.utils.SQLInjectionValidator;
import org.apache.fineract.useradministration.domain.AppUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
@@ -54,6 +58,7 @@ import org.springframework.stereotype.Component;
@Path("/runreports")
@Component
@Scope("singleton")
@Api(value = "Run Reports", description = "")
public class RunreportsApiResource {
private final PlatformSecurityContext context;
@@ -77,9 +82,14 @@ public class RunreportsApiResource {
@Path("{reportName}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON, "text/csv", "application/vnd.ms-excel", "application/pdf", "text/html" })
public Response runReport(@PathParam("reportName") final String reportName, @Context final UriInfo uriInfo) {
@ApiOperation(value = "Running a Report", notes = "This resource allows you to run and receive output from pre-defined Apache Fineract reports.\n" + "\n" + "Reports can also be used to provide data for searching and workflow functionality.\n" + "\n" + "The default output is a JSON formatted \"Generic Resultset\". The Generic Resultset contains Column Heading as well as Data information. However, you can export to CSV format by simply adding \"&exportCSV=true\" to the end of your URL.\n" + "\n" + "If Pentaho reports have been pre-defined, they can also be run through this resource. Pentaho reports can return HTML, PDF or CSV formats.\n" + "\n" + "The Apache Fineract reference application uses a JQuery plugin called stretchy reporting which, itself, uses this reports resource to provide a pretty flexible reporting User Interface (UI).\n\n" + "\n" +
"\n" + "Example Requests:\n" + "\n" + "runreports/Client%20Listing?R_officeId=1\n" + "\n" + "\n" + "runreports/Client%20Listing?R_officeId=1&exportCSV=true\n" + "\n" + "\n" + "runreports/OfficeIdSelectOne?R_officeId=1&parameterType=true\n" + "\n" + "\n" + "runreports/OfficeIdSelectOne?R_officeId=1&parameterType=true&exportCSV=true\n" + "\n" + "\n" + "runreports/Expected%20Payments%20By%20Date%20-%20Formatted?R_endDate=2013-04-30&R_loanOfficerId=-1&R_officeId=1&R_startDate=2013-04-16&output-type=HTML&R_officeId=1\n" + "\n" + "\n" + "runreports/Expected%20Payments%20By%20Date%20-%20Formatted?R_endDate=2013-04-30&R_loanOfficerId=-1&R_officeId=1&R_startDate=2013-04-16&output-type=XLS&R_officeId=1\n" + "\n" + "\n" + "runreports/Expected%20Payments%20By%20Date%20-%20Formatted?R_endDate=2013-04-30&R_loanOfficerId=-1&R_officeId=1&R_startDate=2013-04-16&output-type=CSV&R_officeId=1\n" + "\n" + "\n" + "runreports/Expected%20Payments%20By%20Date%20-%20Formatted?R_endDate=2013-04-30&R_loanOfficerId=-1&R_officeId=1&R_startDate=2013-04-16&output-type=PDF&R_officeId=1")
@ApiResponses({@ApiResponse(code = 200, message = "", response = RunreportsApiResourceSwagger.GetReportNameResponse.class)})
public Response runReport(@PathParam("reportName") @ApiParam(value = "reportName") final String reportName,
@Context final UriInfo uriInfo,
@DefaultValue("false") @QueryParam("isSelfServiceUserReport") @ApiParam(value = "isSelfServiceUserReport") final boolean isSelfServiceUserReport) {
final MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
final MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
final boolean exportCsv = ApiParameterHelper.exportCsv(uriInfo.getQueryParameters());
@@ -91,7 +101,7 @@ public class RunreportsApiResource {
String parameterTypeValue = null;
if (!parameterType) {
parameterTypeValue = "report";
String reportType = this.readExtraDataAndReportingService.getReportType(reportName);
String reportType = this.readExtraDataAndReportingService.getReportType(reportName, isSelfServiceUserReport);
ReportingProcessService reportingProcessService = this.reportingProcessServiceProvider.findReportingProcessService(reportType);
if (reportingProcessService != null) { return reportingProcessService.processRequest(reportName, queryParams); }
} else {
@@ -103,7 +113,7 @@ public class RunreportsApiResource {
if (exportPdf) {
final Map<String, String> reportParams = getReportParams(queryParams);
final String pdfFileName = this.readExtraDataAndReportingService
.retrieveReportPDF(reportName, parameterTypeValue, reportParams);
.retrieveReportPDF(reportName, parameterTypeValue, reportParams, isSelfServiceUserReport);
final File file = new File(pdfFileName);
@@ -119,7 +129,7 @@ public class RunreportsApiResource {
final Map<String, String> reportParams = getReportParams(queryParams);
final GenericResultsetData result = this.readExtraDataAndReportingService.retrieveGenericResultset(reportName,
parameterTypeValue, reportParams);
parameterTypeValue, reportParams, isSelfServiceUserReport);
String json = "";
final boolean genericResultSetIsPassed = ApiParameterHelper.genericResultSetPassed(uriInfo.getQueryParameters());
@@ -140,7 +150,7 @@ public class RunreportsApiResource {
// CSV Export
final Map<String, String> reportParams = getReportParams(queryParams);
final StreamingOutput result = this.readExtraDataAndReportingService
.retrieveReportCSV(reportName, parameterTypeValue, reportParams);
.retrieveReportCSV(reportName, parameterTypeValue, reportParams, isSelfServiceUserReport);
return Response.ok().entity(result).type("text/csv")
.header("Content-Disposition", "attachment;filename=" + reportName.replaceAll(" ", "") + ".csv").build();
@@ -168,6 +178,7 @@ public class RunreportsApiResource {
if (k.startsWith("R_")) {
pKey = "${" + k.substring(2) + "}";
pValue = queryParams.get(k).get(0);
SQLInjectionValidator.validateSQLInput(pValue);
reportParams.put(pKey, pValue);
}
}
@@ -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.infrastructure.dataqueries.api;
import io.swagger.annotations.ApiModel;
import org.apache.fineract.infrastructure.dataqueries.data.ResultsetColumnHeaderData;
import org.apache.fineract.infrastructure.dataqueries.data.ResultsetRowData;
/**
* Created by sanyam on 5/8/17.
*/
final class RunreportsApiResourceSwagger {
private RunreportsApiResourceSwagger() {
}
@ApiModel(value = "GetReportNameResponse")
public static final class GetReportNameResponse {
private GetReportNameResponse() {
}
public ResultsetColumnHeaderData columnHeaders;
public ResultsetRowData row;
}
}
@@ -75,6 +75,9 @@ public final class Report extends AbstractPersistableCustom<Long> {
@OneToMany(cascade = CascadeType.ALL, mappedBy = "report", orphanRemoval = true, fetch=FetchType.EAGER)
private Set<ReportParameterUsage> reportParameterUsages = new HashSet<>();
@Column(name = "self_service_user_report")
private boolean isSelfServiceUserReport;
public static Report fromJson(final JsonCommand command, final Collection<String> reportTypes) {
@@ -278,6 +281,7 @@ public final class Report extends AbstractPersistableCustom<Long> {
}
public Set<ReportParameterUsage> getReportParameterUsages() {
return this.reportParameterUsages;
}
return this.reportParameterUsages;
}
}
@@ -23,10 +23,11 @@ import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourc
/**
* A {@link RuntimeException} thrown when report resources are not found.
*/
@SuppressWarnings("serial")
public class ReportNotFoundException extends AbstractPlatformResourceNotFoundException {
public ReportNotFoundException(final String reportSql) {
super("error.msg.report.name.not.found", "Reporting meta-data entry not found.", "Input sql: " + reportSql);
public ReportNotFoundException(final String reportName) {
super("error.msg.report.name.not.found", "Reporting meta-data entry not found.", "Report Name: " + reportName);
}
public ReportNotFoundException(final Long id) {
@@ -23,6 +23,7 @@ import java.util.List;
import javax.sql.DataSource;
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
import org.apache.fineract.infrastructure.dataqueries.data.GenericResultsetData;
import org.apache.fineract.infrastructure.dataqueries.data.ResultsetColumnHeaderData;
@@ -34,6 +35,7 @@ import org.joda.time.LocalDateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.jdbc.support.rowset.SqlRowSetMetaData;
@@ -55,37 +57,40 @@ public class GenericDataServiceImpl implements GenericDataService {
@Override
public GenericResultsetData fillGenericResultSet(final String sql) {
try{
final SqlRowSet rs = this.jdbcTemplate.queryForRowSet(sql);
final SqlRowSet rs = this.jdbcTemplate.queryForRowSet(sql);
final List<ResultsetColumnHeaderData> columnHeaders = new ArrayList<>();
final List<ResultsetRowData> resultsetDataRows = new ArrayList<>();
final List<ResultsetColumnHeaderData> columnHeaders = new ArrayList<>();
final List<ResultsetRowData> resultsetDataRows = new ArrayList<>();
final SqlRowSetMetaData rsmd = rs.getMetaData();
final SqlRowSetMetaData rsmd = rs.getMetaData();
for (int i = 0; i < rsmd.getColumnCount(); i++) {
for (int i = 0; i < rsmd.getColumnCount(); i++) {
final String columnName = rsmd.getColumnName(i + 1);
final String columnType = rsmd.getColumnTypeName(i + 1);
final String columnName = rsmd.getColumnName(i + 1);
final String columnType = rsmd.getColumnTypeName(i + 1);
final ResultsetColumnHeaderData columnHeader = ResultsetColumnHeaderData.basic(columnName, columnType);
columnHeaders.add(columnHeader);
}
final ResultsetColumnHeaderData columnHeader = ResultsetColumnHeaderData.basic(columnName, columnType);
columnHeaders.add(columnHeader);
}
while (rs.next()) {
final List<String> columnValues = new ArrayList<>();
for (int i = 0; i < rsmd.getColumnCount(); i++) {
final String columnName = rsmd.getColumnName(i + 1);
final String columnValue = rs.getString(columnName);
columnValues.add(columnValue);
}
while (rs.next()) {
final List<String> columnValues = new ArrayList<>();
for (int i = 0; i < rsmd.getColumnCount(); i++) {
final String columnName = rsmd.getColumnName(i + 1);
final String columnValue = rs.getString(columnName);
columnValues.add(columnValue);
}
final ResultsetRowData resultsetDataRow = ResultsetRowData.create(columnValues);
resultsetDataRows.add(resultsetDataRow);
}
final ResultsetRowData resultsetDataRow = ResultsetRowData.create(columnValues);
resultsetDataRows.add(resultsetDataRow);
}
return new GenericResultsetData(columnHeaders, resultsetDataRows);
}
return new GenericResultsetData(columnHeaders, resultsetDataRows);
} catch (DataAccessException e) {
throw new PlatformDataIntegrityException("error.msg.report.unknown.data.integrity.issue", e.getClass().getName());
}
}
@Override
public String replace(final String str, final String pattern, final String replace) {
@@ -32,13 +32,13 @@ import org.apache.fineract.useradministration.domain.AppUser;
public interface ReadReportingService {
StreamingOutput retrieveReportCSV(String name, String type, Map<String, String> extractedQueryParams);
StreamingOutput retrieveReportCSV(String name, String type, Map<String, String> extractedQueryParams, boolean isSelfServiceUserReport);
GenericResultsetData retrieveGenericResultset(String name, String type, Map<String, String> extractedQueryParams);
GenericResultsetData retrieveGenericResultset(String name, String type, Map<String, String> extractedQueryParams, boolean isSelfServiceUserReport);
String retrieveReportPDF(String name, String type, Map<String, String> extractedQueryParams);
String retrieveReportPDF(String name, String type, Map<String, String> extractedQueryParams, boolean isSelfServiceUserReport);
String getReportType(String reportName);
String getReportType(String reportName, boolean isSelfServiceUserReport);
Collection<ReportData> retrieveReportList();
@@ -36,6 +36,7 @@ import java.util.Set;
import javax.sql.DataSource;
import javax.ws.rs.core.StreamingOutput;
import org.apache.commons.lang.StringUtils;
import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
@@ -50,6 +51,7 @@ import org.apache.fineract.infrastructure.documentmanagement.contentrepository.F
import org.apache.fineract.infrastructure.report.provider.ReportingProcessServiceProvider;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.utils.ColumnValidator;
import org.apache.fineract.infrastructure.security.utils.SQLInjectionException;
import org.apache.fineract.useradministration.domain.AppUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -68,6 +70,7 @@ import com.lowagie.text.pdf.PdfWriter;
public class ReadReportingServiceImpl implements ReadReportingService {
private final static Logger logger = LoggerFactory.getLogger(ReadReportingServiceImpl.class);
private final static String REPORT_NAME_REGEX_PATTERN = "^[a-zA-Z][a-zA-Z0-9\\-_\\s]{0,48}[a-zA-Z0-9]$";
private final JdbcTemplate jdbcTemplate;
private final DataSource dataSource;
@@ -90,15 +93,16 @@ public class ReadReportingServiceImpl implements ReadReportingService {
}
@Override
public StreamingOutput retrieveReportCSV(final String name, final String type, final Map<String, String> queryParams) {
public StreamingOutput retrieveReportCSV(final String name, final String type,
final Map<String, String> queryParams, final boolean isSelfServiceUserReport) {
return new StreamingOutput() {
return new StreamingOutput() {
@Override
public void write(final OutputStream out) {
try {
final GenericResultsetData result = retrieveGenericResultset(name, type, queryParams);
final GenericResultsetData result = retrieveGenericResultset(name, type, queryParams, isSelfServiceUserReport);
final StringBuffer sb = generateCsvFileBuffer(result);
final InputStream in = new ByteArrayInputStream(sb.toString().getBytes("UTF-8"));
@@ -171,12 +175,13 @@ public class ReadReportingServiceImpl implements ReadReportingService {
}
@Override
public GenericResultsetData retrieveGenericResultset(final String name, final String type, final Map<String, String> queryParams) {
public GenericResultsetData retrieveGenericResultset(final String name, final String type,
final Map<String, String> queryParams, final boolean isSelfServiceUserReport) {
final long startTime = System.currentTimeMillis();
logger.info("STARTING REPORT: " + name + " Type: " + type);
final String sql = getSQLtoRun(name, type, queryParams);
final String sql = getSQLtoRun(name, type, queryParams, isSelfServiceUserReport);
final GenericResultsetData result = this.genericDataService.fillGenericResultSet(sql);
@@ -185,7 +190,8 @@ public class ReadReportingServiceImpl implements ReadReportingService {
return result;
}
private String getSQLtoRun(final String name, final String type, final Map<String, String> queryParams) {
private String getSQLtoRun(final String name, final String type, final Map<String, String> queryParams,
final boolean isSelfServiceUserReport) {
String sql = getSql(name, type);
@@ -203,40 +209,48 @@ public class ReadReportingServiceImpl implements ReadReportingService {
// (typically used to return report lists containing only reports
// permitted to be run by the user
sql = this.genericDataService.replace(sql, "${currentUserId}", currentUser.getId().toString());
sql = this.genericDataService.replace(sql, "${isSelfServiceUser}",
Integer.toString(isSelfServiceUserReport ? 1 : 0));
sql = this.genericDataService.wrapSQL(sql);
sql = this.genericDataService.wrapSQL(sql);
return sql;
return sql;
}
}
private String getSql(final String name, final String type) {
final String inputSql = "select " + type + "_sql as the_sql from stretchy_" + type + " where " + type + "_name = '" + name + "'";
validateReportName(name);
final String inputSqlWrapped = this.genericDataService.wrapSQL(inputSql);
// the return statement contains the exact sql required
final SqlRowSet rs = this.jdbcTemplate.queryForRowSet(inputSqlWrapped);
if (rs.next() && rs.getString("the_sql") != null) { return rs.getString("the_sql"); }
throw new ReportNotFoundException(inputSql);
throw new ReportNotFoundException(name);
}
@Override
public String getReportType(final String reportName) {
public String getReportType(final String reportName, final boolean isSelfServiceUserReport) {
final String sql = "SELECT ifnull(report_type,'') as report_type FROM `stretchy_report` where report_name = '" + reportName + "'";
final String sql = "SELECT ifnull(report_type,'') as report_type FROM `stretchy_report` where report_name = '" + reportName + "' and self_service_user_report = ?";
validateReportName(reportName);
this.columnValidator.validateSqlInjection(sql, reportName);
final String sqlWrapped = this.genericDataService.wrapSQL(sql);
final SqlRowSet rs = this.jdbcTemplate.queryForRowSet(sqlWrapped);
final SqlRowSet rs = this.jdbcTemplate.queryForRowSet(sqlWrapped, new Object [] {isSelfServiceUserReport});
if (rs.next()) { return rs.getString("report_type"); }
throw new ReportNotFoundException(sql);
throw new ReportNotFoundException(reportName);
}
@Override
public String retrieveReportPDF(final String reportName, final String type, final Map<String, String> queryParams) {
public String retrieveReportPDF(final String reportName, final String type, final Map<String, String> queryParams,
final boolean isSelfServiceUserReport) {
final String fileLocation = FileSystemContentRepository.FINERACT_BASE_DIR + File.separator + "";
if (!new File(fileLocation).isDirectory()) {
@@ -246,7 +260,7 @@ public class ReadReportingServiceImpl implements ReadReportingService {
final String genaratePdf = fileLocation + File.separator + reportName + ".pdf";
try {
final GenericResultsetData result = retrieveGenericResultset(reportName, type, queryParams);
final GenericResultsetData result = retrieveGenericResultset(reportName, type, queryParams, isSelfServiceUserReport);
final List<ResultsetColumnHeaderData> columnHeaders = result.getColumnHeaders();
final List<ResultsetRowData> data = result.getData();
@@ -445,7 +459,7 @@ public class ReadReportingServiceImpl implements ReadReportingService {
}
@Override
public ReportParameterJoinData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
public ReportParameterJoinData mapRow(final ResultSet rs, final int rowNum) throws SQLException {
final Long reportId = rs.getLong("reportId");
final String reportName = rs.getString("reportName");
@@ -483,7 +497,7 @@ public class ReadReportingServiceImpl implements ReadReportingService {
}
@Override
public ReportParameterData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
public ReportParameterData mapRow(final ResultSet rs, final int rowNum) throws SQLException {
final Long id = rs.getLong("id");
final String parameterName = rs.getString("parameterName");
@@ -602,6 +616,11 @@ public class ReadReportingServiceImpl implements ReadReportingService {
*/
return null ;
}
private void validateReportName(final String name) {
if (!StringUtils.isBlank(name) && !name.matches(REPORT_NAME_REGEX_PATTERN)) {
throw new SQLInjectionException();
}
}
}
@@ -20,7 +20,13 @@ package org.apache.fineract.infrastructure.dataqueries.service;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.persistence.PersistenceException;
import javax.sql.DataSource;
@@ -44,7 +50,11 @@ import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import org.apache.fineract.infrastructure.core.serialization.JsonParserHelper;
import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
import org.apache.fineract.infrastructure.dataqueries.api.DataTableApiConstant;
import org.apache.fineract.infrastructure.dataqueries.data.*;
import org.apache.fineract.infrastructure.dataqueries.data.DataTableValidator;
import org.apache.fineract.infrastructure.dataqueries.data.DatatableData;
import org.apache.fineract.infrastructure.dataqueries.data.GenericResultsetData;
import org.apache.fineract.infrastructure.dataqueries.data.ResultsetColumnHeaderData;
import org.apache.fineract.infrastructure.dataqueries.data.ResultsetRowData;
import org.apache.fineract.infrastructure.dataqueries.exception.DatatableEntryRequiredException;
import org.apache.fineract.infrastructure.dataqueries.exception.DatatableNotFoundException;
import org.apache.fineract.infrastructure.dataqueries.exception.DatatableSystemErrorException;
@@ -62,6 +72,7 @@ import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.jdbc.support.rowset.SqlRowSetMetaData;
import org.springframework.stereotype.Service;
@@ -108,6 +119,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
private final CodeReadPlatformService codeReadPlatformService;
private final DataTableValidator dataTableValidator;
private final ColumnValidator columnValidator;
private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;
// private final GlobalConfigurationWritePlatformServiceJpaRepositoryImpl
// configurationWriteService;
@@ -130,6 +142,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
this.dataTableValidator = dataTableValidator;
this.columnValidator = columnValidator;
// this.configurationWriteService = configurationWriteService;
this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
}
@Override
@@ -139,6 +152,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
if (appTable == null) {
andClause = "";
} else {
validateAppTable(appTable);
SQLInjectionValidator.validateSQLInput(appTable);
andClause = " and application_table_name = '" + appTable + "'";
}
@@ -225,7 +239,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
@Transactional
@Override
public void registerDatatable(final JsonCommand command, final String permissionSql) {
public void registerDatatable(final JsonCommand command, final String permissionSql) {
final String applicationTableName = this.getTableName(command.getUrl());
final String dataTableName = this.getDataTableName(command.getUrl());
@@ -237,24 +251,27 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
}
@Transactional
@Transactional
private void _registerDataTable(final String applicationTableName, final String dataTableName, final Integer category,
final String permissionsSql) {
validateAppTable(applicationTableName);
validateDatatableName(dataTableName);
assertDataTableExists(dataTableName);
final String registerDatatableSql = "insert into x_registered_table (registered_table_name, application_table_name,category) values ('"
+ dataTableName + "', '" + applicationTableName + "', '" + category + "')";
Map<String, Object> paramMap = new HashMap<>(3);
final String registerDatatableSql = "insert into x_registered_table (registered_table_name, application_table_name,category) values ( :dataTableName, :applicationTableName, :category)";
paramMap.put("dataTableName", dataTableName);
paramMap.put("applicationTableName", applicationTableName);
paramMap.put("category", category);
try {
final String[] sqlArray = { registerDatatableSql, permissionsSql };
this.jdbcTemplate.batchUpdate(sqlArray);
this.namedParameterJdbcTemplate.update(registerDatatableSql, paramMap);
this.jdbcTemplate.update(permissionsSql);
// add the registered table to the config if it is a ppi
if (this.isSurveyCategory(category)) {
this.jdbcTemplate.execute("insert into c_configuration (name, value, enabled ) values('" + dataTableName + "', '0','0')");
this.namedParameterJdbcTemplate.update("insert into c_configuration (name, value, enabled ) values( :dataTableName , '0','0')", paramMap);
}
}
@@ -333,6 +350,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
@Transactional
@Override
public void deregisterDatatable(final String datatable) {
validateDatatableName(datatable);
final String permissionList = "('CREATE_" + datatable + "', 'CREATE_" + datatable + "_CHECKER', 'READ_" + datatable + "', 'UPDATE_"
+ datatable + "', 'UPDATE_" + datatable + "_CHECKER', 'DELETE_" + datatable + "', 'DELETE_" + datatable + "_CHECKER')";
@@ -476,6 +494,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
throw new PlatformDataIntegrityException("error.msg.datatables.datatable.null.name", "Data table name must not be blank.");
} else if (!name.matches(DATATABLE_NAME_REGEX_PATTERN)) { throw new PlatformDataIntegrityException(
"error.msg.datatables.datatable.invalid.name.regex", "Invalid data table name.", name); }
SQLInjectionValidator.validateSQLInput(name);
}
private String datatableColumnNameToCodeValueName(final String columnName, final String code) {
@@ -1141,6 +1160,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
@Override
public CommandProcessingResult deleteDatatableEntries(final String dataTableName, final Long appTableId) {
validateDatatableName(dataTableName);
if (isDatatableAttachedToEntityDatatableCheck(dataTableName)) { throw new DatatableEntryRequiredException(dataTableName, appTableId); }
final String appTable = queryForApplicationTableName(dataTableName);
final CommandProcessingResult commandProcessingResult = checkMainResourceExistsWithinScope(appTable, appTableId);
@@ -1155,6 +1175,7 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
@Transactional
@Override
public CommandProcessingResult deleteDatatableEntry(final String dataTableName, final Long appTableId, final Long datatableId) {
validateDatatableName(dataTableName);
if (isDatatableAttachedToEntityDatatableCheck(dataTableName)) { throw new DatatableEntryRequiredException(dataTableName, appTableId); }
final String appTable = queryForApplicationTableName(dataTableName);
final CommandProcessingResult commandProcessingResult = checkMainResourceExistsWithinScope(appTable, appTableId);
@@ -39,6 +39,7 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
@@ -60,6 +61,7 @@ import com.sun.jersey.multipart.FormDataParam;
@Path("{entityType}/{entityId}/documents")
@Component
@Scope("singleton")
@Api(value = "Documents", description = "Multiple Documents (a combination of a name, description and a file) may be attached to different Entities like Clients, Groups, Staff, Loans, Savings and Client Identifiers in the system\n" + "\n" + "Note: The currently allowed Entities are\n" + "\n" + "Clients: URL Pattern as clients\n" + "Staff: URL Pattern as staff\n" + "Loans: URL Pattern as loans\n" + "Savings: URL Pattern as savings\n" + "Client Identifiers: URL Pattern as client_identifiers\n" + "Groups: URL Pattern as groups")
public class DocumentManagementApiResource {
private final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList("id", "parentEntityType", "parentEntityId",
@@ -87,8 +89,10 @@ public class DocumentManagementApiResource {
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retreiveAllDocuments(@Context final UriInfo uriInfo, @PathParam("entityType") final String entityType,
@PathParam("entityId") final Long entityId) {
@ApiOperation(value = "List documents", notes = "Example Requests:\n" + "\n" + "clients/1/documents\n" + "\n" + "client_identifiers/1/documents\n" + "\n" + "loans/1/documents?fields=name,description")
@ApiResponses({@ApiResponse(code = 200, message = "", response = DocumentManagementApiResourceSwagger.GetEntityTypeEntityIdDocumentsResponse.class, responseContainer = "list")})
public String retreiveAllDocuments(@Context final UriInfo uriInfo, @PathParam("entityType") @ApiParam(value = "entityType") final String entityType,
@PathParam("entityId") @ApiParam(value = "entityId") final Long entityId) {
this.context.authenticatedUser().validateHasReadPermission(this.SystemEntityType);
@@ -101,10 +105,12 @@ public class DocumentManagementApiResource {
@POST
@Consumes({ MediaType.MULTIPART_FORM_DATA })
@Produces({ MediaType.APPLICATION_JSON })
public String createDocument(@PathParam("entityType") final String entityType, @PathParam("entityId") final Long entityId,
@HeaderParam("Content-Length") final Long fileSize, @FormDataParam("file") final InputStream inputStream,
@FormDataParam("file") final FormDataContentDisposition fileDetails, @FormDataParam("file") final FormDataBodyPart bodyPart,
@FormDataParam("name") final String name, @FormDataParam("description") final String description) {
@ApiOperation(value = "Create a Document", notes = "Note: A document is created using a Multi-part form upload \n" + "\n" + "Body Parts\n" + "\n" + "name : \n" + "Name or summary of the document\n" + "\n" + "description : \n" + "Description of the document\n" + "\n" + "file : \n" + "The file to be uploaded\n" + "\n" + "Mandatory Fields : \n" + "file and description")
@ApiResponses({@ApiResponse(code = 200, message = "Not Shown (multi-part form data)", response = DocumentManagementApiResourceSwagger.PostEntityTypeEntityIdDocumentsResponse.class)})
public String createDocument(@PathParam("entityType") @ApiParam(value = "entityType") final String entityType, @PathParam("entityId") @ApiParam(value = "entityId") final Long entityId,
@HeaderParam("Content-Length") @ApiParam(value = "Content-Length") final Long fileSize, @FormDataParam("file") @ApiParam(value = "file") final InputStream inputStream,
@FormDataParam("file") final @ApiParam(value = "file") FormDataContentDisposition fileDetails, @FormDataParam("file") @ApiParam(value = "file") final FormDataBodyPart bodyPart,
@FormDataParam("name") @ApiParam(value = "name") final String name, @FormDataParam("description") @ApiParam(value = "description") final String description) {
/**
* TODO: also need to have a backup and stop reading from stream after
@@ -127,11 +133,13 @@ public class DocumentManagementApiResource {
@Path("{documentId}")
@Consumes({ MediaType.MULTIPART_FORM_DATA })
@Produces({ MediaType.APPLICATION_JSON })
public String updateDocument(@PathParam("entityType") final String entityType, @PathParam("entityId") final Long entityId,
@PathParam("documentId") final Long documentId, @HeaderParam("Content-Length") final Long fileSize,
@FormDataParam("file") final InputStream inputStream, @FormDataParam("file") final FormDataContentDisposition fileDetails,
@FormDataParam("file") final FormDataBodyPart bodyPart, @FormDataParam("name") final String name,
@FormDataParam("description") final String description) {
@ApiOperation(value = "Update a Document", notes = "Note: A document is updated using a Multi-part form upload \n" + "Body Parts\n" + "name\n" + "Name or summary of the document\n" + "description\n" + "Description of the document\n" + "file\n" + "The file to be uploaded")
@ApiResponses({@ApiResponse(code = 200, message = "Not Shown (multi-part form data)", response = DocumentManagementApiResourceSwagger.PutEntityTypeEntityIdDocumentsResponse.class)})
public String updateDocument(@PathParam("entityType") @ApiParam(value = "entityType") final String entityType, @PathParam("entityId") @ApiParam(value = "entityId") final Long entityId,
@PathParam("documentId") @ApiParam(value = "documentId") final Long documentId, @HeaderParam("Content-Length") @ApiParam(value = "Content-Length") final Long fileSize,
@FormDataParam("file") @ApiParam(value = "file") final InputStream inputStream, @FormDataParam("file") @ApiParam(value = "file") final FormDataContentDisposition fileDetails,
@FormDataParam("file") @ApiParam(value = "file") final FormDataBodyPart bodyPart, @FormDataParam("name") @ApiParam(value = "name") final String name,
@FormDataParam("description") @ApiParam(value = "description") final String description) {
final Set<String> modifiedParams = new HashSet<>();
modifiedParams.add("name");
@@ -166,8 +174,10 @@ public class DocumentManagementApiResource {
@Path("{documentId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String getDocument(@PathParam("entityType") final String entityType, @PathParam("entityId") final Long entityId,
@PathParam("documentId") final Long documentId, @Context final UriInfo uriInfo) {
@ApiOperation(value = "Retrieve a Document", notes = "Example Requests:\n" + "\n" + "clients/1/documents/1\n" + "\n" + "\n" + "loans/1/documents/1\n" + "\n" + "\n" + "client_identifiers/1/documents/1?fields=name,description")
@ApiResponses({@ApiResponse(code = 200, message = "", response = DocumentManagementApiResourceSwagger.GetEntityTypeEntityIdDocumentsResponse.class)})
public String getDocument(@PathParam("entityType") @ApiParam(value = "entityType") final String entityType, @PathParam("entityId") @ApiParam(value = "entityId") final Long entityId,
@PathParam("documentId") @ApiParam(value = "documentId") final Long documentId, @Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(this.SystemEntityType);
@@ -181,8 +191,10 @@ public class DocumentManagementApiResource {
@Path("{documentId}/attachment")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_OCTET_STREAM })
public Response downloadFile(@PathParam("entityType") final String entityType, @PathParam("entityId") final Long entityId,
@PathParam("documentId") final Long documentId) {
@ApiOperation(value = "Retrieve Binary File associated with Document", notes = "Request used to download the file associated with the document\n" + "\n" + "Example Requests:\n" + "\n" + "clients/1/documents/1/attachment\n" + "\n" + "\n" + "loans/1/documents/1/attachment")
@ApiResponses({@ApiResponse(code = 200, message = "Not Shown: The corresponding Binary file")})
public Response downloadFile(@PathParam("entityType") @ApiParam(value = "entityType") final String entityType, @PathParam("entityId") @ApiParam(value = "entityId") final Long entityId,
@PathParam("documentId") @ApiParam(value = "documentId") final Long documentId) {
this.context.authenticatedUser().validateHasReadPermission(this.SystemEntityType);
@@ -198,8 +210,10 @@ public class DocumentManagementApiResource {
@Path("{documentId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String deleteDocument(@PathParam("entityType") final String entityType, @PathParam("entityId") final Long entityId,
@PathParam("documentId") final Long documentId) {
@ApiOperation(value = "Remove a Document", notes = "")
@ApiResponses({@ApiResponse(code = 200, message = "", response = DocumentManagementApiResourceSwagger.DeleteEntityTypeEntityIdDocumentsResponse.class)})
public String deleteDocument(@PathParam("entityType") @ApiParam(value = "entityType") final String entityType, @PathParam("entityId") @ApiParam(value = "entityId") final Long entityId,
@PathParam("documentId") @ApiParam(value = "documentId") final Long documentId) {
final DocumentCommand documentCommand = new DocumentCommand(null, documentId, entityType, entityId, null, null, null, null, null,
null);
@@ -0,0 +1,110 @@
/**
* 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.infrastructure.documentmanagement.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
* Created by sanyam on 7/8/17.
*/
final class DocumentManagementApiResourceSwagger {
private DocumentManagementApiResourceSwagger() {
}
@ApiModel(value = "GetEntityTypeEntityIdDocumentsResponse")
public static final class GetEntityTypeEntityIdDocumentsResponse {
private GetEntityTypeEntityIdDocumentsResponse() {
}
@ApiModelProperty(example = "1")
public Long id;
@ApiModelProperty(example = "clients")
public String parentEntityType;
@ApiModelProperty(example = "1")
public Long parentEntityId;
@ApiModelProperty(example = "Client Details Form")
public String name;
@ApiModelProperty(example = "CGAP.pdf")
public String fileName;
@ApiModelProperty(example = "5246719")
public Long size;
@ApiModelProperty(example = "application/pdf")
public String type;
@ApiModelProperty(example = "A signed form signed by new member")
public String description;
@ApiModelProperty(example = "")
public String location;
@ApiModelProperty(example = "")
public Integer storageType;
}
@ApiModel(value = "PostEntityTypeEntityIdDocumentsResponse")
public static final class PostEntityTypeEntityIdDocumentsResponse {
private PostEntityTypeEntityIdDocumentsResponse() {
}
@ApiModelProperty(example = "3")
public Long resourceId;
@ApiModelProperty(example = "3")
public String resourceIdentifier;
}
@ApiModel(value = "PutEntityTypeEntityIdDocumentsResponse")
public static final class PutEntityTypeEntityIdDocumentsResponse {
private PutEntityTypeEntityIdDocumentsResponse() {
}
public final class PutEntityTypeEntityIdDocumentsResponseChangesSwagger{
private PutEntityTypeEntityIdDocumentsResponseChangesSwagger() {
}
}
@ApiModelProperty(example = "3")
public Long resourceId;
public PutEntityTypeEntityIdDocumentsResponseChangesSwagger changes;
@ApiModelProperty(example = "3")
public String resourceIdentifier;
}
@ApiModel(value = "DeleteEntityTypeEntityIdDocumentsResponse")
public static final class DeleteEntityTypeEntityIdDocumentsResponse {
private DeleteEntityTypeEntityIdDocumentsResponse() {
}
public final class PutEntityTypeEntityIdDocumentsResponseChangesSwagger{
private PutEntityTypeEntityIdDocumentsResponseChangesSwagger() {
}
}
@ApiModelProperty(example = "3")
public Long resourceId;
public PutEntityTypeEntityIdDocumentsResponseChangesSwagger changes;
@ApiModelProperty(example = "3")
public String resourceIdentifier;
}
}
@@ -34,6 +34,7 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import io.swagger.annotations.Api;
import org.apache.commons.lang.StringUtils;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.domain.Base64EncodedImage;
@@ -58,6 +59,7 @@ import com.sun.jersey.multipart.FormDataParam;
@Path("{entity}/{entityId}/images")
@Component
@Scope("singleton")
@Api(value = "DomainName//api//v1//{entity}//{entityId}//images", description = "")
public class ImagesApiResource {
private final PlatformSecurityContext context;
@@ -0,0 +1,30 @@
/**
* 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.infrastructure.documentmanagement.api;
/**
* Created by sanyam on 10/8/17.
*/
final class ImagesApiResourceSwagger {
private ImagesApiResourceSwagger() {
}
}
@@ -32,6 +32,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.Api;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
@@ -52,6 +53,7 @@ import org.springframework.stereotype.Component;
@Produces({ MediaType.APPLICATION_JSON })
@Component
@Scope("singleton")
@Api(value = "DomainName/api/v1/entitytoentitymapping", description = "") // https://github.com/swagger-api/swagger-ui/issues/1655
public class FineractEntityApiResource {
private final PlatformSecurityContext context;
@@ -35,6 +35,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
@@ -54,6 +55,7 @@ import org.springframework.stereotype.Component;
@Produces({ MediaType.APPLICATION_JSON })
@Component
@Scope("singleton")
@Api(value = "Hooks", description = "Hooks are a mechanism to trigger custom code on the occurence of events.")
public class HookApiResource {
private final PlatformSecurityContext context;
@@ -77,6 +79,8 @@ public class HookApiResource {
}
@GET
@ApiOperation(value = "Retrieve Hooks", notes = "Returns the list of hooks.\n" + "\n" + "Example Requests:\n" + "\n" + "hooks", responseContainer = "List", response = HookApiResourceSwagger.GetHookResponse.class)
@ApiResponses({@ApiResponse(code = 200, message = "", response = HookApiResourceSwagger.GetHookResponse.class, responseContainer = "list")})
public String retrieveHooks(@Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(
@@ -93,7 +97,9 @@ public class HookApiResource {
@GET
@Path("{hookId}")
public String retrieveHook(@PathParam("hookId") final Long hookId,
@ApiOperation(value = "Retrieve a Hook", notes = "Returns the details of a Hook.\n" + "\n" + "Example Requests:\n" + "\n" + "hooks/1")
@ApiResponses({@ApiResponse(code = 200, message = "", response = HookApiResourceSwagger.GetHookResponse.class)})
public String retrieveHook(@PathParam("hookId") @ApiParam(value = "hookId") final Long hookId,
@Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(
@@ -116,6 +122,8 @@ public class HookApiResource {
@GET
@Path("template")
@ApiOperation(value = "Retrieve Hooks Template", notes = "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 Value Lists\n" + "Example Request:\n" + "\n" + "hooks/template")
@ApiResponses({@ApiResponse(code = 200, message = "", response = HookApiResourceSwagger.GetHookTemplateResponse.class)})
public String template(@Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(
@@ -131,7 +139,10 @@ public class HookApiResource {
}
@POST
public String createHook(final String apiRequestBodyAsJson) {
@ApiOperation(value = "Create a Hook", notes = "The following parameters can be passed for the creation of a hook :-\n" + "\n" + "name - string - Required. The name of the template that is being called. (See /hooks/template for the list of valid hook names.)\n" + "\n" + "isActive - boolean - Determines whether the hook is actually triggered.\n" + "\n" + "events - array - Determines what events the hook is triggered for.\n" + "\n" + "config - hash - Required. Key/value pairs to provide settings for this hook. These settings vary between the templates.\n" + "\n" + "templateId - Optional. The UGD template ID associated with the same entity (client or loan).")
@ApiImplicitParams({@ApiImplicitParam(paramType = "body", dataType = "body", required = true, type = "body", dataTypeClass = HookApiResourceSwagger.PostHookRequest.class)})
@ApiResponses({@ApiResponse(code = 200, message = "", response = HookApiResourceSwagger.PostHookResponse.class)})
public String createHook(@ApiParam(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder()
.createHook().withJson(apiRequestBodyAsJson).build();
@@ -144,8 +155,11 @@ public class HookApiResource {
@PUT
@Path("{hookId}")
public String updateHook(@PathParam("hookId") final Long hookId,
final String apiRequestBodyAsJson) {
@ApiOperation(value = "Update a Hook", notes = "Updates the details of a hook.")
@ApiImplicitParams({@ApiImplicitParam(paramType = "body", dataType = "body", required = true, type = "body", dataTypeClass = HookApiResourceSwagger.PutHookRequest.class)})
@ApiResponses({@ApiResponse(code = 200, message = "", response = HookApiResourceSwagger.PutHookResponse.class)})
public String updateHook(@PathParam("hookId") @ApiParam(value = "hookId") final Long hookId,
@ApiParam(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder()
.updateHook(hookId).withJson(apiRequestBodyAsJson).build();
@@ -158,7 +172,9 @@ public class HookApiResource {
@DELETE
@Path("{hookId}")
public String deleteHook(@PathParam("hookId") final Long hookId) {
@ApiOperation(value = "Delete a Hook", notes = "Deletes a hook.")
@ApiResponses({@ApiResponse(code = 200, message = "", response = HookApiResourceSwagger.DeleteHookResponse.class)})
public String deleteHook(@PathParam("hookId") @ApiParam(value = "hookId") final Long hookId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder()
.deleteHook(hookId).build();
@@ -0,0 +1,147 @@
/**
* 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.infrastructure.hooks.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.fineract.infrastructure.hooks.data.Event;
import org.apache.fineract.infrastructure.hooks.data.Field;
import org.apache.fineract.infrastructure.hooks.data.Grouping;
import org.apache.fineract.infrastructure.hooks.data.HookTemplateData;
import org.joda.time.LocalDate;
import java.util.List;
/**
* Created by sanyam on 11/8/17.
*/
final class HookApiResourceSwagger {
private HookApiResourceSwagger() {
}
@ApiModel(value = "PostHookRequest")
public static final class PostHookRequest {
private PostHookRequest () {
}
@ApiModelProperty(example = "Web")
public String name;
@ApiModelProperty(example = "true")
public Boolean isActive;
@ApiModelProperty(example = "Kremlin")
public String displayName;
@ApiModelProperty(example = "1")
public Long templateId;
public List<Event> events;
public List<Field> config;
}
@ApiModel(value = "PostHookResponse")
public static final class PostHookResponse {
private PostHookResponse() {
}
@ApiModelProperty(example = "4")
public Long resourceId;
}
@ApiModel(value = "GetHookResponse")
public static final class GetHookResponse {
private GetHookResponse() {
}
@ApiModelProperty(example = "1")
public Long id;
@ApiModelProperty(example = "Web")
public String name;
@ApiModelProperty(example = "Kremlin")
public String displayName;
@ApiModelProperty(example = "true")
public Boolean isActive;
@ApiModelProperty(example = "[2014, 9, 16]")
public LocalDate createdAt;
@ApiModelProperty(example = "[2014, 9, 16]")
public LocalDate updatedAt;
@ApiModelProperty(example = "1")
public Long templateId;
@ApiModelProperty(example = "My UGD")
public String templateName;
public List<Event> events;
public List<Field> config;
}
@ApiModel(value = "GetHookTemplateResponse")
public static final class GetHookTemplateResponse {
private GetHookTemplateResponse() {
}
public List<HookTemplateData> templates;
public List<Grouping> groupings;
}
@ApiModel(value = "DeleteHookResponse")
public static final class DeleteHookResponse {
private DeleteHookResponse() {
}
@ApiModelProperty(example = "4")
public Long resourceId;
}
@ApiModel(value = "PutHookRequest")
public static final class PutHookRequest {
private PutHookRequest () {
}
@ApiModelProperty(example = "Web")
public String name;
@ApiModelProperty(example = "true")
public Boolean isActive;
@ApiModelProperty(example = "Kremlin")
public String displayName;
@ApiModelProperty(example = "1")
public Long templateId;
public List<Event> events;
public List<Field> config;
}
@ApiModel(value = "PutHookResponse")
public static final class PutHookResponse {
private PutHookResponse () {
}
final class PutHookResponseChangesSwagger {
private PutHookResponseChangesSwagger() {}
@ApiModelProperty(example = "Kremlin")
public String displayName;
@ApiModelProperty(example = "1")
public List<Event> events;
public List<Field> config;
}
@ApiModelProperty(example = "4")
public Long resourceId;
public PutHookResponseChangesSwagger changes;
}
}
@@ -29,6 +29,7 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
import org.apache.commons.lang.StringUtils;
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
import org.apache.fineract.infrastructure.core.exception.UnrecognizedQueryParamException;
@@ -43,6 +44,7 @@ import org.springframework.stereotype.Component;
@Path("/scheduler")
@Component
@Api(value = "Scheduler", description = "")
public class SchedulerApiResource {
private final PlatformSecurityContext context;
@@ -62,6 +64,8 @@ public class SchedulerApiResource {
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@ApiOperation(value = "Retrieve Scheduler Status", notes = "Returns the scheduler status.\n" + "\n" + "Example Requests:\n" + "\n" + "scheduler")
@ApiResponses({@ApiResponse(code = 200, message = "", response = SchedulerApiResourceSwagger.GetSchedulerResponse.class)})
public String retrieveStatus(@Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(SchedulerJobApiConstants.SCHEDULER_RESOURCE_NAME);
final boolean isSchedulerRunning = this.jobRegisterService.isSchedulerRunning();
@@ -74,7 +78,9 @@ public class SchedulerApiResource {
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public Response changeSchedulerStatus(@QueryParam(SchedulerJobApiConstants.COMMAND) final String commandParam) {
@ApiOperation(value = "Activate Scheduler Jobs | Suspend Scheduler Jobs", notes = "Activates the scheduler job service. | Suspends the scheduler job service.")
@ApiResponses({@ApiResponse(code = 200, message = "POST : scheduler?command=start\n\n"+"\n"+"POST : scheduler?command=stop")})
public Response changeSchedulerStatus(@QueryParam(SchedulerJobApiConstants.COMMAND) @ApiParam(value = "command") final String commandParam) {
// check the logged in user have permissions to update scheduler status
final boolean hasNotPermission = this.context.authenticatedUser().hasNotPermissionForAnyOf("ALL_FUNCTIONS", "UPDATE_SCHEDULER");
if (hasNotPermission) {
@@ -0,0 +1,42 @@
/**
* 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.infrastructure.jobs.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
* Created by sanyam on 12/8/17.
*/
final class SchedulerApiResourceSwagger {
private SchedulerApiResourceSwagger(){
}
@ApiModel(value = "GetSchedulerResponse")
public static final class GetSchedulerResponse {
private GetSchedulerResponse() {
}
@ApiModelProperty(example = "true")
public boolean active;
}
}
@@ -33,6 +33,7 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
import org.apache.commons.lang.StringUtils;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
@@ -57,6 +58,7 @@ import org.springframework.stereotype.Component;
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@Component
@Api(value = "MIFOSX-BATCH JOBS", description = "Batch jobs (also known as cron jobs on Unix-based systems) are a series of back-end jobs executed on a computer at a particular time defined in job's cron expression.\n" + "\n" + "At any point, you can view the list of batch jobs scheduled to run along with other details specific to each job. Manually you can execute the jobs at any point of time.\n" + "\n" + "The scheduler status can be either \"Active\" or \"Standby\". If the scheduler status is Active, it indicates that all batch jobs are running/ will run as per the specified schedule.If the scheduler status is Standby, it will ensure all scheduled batch runs are suspended.")
public class SchedulerJobApiResource {
private final SchedulerJobRunnerReadService schedulerJobRunnerReadService;
@@ -84,6 +86,8 @@ public class SchedulerJobApiResource {
}
@GET
@ApiOperation(value = "Retrieve Scheduler Jobs", notes = "Returns the list of jobs.\n" + "\n" + "Example Requests:\n" + "\n" + "jobs")
@ApiResponses({@ApiResponse(code = 200, message = "", response = SchedulerJobApiResourceSwagger.GetJobsResponse.class, responseContainer = "list")})
public String retrieveAll(@Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(SchedulerJobApiConstants.SCHEDULER_RESOURCE_NAME);
final List<JobDetailData> jobDetailDatas = this.schedulerJobRunnerReadService.findAllJobDeatils();
@@ -93,7 +97,9 @@ public class SchedulerJobApiResource {
@GET
@Path("{" + SchedulerJobApiConstants.JOB_ID + "}")
public String retrieveOne(@PathParam(SchedulerJobApiConstants.JOB_ID) final Long jobId, @Context final UriInfo uriInfo) {
@ApiOperation(value = "Retrieve a Job", notes = "Returns the details of a Job.\n" + "\n" + "Example Requests:\n" + "\n" + "jobs/5")
@ApiResponses({@ApiResponse(code = 200, message = "", response = SchedulerJobApiResourceSwagger.GetJobsResponse.class)})
public String retrieveOne(@PathParam(SchedulerJobApiConstants.JOB_ID) @ApiParam(value = "jobId") final Long jobId, @Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(SchedulerJobApiConstants.SCHEDULER_RESOURCE_NAME);
final JobDetailData jobDetailData = this.schedulerJobRunnerReadService.retrieveOne(jobId);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
@@ -102,9 +108,11 @@ public class SchedulerJobApiResource {
@GET
@Path("{" + SchedulerJobApiConstants.JOB_ID + "}/" + SchedulerJobApiConstants.JOB_RUN_HISTORY)
public String retrieveHistory(@Context final UriInfo uriInfo, @PathParam(SchedulerJobApiConstants.JOB_ID) final Long jobId,
@QueryParam("offset") final Integer offset, @QueryParam("limit") final Integer limit,
@QueryParam("orderBy") final String orderBy, @QueryParam("sortOrder") final String sortOrder) {
@ApiOperation(value = "Retrieve Job Run History", notes = "Example Requests:\n" + "\n" + "jobs/5/runhistory?offset=0&limit=200")
@ApiResponses({@ApiResponse(code = 200, message = "", response = SchedulerJobApiResourceSwagger.GetJobsJobIDJobRunHistoryResponse.class)})
public String retrieveHistory(@Context final UriInfo uriInfo, @PathParam(SchedulerJobApiConstants.JOB_ID) @ApiParam(value = "jobId") final Long jobId,
@QueryParam("offset") @ApiParam(value = "offset") final Integer offset, @QueryParam("limit") @ApiParam(value = "limit") final Integer limit,
@QueryParam("orderBy") @ApiParam(value = "orderBy") final String orderBy, @QueryParam("sortOrder") @ApiParam(value = "sortOrder") final String sortOrder) {
this.context.authenticatedUser().validateHasReadPermission(SchedulerJobApiConstants.SCHEDULER_RESOURCE_NAME);
final SearchParameters searchParameters = SearchParameters.forPagination(offset, limit, orderBy, sortOrder);
final Page<JobDetailHistoryData> jobhistoryDetailData = this.schedulerJobRunnerReadService.retrieveJobHistory(jobId,
@@ -116,8 +124,10 @@ public class SchedulerJobApiResource {
@POST
@Path("{" + SchedulerJobApiConstants.JOB_ID + "}")
public Response executeJob(@PathParam(SchedulerJobApiConstants.JOB_ID) final Long jobId,
@QueryParam(SchedulerJobApiConstants.COMMAND) final String commandParam) {
@ApiOperation(value = "Run a Job", notes = "Manually Execute Specific Job.")
@ApiResponses({@ApiResponse(code = 200, message = "POST: jobs/1?command=executeJob")})
public Response executeJob(@PathParam(SchedulerJobApiConstants.JOB_ID) @ApiParam(value = "jobId") final Long jobId,
@QueryParam(SchedulerJobApiConstants.COMMAND) @ApiParam(value = "command") final String commandParam) {
// check the logged in user have permissions to execute scheduler jobs
final boolean hasNotPermission = this.context.authenticatedUser().hasNotPermissionForAnyOf("ALL_FUNCTIONS", "EXECUTEJOB_SCHEDULER");
if (hasNotPermission) {
@@ -136,7 +146,10 @@ public class SchedulerJobApiResource {
@PUT
@Path("{" + SchedulerJobApiConstants.JOB_ID + "}")
public String updateJobDetail(@PathParam(SchedulerJobApiConstants.JOB_ID) final Long jobId, final String jsonRequestBody) {
@ApiOperation(value = "Update a Job", notes = "Updates the details of a job.")
@ApiImplicitParams({@ApiImplicitParam(value = "body", required = true, paramType = "body", dataType = "body", format = "body", dataTypeClass = SchedulerJobApiResourceSwagger.PutJobsJobIDRequest.class )})
@ApiResponses({@ApiResponse(code = 200, message = "")})
public String updateJobDetail(@PathParam(SchedulerJobApiConstants.JOB_ID) @ApiParam(value = "jobId") final Long jobId, @ApiParam(hidden = true) final String jsonRequestBody) {
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
.updateJobDetail(jobId) //
@@ -0,0 +1,96 @@
/**
* 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.infrastructure.jobs.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.fineract.infrastructure.jobs.data.JobDetailHistoryData;
import java.util.Date;
import java.util.List;
/**
* Created by sanyam on 12/8/17.
*/
final class SchedulerJobApiResourceSwagger {
private SchedulerJobApiResourceSwagger() {
}
@ApiModel(value = "GetJobsResponse")
public static final class GetJobsResponse {
private GetJobsResponse() {
}
@ApiModelProperty(example = "1")
public Long jobId;
@ApiModelProperty(example = "Update loan Summary")
public String displayName;
@ApiModelProperty(example = "")
public Date nextRunTime;
@ApiModelProperty(example = "")
public String initializingError;
@ApiModelProperty(example = "0 0 22 1/1 * ? *")
public String cronExpression;
@ApiModelProperty(example = "false")
public boolean active;
@ApiModelProperty(example = "false")
public boolean currentlyRunning;
public JobDetailHistoryData lastRunHistory;
}
@ApiModel(value = "PutJobsJobsIDRequest")
public static final class PutJobsJobIDRequest {
private PutJobsJobIDRequest() {
}
@ApiModelProperty(example = "Update loan Summary")
public String displayName;
@ApiModelProperty(example = "0 0 22 1/1 * ? *")
public String cronExpression;
@ApiModelProperty(example = "false")
public boolean active;
}
@ApiModel(value = "GetJobsJobIDJobRunHistoryResponse")
public static final class GetJobsJobIDJobRunHistoryResponse {
private GetJobsJobIDJobRunHistoryResponse() {
}
final class JobDetailHistoryDataSwagger {
private JobDetailHistoryDataSwagger(){}
@ApiModelProperty(example = "1")
public Long version;
@ApiModelProperty(example = "Jul 16, 2013 12:00:00 PM")
public Date jobRunStartTime;
@ApiModelProperty(example = "Jul 16, 2013 12:00:00 PM")
public Date jobRunEndTime;
@ApiModelProperty(example = "success")
public String status;
@ApiModelProperty(example = "cron")
public String triggerType;
}
@ApiModelProperty(example = "8")
public int totalFilteredRecords;
public List<JobDetailHistoryDataSwagger> pageItems;
}
}
@@ -49,7 +49,8 @@ public enum JobName {
GENERATE_ADHOCCLIENT_SCEHDULE("Generate AdhocClient Schedule"),
SEND_MESSAGES_TO_EMAIL_GATEWAY("Send messages to Email gateway"),
UPDATE_EMAIL_OUTBOUND_WITH_CAMPAIGN_MESSAGE("Update Email Outbound with campaign message"),
EXECUTE_EMAIL("Execute Email");
EXECUTE_EMAIL("Execute Email"),
UPDATE_TRAIL_BALANCE_DETAILS("Update Trial Balance Details");
private final String name;
@@ -115,14 +115,18 @@ public class SchedulerJobRunnerReadServiceImpl implements SchedulerJobRunnerRead
}
private boolean isJobExist(final Long jobId) {
boolean isJobPresent = false;
final String sql = "select count(*) from job job where job.id=" + jobId;
@SuppressWarnings("deprecation")
final int count = this.jdbcTemplate.queryForInt(sql);
if (count == 1) {
isJobPresent = true;
}
return isJobPresent;
boolean isJobPresent = false;
try{
final String sql = "select count(*) from job job where job.id= ?";
final int count = this.jdbcTemplate.queryForObject(sql, Integer.class, new Object[] { jobId });
if (count == 1) {
isJobPresent = true;
}
return isJobPresent;
}catch(EmptyResultDataAccessException e){
return isJobPresent;
}
}
private static final class JobDetailMapper implements RowMapper<JobDetailData> {
@@ -31,6 +31,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
@@ -51,6 +52,7 @@ import org.springframework.stereotype.Component;
@Path("/" + ReportMailingJobConstants.REPORT_MAILING_JOB_RESOURCE_NAME)
@Component
@Scope("singleton")
@Api(value = "Report Mailing Jobs", description = "This resource allows you to create a scheduled job that runs a report and sents it by email to specified email addresses.\n" + "\n" + "The scheduled job can be configured to run once or on a regular basis (once a day, twice a week, etc).")
public class ReportMailingJobApiResource {
private final PlatformSecurityContext platformSecurityContext;
@@ -75,7 +77,10 @@ public class ReportMailingJobApiResource {
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String createReportMailingJob(final String apiRequestBodyAsJson) {
@ApiOperation(value = "Create a Report Mailing Job", notes = "Mandatory Fields: " + "name, startDateTime, stretchyReportId, emailRecipients, emailSubject, emailMessage, emailAttachmentFileFormatId, recurrence, isActive\n" + "\n" + "Optional Fields: " + "description, stretchyReportParamMap")
@ApiImplicitParams({@ApiImplicitParam(value = "body", required = true, paramType = "body", dataType = "body", format = "body", dataTypeClass = ReportMailingJobApiResourceSwagger.PostReportMailingJobsRequest.class )})
@ApiResponses({@ApiResponse(code = 200, message = "", response = ReportMailingJobApiResourceSwagger.PostReportMailingJobsResponse.class)})
public String createReportMailingJob(@ApiParam(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandWrapper = new CommandWrapperBuilder().
createReportMailingJob(ReportMailingJobConstants.REPORT_MAILING_JOB_ENTITY_NAME).
withJson(apiRequestBodyAsJson).build();
@@ -89,7 +94,10 @@ public class ReportMailingJobApiResource {
@Path("{entityId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String updateReportMailingJob(@PathParam("entityId") final Long entityId, final String apiRequestBodyAsJson) {
@ApiOperation(value = "Update a Report Mailing Job\n", notes = "")
@ApiImplicitParams({@ApiImplicitParam(value = "body", required = true, paramType = "body", dataType = "body", format = "body", dataTypeClass = ReportMailingJobApiResourceSwagger.PutReportMailingJobsRequest.class )})
@ApiResponses({@ApiResponse(code = 200, message = "", response = ReportMailingJobApiResourceSwagger.PutReportMailingJobsResponse.class)})
public String updateReportMailingJob(@PathParam("entityId") @ApiParam(value = "entityId") final Long entityId, @ApiParam(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandWrapper = new CommandWrapperBuilder().
updateReportMailingJob(ReportMailingJobConstants.REPORT_MAILING_JOB_ENTITY_NAME, entityId).
withJson(apiRequestBodyAsJson).build();
@@ -103,7 +111,10 @@ public class ReportMailingJobApiResource {
@Path("{entityId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String deleteReportMailingJob(@PathParam("entityId") final Long entityId, final String apiRequestBodyAsJson) {
@ApiOperation(value = "Delete a Report Mailing Job", notes = "")
@ApiImplicitParams({@ApiImplicitParam(value = "body", required = true, paramType = "body", dataType = "body", format = "body", dataTypeClass = ReportMailingJobApiResourceSwagger.DeleteReportMailingJobsRequest.class )})
@ApiResponses({@ApiResponse(code = 200, message = "", response = ReportMailingJobApiResourceSwagger.DeleteReportMailingJobsResponse.class)})
public String deleteReportMailingJob(@PathParam("entityId") @ApiParam(value = "entityId") final Long entityId, @ApiParam(hidden = true) final String apiRequestBodyAsJson) {
final CommandWrapper commandWrapper = new CommandWrapperBuilder().
deleteReportMailingJob(ReportMailingJobConstants.REPORT_MAILING_JOB_ENTITY_NAME, entityId).
withJson(apiRequestBodyAsJson).build();
@@ -117,7 +128,9 @@ public class ReportMailingJobApiResource {
@Path("{entityId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveReportMailingJob(@PathParam("entityId") final Long entityId, @Context final UriInfo uriInfo) {
@ApiOperation(value = "Retrieve a Report Mailing Job", notes = "Example Requests:\n" + "\n" + "reportmailingjobs/1\n" + "\n" + "\n" + "reportmailingjobs/1?template=true")
@ApiResponses({@ApiResponse(code = 200, message = "", response = ReportMailingJobApiResourceSwagger.GetReportMailingJobsResponse.class)})
public String retrieveReportMailingJob(@PathParam("entityId") @ApiParam(value = "entityId") final Long entityId, @Context final UriInfo uriInfo) {
this.platformSecurityContext.authenticatedUser().validateHasReadPermission(ReportMailingJobConstants.REPORT_MAILING_JOB_ENTITY_NAME);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
@@ -135,6 +148,8 @@ public class ReportMailingJobApiResource {
@Path("template")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@ApiOperation(value = "Retrieve Report Mailing Job Details Template", notes = "This is a convenience resource. It can be useful when building maintenance user interface screens for report mailing job applications. The template data returned consists of any or all of:\n" + "\n" + "Field Defaults\n" + "Allowed Value Lists\n" + "Example Request:\n" + "\n" + "reportmailingjobs/template")
@ApiResponses({@ApiResponse(code = 200, message = "", response = ReportMailingJobApiResourceSwagger.GetReportMailingJobsTemplate.class)})
public String retrieveReportMailingJobTemplate(@Context final UriInfo uriInfo) {
this.platformSecurityContext.authenticatedUser().validateHasReadPermission(ReportMailingJobConstants.REPORT_MAILING_JOB_ENTITY_NAME);
@@ -147,10 +162,12 @@ public class ReportMailingJobApiResource {
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@ApiOperation(value = "List Report Mailing Jobs", notes = "Example Requests:\n" + "\n" + "reportmailingjobs")
@ApiResponses({@ApiResponse(code = 200, message = "", response = ReportMailingJobApiResourceSwagger.GetReportMailingJobsResponse.class, responseContainer = "list")})
public String retrieveAllReportMailingJobs(@Context final UriInfo uriInfo,
@QueryParam("offset") final Integer offset,
@QueryParam("limit") final Integer limit, @QueryParam("orderBy") final String orderBy,
@QueryParam("sortOrder") final String sortOrder) {
@QueryParam("offset") @ApiParam(value = "offset") final Integer offset,
@QueryParam("limit") @ApiParam(value = "limit") final Integer limit, @QueryParam("orderBy") @ApiParam(value = "orderBy") final String orderBy,
@QueryParam("sortOrder") @ApiParam(value = "sortOrder") final String sortOrder) {
this.platformSecurityContext.authenticatedUser().validateHasReadPermission(ReportMailingJobConstants.REPORT_MAILING_JOB_ENTITY_NAME);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
@@ -0,0 +1,172 @@
/**
* 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.infrastructure.reportmailingjob.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
import org.apache.fineract.infrastructure.dataqueries.data.ReportData;
import org.apache.fineract.infrastructure.reportmailingjob.data.ReportMailingJobTimelineData;
import org.joda.time.DateTime;
import java.util.List;
/**
* Created by sanyam on 13/8/17.
*/
final class ReportMailingJobApiResourceSwagger {
private ReportMailingJobApiResourceSwagger(){
}
@ApiModel(value = "GetReportMailingJobsTemplate")
public static final class GetReportMailingJobsTemplate {
private GetReportMailingJobsTemplate(){
}
@ApiModelProperty(example = "true")
public boolean isActive;
public List<EnumOptionData> emailAttachmentFileFormatOptions;
public List<EnumOptionData> stretchyReportParamDateOptions;
}
@ApiModel(value = "GetReportMailingJobsResponse")
public static final class GetReportMailingJobsResponse {
private GetReportMailingJobsResponse(){
}
@ApiModelProperty(example = "1")
public Long id;
@ApiModelProperty(example = "Client Numbers Report")
public String name;
@ApiModelProperty(example = "Client Numbers Report")
public String description;
@ApiModelProperty(example = "1469627093000")
public DateTime startDateTime;
@ApiModelProperty(example = "")
public String recurrence;
public ReportMailingJobTimelineData timeline;
@ApiModelProperty(example = "info@musonisystem.com")
public String emailRecipients;
@ApiModelProperty(example = "Client Numbers Report")
public String emailSubject;
@ApiModelProperty(example = "Client Numbers Report")
public String emailMessage;
@ApiModelProperty(example = "")
public EnumOptionData emailAttachmentFileFormat;
@ApiModelProperty(example = "")
public ReportData stretchyReport;
@ApiModelProperty(example = "{\"startDate\":\"2016-07-01\",\"endDate\":\"2016-08-02\",\"selectOffice\":\"1\",\"environementUrl\":\"environementUrl\"}")
public String stretchyReportParamMap;
@ApiModelProperty(example = "1469627093000")
public DateTime nextRunDateTime;
@ApiModelProperty(example = "0")
public Integer numberOfRuns;
@ApiModelProperty(example = "true")
public boolean isActive;
@ApiModelProperty(example = "1")
public Long runAsUserId;
}
@ApiModel(value = "PostReportMailingJobsRequest")
public static final class PostReportMailingJobsRequest {
private PostReportMailingJobsRequest(){
}
@ApiModelProperty(example = "en_GB")
public String locale;
@ApiModelProperty(example = "dd-MM-yyyy HH:mm:ss")
public String dateFormat;
@ApiModelProperty(example = "Client Numbers Report")
public String name;
@ApiModelProperty(example = "Client Numbers Report")
public String description;
@ApiModelProperty(example = "1469627093000")
public DateTime startDateTime;
@ApiModelProperty(example = "120")
public Long stretchyReportId;
@ApiModelProperty(example = "info@musonisystem.com")
public String emailRecipients;
@ApiModelProperty(example = "Client Numbers Report")
public String emailSubject;
@ApiModelProperty(example = "Client Numbers Report")
public String emailMessage;
@ApiModelProperty(example = "FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,WE,FR")
public String recurrence;
@ApiModelProperty(example = "true")
public boolean isActive;
@ApiModelProperty(example = "{\"startDate\":\"2016-07-01\",\"endDate\":\"2016-08-02\",\"selectOffice\":\"1\",\"environementUrl\":\"environementUrl\"}")
public String stretchyReportParamMap;
}
@ApiModel(value = "PostReportMailingJobsResponse")
public static final class PostReportMailingJobsResponse {
private PostReportMailingJobsResponse(){
}
@ApiModelProperty(example = "1")
public Long resourceId;
}
@ApiModel(value = "PutReportMailingJobsRequest")
public static final class PutReportMailingJobsRequest {
private PutReportMailingJobsRequest(){
}
@ApiModelProperty(example = "en_GB")
public String locale;
@ApiModelProperty(example = "dd-MM-yyyy HH:mm:ss")
public String dateFormat;
@ApiModelProperty(example = "10-08-2016 23:30:00")
public DateTime startDateTime;
}
@ApiModel(value = "PutReportMailingJobsResponse")
public static final class PutReportMailingJobsResponse {
private PutReportMailingJobsResponse(){
}
final class PutReportMailingJobsResponseChanges{
private PutReportMailingJobsResponseChanges(){}
@ApiModelProperty(example = "10-08-2016 23:30:00")
public DateTime startDateTime;
}
@ApiModelProperty(example = "1")
public Long resourceId;
public PutReportMailingJobsResponseChanges changes;
}
@ApiModel(value = "DeleteReportMailingJobsRequest ")
public static final class DeleteReportMailingJobsRequest {
private DeleteReportMailingJobsRequest(){
}
}
@ApiModel(value = "DeleteReportMailingJobsResponse")
public static final class DeleteReportMailingJobsResponse {
private DeleteReportMailingJobsResponse(){
}
@ApiModelProperty(example = "1")
public Long resourceId;
}
}
@@ -27,6 +27,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.*;
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
@@ -43,6 +44,7 @@ import org.springframework.stereotype.Component;
@Path("/" + ReportMailingJobConstants.REPORT_MAILING_JOB_RUN_HISTORY_RESOURCE_NAME)
@Component
@Scope("singleton")
@Api(value = "List Report Mailing Job History", description = "")
public class ReportMailingJobRunHistoryApiResource {
private final PlatformSecurityContext platformSecurityContext;
@@ -64,10 +66,14 @@ public class ReportMailingJobRunHistoryApiResource {
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveAllByReportMailingJobId(@Context final UriInfo uriInfo,
@QueryParam("reportMailingJobId") final Long reportMailingJobId, @QueryParam("offset") final Integer offset,
@QueryParam("limit") final Integer limit, @QueryParam("orderBy") final String orderBy,
@QueryParam("sortOrder") final String sortOrder) {
@ApiOperation(value = "List Report Mailing Job History", notes = "The list capability of report mailing job history can support pagination and sorting.\n" + "\n" + "Example Requests:\n" + "\n" + "reportmailingjobrunhistory/1")
@ApiResponses({@ApiResponse(code = 200, message = "", response = ReportMailingJobRunHistoryData.class)})
public String retrieveAllByReportMailingJobId(@Context final UriInfo uriInfo,
@QueryParam("reportMailingJobId") @ApiParam(value = "reportMailingJobId") final Long reportMailingJobId,
@QueryParam("offset") @ApiParam(value = "offset") final Integer offset,
@QueryParam("limit") @ApiParam(value = "limit") final Integer limit,
@QueryParam("orderBy") @ApiParam(value = "orderBy") final String orderBy,
@QueryParam("sortOrder") @ApiParam(value = "sortOrder") final String sortOrder) {
this.platformSecurityContext.authenticatedUser().validateHasReadPermission(ReportMailingJobConstants.REPORT_MAILING_JOB_ENTITY_NAME);
final SearchParameters searchParameters = SearchParameters.fromReportMailingJobRunHistory(offset, limit, orderBy, sortOrder);
@@ -0,0 +1,54 @@
/**
* 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.infrastructure.reportmailingjob.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiParam;
import org.joda.time.DateTime;
/**
* Created by sanyam on 13/8/17.
*/
final class ReportMailingJobRunHistoryApiResourceSwagger {
private ReportMailingJobRunHistoryApiResourceSwagger(){
}
@ApiModel(value = "GetReportMailingJobRunHistoryResponse")
public static final class GetReportMailingJobRunHistoryResponse {
private GetReportMailingJobRunHistoryResponse(){
}
@ApiModelProperty(example = "1")
public Long id;
@ApiModelProperty(example = "1")
public Long reportMailingJobId;
@ApiModelProperty(example = "1469627093050")
public DateTime startDateTime;
@ApiModelProperty(example = "1469627093050")
public DateTime endDateTime;
@ApiModelProperty(example = "success")
public String status;
@ApiModelProperty(example = "")
public String errorMessage;
@ApiModelProperty(example = "")
public String errorLog;
}
}
@@ -422,7 +422,8 @@ public class ReportMailingJobWritePlatformServiceImpl implements ReportMailingJo
final MultivaluedMap<String, String> reportParams, final String reportName, final StringBuilder errorLog) {
try {
final String reportType = this.readReportingService.getReportType(reportName);
final boolean isSelfServiceUserReport = false;
final String reportType = this.readReportingService.getReportType(reportName, isSelfServiceUserReport);
final ReportingProcessService reportingProcessService = this.reportingProcessServiceProvider.findReportingProcessService(reportType);
if (reportingProcessService != null) {
@@ -28,6 +28,7 @@ import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import io.swagger.annotations.*;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
import org.apache.fineract.infrastructure.core.serialization.ToApiJsonSerializer;
import org.apache.fineract.infrastructure.security.constants.TwoFactorConstants;
@@ -53,6 +54,7 @@ import com.sun.jersey.core.util.Base64;
@Component
@Profile("basicauth")
@Scope("singleton")
@Api(value = "Authentication HTTP Basic", description = "An API capability that allows client applications to verify authentication details using HTTP Basic Authentication.")
public class AuthenticationApiResource {
private final DaoAuthenticationProvider customAuthenticationProvider;
@@ -73,7 +75,9 @@ public class AuthenticationApiResource {
@POST
@Produces({ MediaType.APPLICATION_JSON })
public String authenticate(@QueryParam("username") final String username, @QueryParam("password") final String password) {
@ApiOperation(value = "Verify authentication", notes = "Authenticates the credentials provided and returns the set roles and permissions allowed.")
@ApiResponses({@ApiResponse(code = 200, message = "", response = AuthenticationApiResourceSwagger.PostAuthenticationResponse.class), @ApiResponse(code = 400, message = "Unauthenticated. Please login")})
public String authenticate(@QueryParam("username") @ApiParam(value = "username") final String username, @QueryParam("password") @ApiParam(value = "password") final String password) {
final Authentication authentication = new UsernamePasswordAuthenticationToken(username, password);
final Authentication authenticationCheck = this.customAuthenticationProvider.authenticate(authentication);
@@ -0,0 +1,62 @@
/**
* 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.infrastructure.security.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
import org.apache.fineract.useradministration.data.RoleData;
import java.util.Collection;
/**
* Created by sanyam on 13/8/17.
*/
final class AuthenticationApiResourceSwagger {
private AuthenticationApiResourceSwagger(){
}
@ApiModel(value = "PostAuthenticationResponse")
public static final class PostAuthenticationResponse {
private PostAuthenticationResponse() {
}
@ApiModelProperty(example = "mifos")
public String username;
@ApiModelProperty(example = "1")
public Long userId;
@ApiModelProperty(example = "bWlmb3M6cGFzc3dvcmQ=")
public String base64EncodedAuthenticationKey;
@ApiModelProperty(example = "true")
public boolean authenticated;
@ApiModelProperty(example = "1")
public Long officeId;
@ApiModelProperty(example = "Head Office")
public String officeName;
@ApiModelProperty(example = "1")
public Long staffId;
@ApiModelProperty(example = "Director, Program")
public String staffDisplayName;
public EnumOptionData organisationalRole;
public Collection<RoleData> roles;
@ApiModelProperty(example = "ALL_FUNCTIONS")
public Collection<String> permissions;
}
}
@@ -28,6 +28,7 @@ import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import io.swagger.annotations.*;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
import org.apache.fineract.infrastructure.core.serialization.ToApiJsonSerializer;
import org.apache.fineract.infrastructure.security.constants.TwoFactorConstants;
@@ -53,6 +54,7 @@ import org.springframework.stereotype.Component;
@Component
@Profile("oauth")
@Scope("singleton")
@Api(value = "Fetch authenticated user details", description = "")
public class UserDetailsApiResource {
private final ResourceServerTokenServices tokenServices;
@@ -73,7 +75,9 @@ public class UserDetailsApiResource {
@GET
@Produces({ MediaType.APPLICATION_JSON })
public String fetchAuthenticatedUserData(@QueryParam("access_token") final String accessToken) {
@ApiOperation(value = "Fetch authenticated user details\n", notes = "checks the Authentication and returns the set roles and permissions allowed.")
@ApiResponses({@ApiResponse(code = 200, message = "", response = UserDetailsApiResourceSwagger.GetUserDetailsResponse.class)})
public String fetchAuthenticatedUserData(@QueryParam("access_token") @ApiParam(value = "access_token") final String accessToken) {
final Authentication authentication = this.tokenServices.loadAuthentication(accessToken);
if (authentication.isAuthenticated()) {
@@ -0,0 +1,62 @@
/**
* 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.infrastructure.security.api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
import org.apache.fineract.useradministration.data.RoleData;
import java.util.Collection;
/**
* Created by sanyam on 13/8/17.
*/
final class UserDetailsApiResourceSwagger {
private UserDetailsApiResourceSwagger() {
}
@ApiModel(value = "GetUserDetailsResponse")
public static final class GetUserDetailsResponse {
private GetUserDetailsResponse(){
}
@ApiModelProperty(example = "mifos")
public String username;
@ApiModelProperty(example = "1")
public Long userId;
@ApiModelProperty(example = "bWlmb3M6cGFzc3dvcmQ=")
public String accessToken;
@ApiModelProperty(example = "true")
public boolean authenticated;
@ApiModelProperty(example = "1")
public Long officeId;
@ApiModelProperty(example = "Head Office")
public String officeName;
@ApiModelProperty(example = "1")
public Long staffId;
@ApiModelProperty(example = "mifosStaffDisplayName")
public String staffDisplayName;
public EnumOptionData organisationalRole;
public Collection<RoleData> roles;
@ApiModelProperty(example = "ALL_FUNCTIONS")
public Collection<String> permissions;
}
}
@@ -34,6 +34,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import io.swagger.annotations.Api;
import org.apache.fineract.accounting.journalentry.api.DateParam;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
@@ -56,6 +57,7 @@ import org.springframework.stereotype.Component;
@Produces({ MediaType.APPLICATION_JSON })
@Component
@Scope("singleton")
@Api(value = "SMS", description = "")
public class SmsApiResource {
private final String resourceNameForPermissions = "SMS";
@@ -28,6 +28,7 @@ import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import io.swagger.annotations.Api;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
@@ -46,6 +47,7 @@ import org.springframework.stereotype.Component;
@Path("/likelihood")
@Component
@Scope("singleton")
@Api(value = "Likelihood")
public class LikelihoodApiResource {
private final DefaultToApiJsonSerializer<LikelihoodData> toApiJsonSerializer;
@@ -25,6 +25,7 @@ import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import io.swagger.annotations.Api;
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.survey.data.LikeliHoodPovertyLineData;
@@ -37,6 +38,7 @@ import org.springframework.stereotype.Component;
@Path("/povertyLine")
@Component
@Scope("singleton")
@Api(value = "Poverty Line")
public class PovertyLineApiResource {
private final DefaultToApiJsonSerializer<PpiPovertyLineData> toApiJsonSerializer;
@@ -30,6 +30,7 @@ import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import io.swagger.annotations.*;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
@@ -52,6 +53,7 @@ import org.springframework.stereotype.Component;
@Path("/survey")
@Component
@Scope("singleton")
@Api(value = "Survey", description = "")
public class SurveyApiResource {
private final DefaultToApiJsonSerializer<SurveyData> toApiJsonSerializer;
@@ -78,6 +80,8 @@ public class SurveyApiResource {
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@ApiOperation(value = "Retrieve surveys", notes = "Retrieve surveys. This allows to retrieve the list of survey tables registered .")
@ApiResponses({@ApiResponse(code = 200, message = "", response = SurveyApiResourceSwagger.GetSurveyResponse.class, responseContainer = "List")})
public String retrieveSurveys() {
this.context.authenticatedUser().validateHasReadPermission(SurveyApiConstants.SURVEY_RESOURCE_NAME);
@@ -90,7 +94,9 @@ public class SurveyApiResource {
@Path("{surveyName}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveSurvey(@PathParam("surveyName") final String surveyName) {
@ApiOperation(value = "Retrieve survey", notes = "Lists a registered survey table details and the Apache Fineract Core application table they are registered to.")
@ApiResponses({@ApiResponse(code = 200, message = "", response = SurveyApiResourceSwagger.GetSurveyResponse.class)})
public String retrieveSurvey(@PathParam("surveyName") @ApiParam(value = "surveyName") final String surveyName) {
this.context.authenticatedUser().validateHasReadPermission(SurveyApiConstants.SURVEY_RESOURCE_NAME);
@@ -104,7 +110,10 @@ public class SurveyApiResource {
@Path("{surveyName}/{apptableId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String createDatatableEntry(@PathParam("surveyName") final String datatable, @PathParam("apptableId") final Long apptableId,
@ApiOperation(value = "Create an entry in the survey table", notes = "Insert and entry in a survey table (full fill the survey)." + "\n" + "\n" + "Refer Link for sample Body: [ https://demo.openmf.org/api-docs/apiLive.htm#survey_create ] ")
@ApiImplicitParams({@ApiImplicitParam(value = "body", required = true, paramType = "body", dataType = "body", format = "body", dataTypeClass = SurveyApiResourceSwagger.PostSurveySurveyNameApptableIdRequest.class)})
@ApiResponses({@ApiResponse(code = 200, message = "", response = SurveyApiResourceSwagger.PostSurveySurveyNameApptableIdResponse.class)})
public String createDatatableEntry(@PathParam("surveyName") @ApiParam(value = "surveyName") final String datatable, @PathParam("apptableId") @ApiParam(value = "apptableId") final Long apptableId,
final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder() //

Some files were not shown because too many files have changed in this diff Show More