diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm index 696e06622..686834944 100644 --- a/api-docs/apiLive.htm +++ b/api-docs/apiLive.htm @@ -292,6 +292,22 @@ + + Client Address + client/{clientId}/addresses + Create an address for a Client + List all Addresses for a Client + Update an address for a Client + + + + Entity Field Configuration + fieldconfiguration/{entity} + td> + List all configuration for a entity + + + Client Identifiers clients/{clientId}/identifiers @@ -1024,7 +1040,7 @@ - + accounts/share/{accountId}?command=activate @@ -1057,7 +1073,7 @@ - + accounts/share/{accountId}?command=rejectadditionalshares @@ -1066,7 +1082,7 @@ - + accounts/share/{accountId}?command=redeemshares @@ -1075,12 +1091,12 @@ - + - +

Loan

@@ -1976,7 +1992,7 @@ - + savingsproducts/{productId} @@ -2032,7 +2048,7 @@ Retrieve a Share product Update a Share product - + Currency currencies @@ -4460,6 +4476,187 @@ GET https://DomainName/api/v1/clients/template }
+ +
+ + GET https://DomainName/api/v1/clients/template + + + { + "activationDate":[2014,3,4], + "officeId":1, + "officeOptions":[{ + "id":1, + "name":"Head Office", + "nameDecorated":"Head Office" + }], + "staffOptions":[{ + "id":1, + "firstname":"xyz", + "lastname":"sjs", + "displayName":"sjs, xyz", + "officeId":1, + "officeName":"Head Office", + "isLoanOfficer":true, + "isActive":true + }], + "savingProductOptions":[{ + "id":4, + "name":"account overdraft", + "withdrawalFeeForTransfers":false, + "allowOverdraft":false + }] + } + +
+ +
+

if address is enabled

+ + GET https://DomainName/api/v1/clients/template + + + + + { + "activationDate": + [ + 2016, + 8, + 11 + ], + "officeId": 1, + "officeOptions": + [ + { + "id": 1, + "name": "Head Office", + "nameDecorated": "Head Office" + } + ], + "savingProductOptions": + [ + ], + "genderOptions": + [ + { + "id": 748, + "name": "Female", + "position": 1, + "isActive": true + }, + { + "id": 749, + "name": "Male", + "position": 2, + "isActive": true + } + ], + "clientTypeOptions": + [ + { + "id": 761, + "name": "JLG", + "position": 1, + "description": "", + "isActive": true + }, + { + "id": 760, + "name": "individual", + "position": 2, + "description": "", + "isActive": true + } + ], + "clientClassificationOptions": + [ + ], + "clientNonPersonConstitutionOptions": + [ + ], + "clientNonPersonMainBusinessLineOptions": + [ + ], + "clientLegalFormOptions": + [ + { + "id": 1, + "code": "legalFormType.person", + "value": "PERSON" + }, + { + "id": 2, + "code": "legalFormType.entity", + "value": "ENTITY" + } + ], + "address": + { + "countryIdOptions": + [ + { + "id": 802, + "name": "INDIA", + "position": 1, + "isActive": true + }, + { + "id": 803, + "name": "BANGLADESH", + "position": 2, + "isActive": true + }, + { + "id": 807, + "name": "UNITED STATES", + "position": 3, + "isActive": true + } + ], + "stateProvinceIdOptions": + [ + { + "id": 800, + "name": "MAHARASHTRA", + "position": 1, + "isActive": true + }, + { + "id": 801, + "name": "GUJRAT", + "position": 2, + "isActive": true + } + ], + "addressTypeIdOptions": + [ + { + "id": 804, + "name": "PERMANENT ADDRESS", + "position": 1, + "isActive": true + }, + { + "id": 805, + "name": "OFFICE ADDRESS", + "position": 2, + "isActive": true + }, + { + "id": 806, + "name": "CURRENT ADDRESS", + "position": 3, + "isActive": true + } + ] + }, + "isAddressEnabled": true + } + + + +
  @@ -4467,10 +4664,13 @@ GET https://DomainName/api/v1/clients/template

Create a Client

- Note: You can enter either:
+ Note:1. You can enter either:
firstname/middlename/lastname - for a person (middlename is optional) OR
fullname - for a business or organisation (or person known by one name).
+       2.If address is enable(enable-address=true), then additional field
+ called address has to be passed +

@@ -4478,6 +4678,7 @@ GET https://DomainName/api/v1/clients/template
firstname and lastname OR fullname,
officeId,
active=true and activationDate OR active=false,
+ if(address enabled) address
@@ -4520,6 +4721,45 @@ Content-Type: application/json Request Body: }
+
+ +

if address is enabled

+ POST https://DomainName/api/v1/clients +
+ + POST clients + Content-Type: application/json Request Body: + { + + "firstname": "Petra", + "lastname": "Yton", + "externalId": "786YYH7", + "dateFormat": "dd MMMM yyyy", + "locale": "en", + "active": true, + "activationDate": "04 March 2009", + "submittedOnDate":"04 March 2009", + "officeId":1, + "address":[ + { + "addressTypeId": 805, + "isActive": true, + "street": "rapchik", + "stateProvinceId": 800, + "countryId": 802 + } + ] + } + + + { + "officeId": 1, + "clientId": 1, + "resourceId": 1, + "savingsId": 10 + } + +
POST clients @@ -5324,11 +5564,358 @@ GET https://DomainName/api/v1/clients/{clientId}/accounts } } ] -} - -
+} + + +   +
+
+

Entity Field Configuration

+

Entity Field configuration API is a generic and extensible
+ wherein various entities and subentities can be related.
+ Also it gives the user an ability to enable/disable fields,
add regular expression for validation

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Field Descriptions
entity
Entity to which relationship is to be established +
subentity
Entity which uses/relies on other entity for addional description +
field
Field of the Enity which is to be configured +
validation_regex
Regular expression for validating field's data +
is_enabled
This is used to enable/disable field +
is_mandatory
This is used to make field mandatory +
+
+
+   +
+
+ + GET https://DomainName/api/v1/fieldconfiguration/{entity} + + + [ + { + "fieldConfigurationId": 1, + "entity": "ADDRESS", + "subentity": "CLIENT", + "field": "addressType", + "is_enabled": true, + "is_mandatory": false, + "validation_regex": "" + }, + { + "fieldConfigurationId": 2, + "entity": "ADDRESS", + "subentity": "CLIENT", + "field": "street", + "is_enabled": true, + "is_mandatory": true, + "validation_regex": "" + }, + { + "fieldConfigurationId": 3, + "entity": "ADDRESS", + "subentity": "CLIENT", + "field": "addressLine1", + "is_enabled": true, + "is_mandatory": false, + "validation_regex": "" + }, + { + "fieldConfigurationId": 4, + "entity": "ADDRESS", + "subentity": "CLIENT", + "field": "addressLine2", + "is_enabled": true, + "is_mandatory": false, + "validation_regex": "" + }, + { + "fieldConfigurationId": 5, + "entity": "ADDRESS", + "subentity": "CLIENT", + "field": "addressLine3", + "is_enabled": true, + "is_mandatory": false, + "validation_regex": "" + } + ] + +
+
+ + + + +   +
+
+

Client Address

+

Address module is an optional module and can be configured
+ into the system by using GlobalConfiguration setting: enable-address.
+ In order to activate Address module, we need to enable the configuration,
+ enable-address by setting its value to true. +

+ + + + + + + + + + + + + + + + + +
Field Descriptions
addressTypeId
Address module has the ability to store
+ multiple types of address of clients.addressTypeId is basically a code whose value
+ are used to store the different types of addresses. +
street,addressLine1,addressLine2,addressLine3,townVillage,city,
+ countyDistrict,stateProvinceId,
+ countryId,postalCode,latitude,longitude,createdBy,createdOn,
+ updatedBy,updatedOn
The above are the fields of address
+ which are configurable using settings stored for each field in
+ m_field_configuration table. +
+
+
+ +   +
+
+

List all addresses for a Client

+

Example Requests:

+
client/1/addresses
+
+
+
clients/1/addresses?status=false,true&&type=1,2,3
+ +
+
+ + GET https://DomainName/api/v1/client/{clientid}/addresses + + + [ + { + "client_id": 111755, + "addressType": "PERMANENT ADDRESS", + "addressId": 14, + "addressTypeId": 804, + "isActive": false, + "street": "anki's home", + "addressLine1": "test123", + "addressLine2": "iuyt", + "addressLine3": "", + "townVillage": "", + "city": "mumbai", + "countyDistrict": "", + "stateProvinceId": 801, + "countryName": "UNITED STATES", + "stateName": "GUJRAT", + "countryId": 807, + "postalCode": "400095", + "createdBy": "", + "updatedBy": "" + }, + { + "client_id": 111755, + "addressType": "PERMANENT ADDRESS", + "addressId": 17, + "addressTypeId": 804, + "isActive": false, + "street": "anki's home", + "addressLine1": "", + "addressLine2": "", + "addressLine3": "", + "townVillage": "", + "city": "", + "countyDistrict": "", + "stateProvinceId": 800, + "countryName": "INDIA", + "stateName": "MAHARASHTRA", + "countryId": 802, + "postalCode": "", + "createdBy": "", + "updatedBy": "" + }, + { + "client_id": 111755, + "addressType": "OFFICE ADDRESS", + "addressId": 18, + "addressTypeId": 805, + "isActive": false, + "street": "anki's office", + "addressLine1": "", + "addressLine2": "", + "addressLine3": "", + "townVillage": "", + "city": "", + "countyDistrict": "", + "stateProvinceId": 0, + "countryId": 0, + "postalCode": "", + "createdBy": "", + "updatedBy": "" + } + ] + +
+ +
+ + GET https://DomainName/api/v1/client/{clientid}/addresses?type=804&&status=false + + + [ + { + "client_id": 111755, + "addressType": "PERMANENT ADDRESS", + "addressId": 14, + "addressTypeId": 804, + "isActive": false, + "street": "anki's home", + "addressLine1": "test123", + "addressLine2": "iuyt", + "addressLine3": "", + "townVillage": "", + "city": "mumbai", + "countyDistrict": "", + "stateProvinceId": 801, + "countryName": "UNITED STATES", + "stateName": "GUJRAT", + "countryId": 807, + "postalCode": "400095", + "createdBy": "", + "updatedBy": "" + } + } + ] + +
+
+ +   +
+
+

Create an address for a Client

+ + + + + + + +
Mandatory Fields
type and clientId +
+
+
+ + POST https://DomainName/api/v1/client/{clientId}/addresses?type={addressTypeId} + + + POST client/1/address?type=805 + Content-Type: application/json Request Body: + { + "street":"Ipca", + "addressLine1":"Kandivali", + "addressLine2":"plot47", + "addressLine3":"charkop", + "city":"Mumbai", + "stateProvinceId":800, + "countryId":802, + "postalCode":"400064" + } + + + { + "resourceId":15 + } + +
+
+ +   +
+
+

update an address for a Client

+

All the address fields can be updated by using update client address API

+ + + + + + + +
Mandatory Fields
type and addressId +
+
+
+ + PUT https://DomainName/api/v1/client/{clientId}/addresses?type={addressTypeId} + + + POST client/1/addresses?type=805 + Content-Type: application/json Request Body: + { + "addressId":67, + "street":"goldensource" + } + + + { + "resourceId":67 + } + +
+
+  
@@ -10152,8 +10739,8 @@ No Request Body:
'foreclosure'
"transaction date" is set to the current date by default
"transaction amount" is set - to the sum of total loan outstanding principal - and total Interest/ Fee/ Charges / Penalties + to the sum of total loan outstanding principal + and total Interest/ Fee/ Charges / Penalties till foreclosure date.
@@ -19748,7 +20335,7 @@ Content-Type: application/json taxGroupId Optional: If withhold tax set as true, with hold tax will be applied as per the tax group provided - +
@@ -20320,12 +20907,12 @@ Content-Type: application/json
-
Optional Fields
sharesIssued, minimumShares, maximumShares, minimumActivePeriodForDividends, minimumactiveperiodFrequencyType, +
sharesIssued, minimumShares, maximumShares, minimumActivePeriodForDividends, minimumactiveperiodFrequencyType, lockinPeriodFrequency, lockinPeriodFrequencyType, marketPricePeriods, chargesSelected
- + POST https://Domain Name/api/v1/products/share POST shareproducts Content-Type: application/json @@ -20358,7 +20945,7 @@ Request Body: "chargesSelected": [{ "id": 20 }], -"accountingRule": "1" +"accountingRule": "1" } @@ -20402,7 +20989,7 @@ Request Body: "shareReferenceId": 5, "shareSuspenseId": 8, "shareEquityId": 66, -"incomeFromFeeAccountId": 2 +"incomeFromFeeAccountId": 2 } @@ -20775,10 +21362,10 @@ Request Body:
shareproducts
- + GET https://Domain Name/api/v1/products/share?limit=10&offset=0 - + { "totalFilteredRecords": 1, "pageItems": [{ @@ -20791,7 +21378,7 @@ Request Body:
- +  
@@ -22178,7 +22765,7 @@ Content-Type: application/json

Share Account:

-

Share accounts are instances of a praticular share product created for an individual. +

Share accounts are instances of a praticular share product created for an individual. An application process around the creation of accounts is also supported.

@@ -22260,7 +22847,7 @@ Content-Type: application/json
- +  
@@ -22331,7 +22918,7 @@ Content-Type: application/json "value": "Flat" }, "amount": 1.000000, - + }], "lockinPeriodFrequencyTypeOptions": [{ "id": 0, @@ -22402,7 +22989,7 @@ Request Body: { "clientId": "7", "productId": 1, - + "requestedShares": 100, "externalId": "1", "submittedDate": "01 May 2016", @@ -22426,7 +23013,7 @@ Request Body: "chargeId": 23, "amount": 2 }], - + "savingsAccountId": 13 } @@ -22437,7 +23024,7 @@ Request Body:
- +  
@@ -22458,7 +23045,7 @@ Request Body: { - + "resourceId": 1, "changes": { "status": { @@ -22496,7 +23083,7 @@ Request Body: { - + "resourceId": 1, "changes": { "status": { @@ -22515,7 +23102,7 @@ Request Body:
- +  
@@ -22535,7 +23122,7 @@ Request Body: { - + "resourceId": 1, "changes": { "status": { @@ -22613,7 +23200,7 @@ Request Body:
- +
POST https://Domain Name/api/v1/accounts/share/{shareAccountId}?command=close @@ -22629,7 +23216,7 @@ Request Body: { - + "resourceId":5, "changes":{ "status":{ @@ -22648,7 +23235,7 @@ Request Body: "note":"close note" } } - +
@@ -22659,7 +23246,7 @@ Request Body:

Apply additional shares on a share account

requestedDate is requsted date of share purchase

requestedShares is number of shares to be purchase

- + @@ -22669,7 +23256,7 @@ Request Body:
Mandatory Fields

- +
POST https://Domain Name/api/v1/accounts/share/{shareAccountId}?command=applyadditionalshares @@ -22685,10 +23272,10 @@ Request Body: { - + "resourceId":5, } - +
@@ -22698,7 +23285,7 @@ Request Body:

Approve additional shares request on a share account

requestedShares is Share purchase transaction ids

- + @@ -22708,7 +23295,7 @@ Request Body:
Mandatory Fields

- +
POST https://Domain Name/api/v1/accounts/share/{shareAccountId}?command=approveadditionalshares @@ -22723,10 +23310,10 @@ Request Body: { - + "resourceId":5, } - +
@@ -22736,7 +23323,7 @@ Request Body:

Reject additional shares request on a share account

requestedShares is Share purchase transaction ids

- + @@ -22746,7 +23333,7 @@ Request Body:
Mandatory Fields

- +
POST https://Domain Name/api/v1/accounts/share/{shareAccountId}?command=rejectadditionalshares @@ -22759,10 +23346,10 @@ Request Body: { - + "resourceId":5, } - +
@@ -22774,7 +23361,7 @@ Request Body:

Results redeem some/all shares from share account.

requestedDate is requsted date of shares redeem

requestedShares is number of shares to be redeemed

- + @@ -22784,7 +23371,7 @@ Request Body:
Mandatory Fields

- +
POST https://Domain Name/api/v1/accounts/share/{shareAccountId}?command=redeemshares @@ -22800,10 +23387,10 @@ Request Body: { - + "resourceId":5, } - +
@@ -22814,7 +23401,7 @@ Request Body:

List share applications/accounts

Example Requests:

shareaccount
- +
GET https://Domain Name/api/v1/accounts/share @@ -22829,7 +23416,7 @@ Request Body: "clientName": "Client Name", "productId": 1, "productName": "Share Product Name", - + "status": { "id": 100, "code": "shareAccountStatusType.submitted.and.pending.approval", @@ -22862,7 +23449,7 @@ Request Body: "purchasedPrice": 5 } ], - + "summary": { "currency": { "code": "USD", @@ -22884,7 +23471,7 @@ Request Body:

Retrieve a share application/account:

- +

Example Requests :

shareaccount/1
@@ -23271,7 +23858,7 @@ No Request Body: { - + "resourceId": 1, "changes": { "dateFormat": "dd MMMM yyyy", @@ -23283,7 +23870,7 @@ No Request Body:
- +   @@ -23388,7 +23975,7 @@ No Request Body: overdraftLimit Optional: If provided, sets the maximum allowed overdraft amount for a savings account e.g. 5,000 else set the limit as zero - + withHoldTax Optional: If tax group provided at product level, will allow to Enable or disable withhold tax on interest posting for savings account @@ -24476,8 +25063,8 @@ No Request Body: - - + +  
@@ -27062,7 +27649,7 @@ No Request Body: withHoldTax Optional: If tax group provided at product level, will allow to Enable or disable withhold tax on interest posting for savings account - +
@@ -39552,7 +40139,7 @@ No Request Body: - +  
@@ -39716,7 +40303,7 @@ No Request Body: 4, 11], "taxComponentHistories": [{ - + }] }, { @@ -39737,9 +40324,9 @@ No Request Body: 4, 11], "taxComponentHistories": [{ - + }] - }] + }]
@@ -39777,7 +40364,7 @@ No Request Body: 4, 11], "taxComponentHistories": [{ - + }] } @@ -39940,7 +40527,7 @@ No Request Body: "startDate": "11 April 2016" }], "dateFormat": "dd MMMM yyyy" - } + } { @@ -39992,7 +40579,7 @@ No Request Body: 4, 11] }] - }] + }] @@ -43002,8 +43589,8 @@ Request Body: - - + +  
@@ -44201,7 +44788,7 @@ No Request Body:
- +
POST https://DomainName/api/v1/self/beneficiaries/tpt @@ -44216,7 +44803,7 @@ Request Body: "accountNumber": "0000001", "accountType": 1, "transferLimit": 1000 - + } @@ -44235,7 +44822,7 @@ Request Body:

Example Requests:

/self/beneficiaries/tpt
- +
GET https://DomainName/api/v1/self/beneficiaries/tpt @@ -44295,7 +44882,7 @@ Content-Type: application/json
- +
PUT https://DomainName/api/v1/self/beneficiaries/tpt/{beneficiaryId} @@ -44306,7 +44893,7 @@ Request Body: { "name": "beneficiary nick name", "transferLimit": 1000 - + } @@ -44329,7 +44916,7 @@ Request Body:

Example Requests:

/self/beneficiaries/tpt/{beneficiaryId}
- +
DELETE https://DomainName/api/v1/self/beneficiaries/tpt/{beneficiaryId} @@ -44593,6 +45180,7 @@ No Request Body: + Client Identifiers clients/{clientId}/identifiers @@ -46298,7 +46886,7 @@ No Request Body: - + shareproducts/template diff --git a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java index 3b26e1df1..dea6a9e42 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java +++ b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java @@ -41,12 +41,31 @@ public class CommandWrapperBuilder { private String transactionId; private Long productId; private Long templateId; + public CommandWrapper build() { return new CommandWrapper(this.officeId, this.groupId, this.clientId, this.loanId, this.savingsId, this.actionName, - this.entityName, this.entityId, this.subentityId, this.href, this.json, this.transactionId, this.productId, this.templateId); + this.entityName, this.entityId, this.subentityId, this.href, this.json, this.transactionId, this.productId, + this.templateId); } - + + public CommandWrapperBuilder addClientAddress(final long clientId,final long addressTypeId) { + this.actionName = "CREATE"; + this.entityName = "ADDRESS"; + this.entityId = addressTypeId; + this.href = "/clients/"+clientId+"/addresses"; + this.clientId=clientId; + return this; + } + + public CommandWrapperBuilder updateClientAddress(final long clientId) { + this.actionName = "UPDATE"; + this.entityName = "ADDRESS"; + this.href = "/clients/"+clientId+"/addresses"; + this.clientId=clientId; + return this; + } + public CommandWrapperBuilder withLoanId(final Long withLoanId) { this.loanId = withLoanId; return this; diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/data/GlobalConfigurationPropertyData.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/data/GlobalConfigurationPropertyData.java index 7b3a0ab72..40aede7d2 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/data/GlobalConfigurationPropertyData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/data/GlobalConfigurationPropertyData.java @@ -60,4 +60,34 @@ public class GlobalConfigurationPropertyData { this.description = description; this.trapDoor = isTrapDoor; } + + public String getName() { + return this.name; + } + + public boolean isEnabled() { + return this.enabled; + } + + public Long getValue() { + return this.value; + } + + public Date getDateValue() { + return this.dateValue; + } + + public Long getId() { + return this.id; + } + + public String getDescription() { + return this.description; + } + + public boolean isTrapDoor() { + return this.trapDoor; + } + + } \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/ConfigurationReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/ConfigurationReadPlatformService.java index 27a734920..2c9c9c11a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/ConfigurationReadPlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/ConfigurationReadPlatformService.java @@ -24,6 +24,8 @@ import org.apache.fineract.infrastructure.configuration.data.GlobalConfiguration public interface ConfigurationReadPlatformService { GlobalConfigurationPropertyData retrieveGlobalConfiguration(Long configId); + + GlobalConfigurationPropertyData retrieveGlobalConfiguration(String name); GlobalConfigurationData retrieveGlobalConfiguration(boolean survey); diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/ConfigurationReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/ConfigurationReadPlatformServiceImpl.java index 80c704739..ab7f30f23 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/ConfigurationReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/ConfigurationReadPlatformServiceImpl.java @@ -66,6 +66,21 @@ public class ConfigurationReadPlatformServiceImpl implements ConfigurationReadPl return new GlobalConfigurationData(globalConfiguration); } + + + + @Override + public GlobalConfigurationPropertyData retrieveGlobalConfiguration(String name) { + + this.context.authenticatedUser(); + + final String sql = "SELECT c.id, c.name, c.enabled, c.value, c.date_value, c.description, c.is_trap_door FROM " + + "c_configuration c where c.name=? order by c.id"; + final GlobalConfigurationPropertyData globalConfiguration = this.jdbcTemplate.queryForObject(sql, this.rm, + new Object[] { name }); + + return globalConfiguration; + } @Override public GlobalConfigurationPropertyData retrieveGlobalConfiguration(Long configId) { @@ -80,6 +95,7 @@ public class ConfigurationReadPlatformServiceImpl implements ConfigurationReadPl return globalConfiguration; } + private static final class GlobalConfigurationRowMapper implements RowMapper { @Override diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/api/EntityFieldConfigurationApiResources.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/api/EntityFieldConfigurationApiResources.java new file mode 100644 index 000000000..838e419fe --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/api/EntityFieldConfigurationApiResources.java @@ -0,0 +1,99 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.address.api; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.UriInfo; + +import org.apache.fineract.commands.domain.CommandWrapper; +import org.apache.fineract.commands.service.CommandWrapperBuilder; +import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService; +import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings; +import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.apache.fineract.portfolio.address.data.AddressData; +import org.apache.fineract.portfolio.address.data.FieldConfigurationData; +import org.apache.fineract.portfolio.address.service.AddressReadPlatformServiceImpl; +import org.apache.fineract.portfolio.address.service.FieldConfigurationReadPlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +@Path("/fieldconfiguration/{entity}") +@Component +@Scope("singleton") +public class EntityFieldConfigurationApiResources { + + private final Set RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList("clientAddressId", "client_id", + "address_id", "address_type_id", "isActive", "fieldConfigurationId", "entity", "table", "field", + "is_enabled", "is_mandatory", "validation_regex")); + private final String resourceNameForPermissions = "Address"; + private final PlatformSecurityContext context; + private final DefaultToApiJsonSerializer toApiJsonSerializer; + private final FieldConfigurationReadPlatformService readPlatformServicefld; + private final DefaultToApiJsonSerializer toApiJsonSerializerfld; + private final ApiRequestParameterHelper apiRequestParameterHelper; + private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; + + @Autowired + public EntityFieldConfigurationApiResources(final PlatformSecurityContext context, + final DefaultToApiJsonSerializer toApiJsonSerializer, + final FieldConfigurationReadPlatformService readPlatformServicefld, + final DefaultToApiJsonSerializer toApiJsonSerializerfld, + final ApiRequestParameterHelper apiRequestParameterHelper, + final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) { + this.context = context; + this.toApiJsonSerializer = toApiJsonSerializer; + this.readPlatformServicefld = readPlatformServicefld; + this.toApiJsonSerializerfld = toApiJsonSerializerfld; + this.apiRequestParameterHelper = apiRequestParameterHelper; + this.commandsSourceWritePlatformService = commandsSourceWritePlatformService; + } + + @GET + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String getAddresses(@PathParam("entity") final String entityname, @Context final UriInfo uriInfo) { + this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions); + + final Collection fldconfig = this.readPlatformServicefld + .retrieveFieldConfiguration(entityname); + + final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper + .process(uriInfo.getQueryParameters()); + return this.toApiJsonSerializerfld.serialize(settings, fldconfig, this.RESPONSE_DATA_PARAMETERS); + + } + + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/data/AddressData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/data/AddressData.java new file mode 100644 index 000000000..8601b46a9 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/data/AddressData.java @@ -0,0 +1,188 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.address.data; + +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Date; + +import org.apache.fineract.infrastructure.codes.data.CodeValueData; + +public class AddressData { + private final Long client_id; + + private final String addressType; + + private final Long addressId; + + private final Long addressTypeId; + + private final Boolean isActive; + + private final String street; + + private final String addressLine1; + + private final String addressLine2; + + private final String addressLine3; + + private final String townVillage; + + private final String city; + + private final String countyDistrict; + + private final Long stateProvinceId; + + private final String countryName; + + private final String stateName; + + private final Long countryId; + + private final String postalCode; + + private final BigDecimal latitude; + + private final BigDecimal longitude; + + private final String createdBy; + + private final Date createdOn; + + private final String updatedBy; + + private final Date updatedOn; + + // template holder + private final Collection countryIdOptions; + private final Collection stateProvinceIdOptions; + private final Collection addressTypeIdOptions; + + private AddressData(final String addressType, final Long client_id, final Long addressId, final Long addressTypeId, + final Boolean is_active, final String street, final String addressLine1, final String addressLine2, + final String addressLine3, final String townVillage, final String city, final String countyDistrict, + final Long stateProvinceId, final Long countryId, final String stateName, final String countryName, + final String postalCode, final BigDecimal latitude, final BigDecimal longitude, final String createdBy, + final Date createdOn, final String updatedBy, final Date updatedOn, + final Collection countryIdOptions, final Collection stateProvinceIdOptions, + final Collection addressTypeIdOptions) { + this.addressType = addressType; + this.client_id = client_id; + this.addressId = addressId; + this.addressTypeId = addressTypeId; + this.isActive = is_active; + this.street = street; + this.addressLine1 = addressLine1; + this.addressLine2 = addressLine2; + this.addressLine3 = addressLine3; + this.townVillage = townVillage; + this.city = city; + this.countyDistrict = countyDistrict; + this.stateProvinceId = stateProvinceId; + this.countryId = countryId; + this.stateName = stateName; + this.countryName = countryName; + this.postalCode = postalCode; + this.latitude = latitude; + this.longitude = longitude; + this.createdBy = createdBy; + this.createdOn = createdOn; + this.updatedBy = updatedBy; + this.updatedOn = updatedOn; + this.countryIdOptions = countryIdOptions; + this.stateProvinceIdOptions = stateProvinceIdOptions; + this.addressTypeIdOptions = addressTypeIdOptions; + } + + public static AddressData instance(final String addressType, final Long client_id, final Long addressId, + final Long addressTypeId, final Boolean is_active, final String street, final String addressLine1, + final String addressLine2, final String addressLine3, final String townVillage, final String city, + final String countyDistrict, final Long stateProvinceId, final Long countryId, final String stateName, + final String countryName, final String postalCode, final BigDecimal latitude, final BigDecimal longitude, + final String createdBy, final Date createdOn, final String updatedBy, final Date updatedOn) { + + return new AddressData(addressType, client_id, addressId, addressTypeId, is_active, street, addressLine1, + addressLine2, addressLine3, townVillage, city, countyDistrict, stateProvinceId, countryId, + stateName, countryName, postalCode, latitude, longitude, createdBy, createdOn, updatedBy, + updatedOn, null, null, null); + } + + public static AddressData instance1(final Long addressId, final String street, final String addressLine1, + final String addressLine2, final String addressLine3, final String townVillage, final String city, + final String countyDistrict, final Long stateProvinceId, final Long countryId, final String postalCode, + final BigDecimal latitude, final BigDecimal longitude, final String createdBy, final Date createdOn, + final String updatedBy, final Date updatedOn) { + return new AddressData(null, null, addressId, null, false, street, addressLine1, addressLine2, + addressLine3, townVillage, city, countyDistrict, stateProvinceId, countryId, null, null, + postalCode, latitude, longitude, createdBy, createdOn, updatedBy, updatedOn, null, null, null); + } + + public static AddressData template(final Collection countryIdOptions, + final Collection stateProvinceIdOptions, + final Collection addressTypeIdOptions) { + final Long client_idtemp = null; + + final Long addressIdtemp = null; + + final Long addressTypeIdtemp = null; + + final Boolean is_activetemp = null; + + final String streettemp = null; + + final String addressLine1temp = null; + + final String addressLine2temp = null; + + final String addressLine3temp = null; + + final String townVillagetemp = null; + + final String citytemp = null; + + final String countyDistricttemp = null; + + final Long stateProvinceIdtemp = null; + + final Long countryIdtemp = null; + + final String postalCodetemp = null; + + final BigDecimal latitudetemp = null; + + final BigDecimal longitudetemp = null; + + final String createdBytemp = null; + + final Date createdOntemp = null; + + final String updatedBytemp = null; + + final Date updatedOntemp = null; + + return new AddressData(null, client_idtemp, addressIdtemp, addressTypeIdtemp, is_activetemp, streettemp, + addressLine1temp, addressLine2temp, addressLine3temp, townVillagetemp, citytemp, + countyDistricttemp, stateProvinceIdtemp, countryIdtemp, null, null, postalCodetemp, latitudetemp, + longitudetemp, createdBytemp, createdOntemp, updatedBytemp, updatedOntemp, countryIdOptions, + stateProvinceIdOptions, addressTypeIdOptions); + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/data/ClientAddressData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/data/ClientAddressData.java new file mode 100644 index 000000000..dc55e0538 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/data/ClientAddressData.java @@ -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.portfolio.address.data; + +public class ClientAddressData { + + private final long clientAddressId; + + private final long client_id; + + private final long address_id; + + private final long address_type_id; + + private final boolean isActive; + + private ClientAddressData(final long clientAddressId, final long client_id, final long address_id, + final long address_type_id, final boolean isActive) { + this.clientAddressId = clientAddressId; + this.client_id = client_id; + this.address_id = address_id; + this.address_type_id = address_type_id; + this.isActive = isActive; + } + + public static ClientAddressData instance(final long clientAddressId, final long client_id, final long address_id, + final long address_type_id, final boolean isActive) { + return new ClientAddressData(clientAddressId, client_id, address_id, address_type_id, isActive); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/data/FieldConfigurationData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/data/FieldConfigurationData.java new file mode 100644 index 000000000..ae0495d0a --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/data/FieldConfigurationData.java @@ -0,0 +1,82 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.address.data; + +public class FieldConfigurationData { + private final long fieldConfigurationId; + + private final String entity; + + private final String subentity; + + private final String field; + + private final boolean is_enabled; + + private final boolean is_mandatory; + + private final String validation_regex; + + private FieldConfigurationData(final long fieldConfigurationId, final String entity, final String subentity, + final String field, final boolean is_enabled, final boolean is_mandatory, final String validation_regex) { + this.fieldConfigurationId = fieldConfigurationId; + this.entity = entity; + this.subentity = subentity; + this.field = field; + this.is_enabled = is_enabled; + this.is_mandatory = is_mandatory; + this.validation_regex = validation_regex; + } + + public static FieldConfigurationData instance(final long fieldConfigurationId, final String entity, + final String subentity, final String field, final boolean is_enabled, final boolean is_mandatory, + final String validation_regex) { + return new FieldConfigurationData(fieldConfigurationId, entity, subentity, field, is_enabled, is_mandatory, + validation_regex); + } + + public long getFieldConfigurationId() { + return this.fieldConfigurationId; + } + + public String getEntity() { + return this.entity; + } + + public String getSubEntity() { + return this.subentity; + } + + public String getField() { + return this.field; + } + + public boolean isIs_enabled() { + return this.is_enabled; + } + + public boolean isIs_mandatory() { + return this.is_mandatory; + } + + public String getValidation_regex() { + return this.validation_regex; + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/domain/Address.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/domain/Address.java new file mode 100644 index 000000000..6143a5b81 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/domain/Address.java @@ -0,0 +1,393 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.address.domain; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.Locale; +import java.util.Set; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Table; + +import org.apache.fineract.infrastructure.codes.domain.CodeValue; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.portfolio.client.domain.ClientAddress; +import org.joda.time.LocalDate; +import org.joda.time.format.DateTimeFormat; +import org.joda.time.format.DateTimeFormatter; +import org.springframework.data.jpa.domain.AbstractPersistable; + +import com.google.gson.JsonObject; + +@Entity +@Table(name = "m_address") +public class Address extends AbstractPersistable { + + /* + * @OneToMany(mappedBy = "address", cascade = CascadeType.ALL) private + * List clientaddress = new ArrayList<>(); + */ + + @OneToMany(mappedBy = "address", cascade = CascadeType.ALL) + private Set clientaddress; + + @Column(name = "street") + private String street; + + @Column(name = "address_line_1") + private String addressLine1; + + @Column(name = "address_line_2") + private String addressLine2; + + @Column(name = "address_line_3") + private String addressLine3; + + @Column(name = "town_village") + private String townVillage; + + @Column(name = "city") + private String city; + + @Column(name = "county_district") + private String countyDistrict; + + @ManyToOne + @JoinColumn(name = "state_province_id") + private CodeValue stateProvince; + + @ManyToOne + @JoinColumn(name = "country_id") + private CodeValue country; + + @Column(name = "postal_code") + private String postalCode; + + @Column(name = "latitude") + private BigDecimal latitude; + + @Column(name = "longitude") + private BigDecimal longitude; + + @Column(name = "created_by") + private String createdBy; + + @Column(name = "created_on") + private Date createdOn; + + @Column(name = "updated_by") + private String updatedBy; + + @Column(name = "updated_on") + private Date updatedOn; + + private Address(final String street, final String addressLine1, final String addressLine2, + final String addressLine3, final String townVillage, final String city, final String countyDistrict, + final CodeValue stateProvince, final CodeValue country, final String postalCode, final BigDecimal latitude, + final BigDecimal longitude, final String createdBy, final LocalDate createdOn, final String updatedBy, + final LocalDate updatedOn) { + this.street = street; + this.addressLine1 = addressLine1; + this.addressLine2 = addressLine2; + this.addressLine3 = addressLine3; + this.townVillage = townVillage; + this.city = city; + this.countyDistrict = countyDistrict; + this.stateProvince = stateProvince; + this.country = country; + this.postalCode = postalCode; + this.latitude = latitude; + this.longitude = longitude; + this.createdBy = createdBy; + //this.createdOn = createdOn; + this.updatedBy = updatedBy; + //this.updatedOn = updatedOn; + + if (createdOn != null) { + this.createdOn = createdOn.toDate(); + + } + + if (updatedOn != null) { + this.updatedOn = updatedOn.toDate(); + } + + } + + public Address() { + + } + + public static Address fromJson(final JsonCommand command, final CodeValue stateProvince, final CodeValue country) { + + final String street = command.stringValueOfParameterNamed("street"); + + final String addressLine1 = command.stringValueOfParameterNamed("addressLine1"); + + final String addressLine2 = command.stringValueOfParameterNamed("addressLine2"); + + final String addressLine3 = command.stringValueOfParameterNamed("addressLine3"); + + final String townVillage = command.stringValueOfParameterNamed("townVillage"); + + final String city = command.stringValueOfParameterNamed("city"); + + final String countyDistrict = command.stringValueOfParameterNamed("countyDistrict"); + + final String postalCode = command.stringValueOfParameterNamed("postalCode"); + + final BigDecimal latitude = command.bigDecimalValueOfParameterNamed("latitude"); + + final BigDecimal longitude = command.bigDecimalValueOfParameterNamed("longitude"); + + final String createdBy = command.stringValueOfParameterNamed("createdBy"); + + final LocalDate createdOn = command.localDateValueOfParameterNamed("createdOn"); + + final String updatedBy = command.stringValueOfParameterNamed("updatedBy"); + + final LocalDate updatedOn = command.localDateValueOfParameterNamed("updatedOn"); + + + + return new Address(street, addressLine1, addressLine2, addressLine3, townVillage, city, countyDistrict, + stateProvince, country, postalCode, latitude, longitude, createdBy, createdOn, updatedBy, updatedOn); + } + + public static Address fromJsonObject(final JsonObject jsonObject, final CodeValue state_province, + final CodeValue country) { + String street = ""; + String addressLine1 = ""; + String addressLine2 = ""; + String addressLine3 = ""; + String townVillage = ""; + String city = ""; + String countyDistrict = ""; + String postalCode = ""; + BigDecimal latitude = BigDecimal.ZERO; + BigDecimal longitude = BigDecimal.ZERO; + String createdBy = ""; + Locale locale = Locale.ENGLISH; + String updatedBy = ""; + LocalDate updatedOnDate = null; + LocalDate createdOnDate = null; + + if (jsonObject.has("street")) { + street = jsonObject.get("street").getAsString(); + + } + + if (jsonObject.has("addressLine1")) { + addressLine1 = jsonObject.get("addressLine1").getAsString(); + } + if (jsonObject.has("addressLine2")) { + + addressLine2 = jsonObject.get("addressLine2").getAsString(); + } + if (jsonObject.has("addressLine3")) { + addressLine3 = jsonObject.get("addressLine3").getAsString(); + } + if (jsonObject.has("townVillage")) { + townVillage = jsonObject.get("townVillage").getAsString(); + } + if (jsonObject.has("city")) { + city = jsonObject.get("city").getAsString(); + } + if (jsonObject.has("countyDistrict")) { + countyDistrict = jsonObject.get("countyDistrict").getAsString(); + } + if (jsonObject.has("postalCode")) { + + postalCode = jsonObject.get("postalCode").getAsString(); + } + if (jsonObject.has("latitude")) { + + latitude = jsonObject.get("latitude").getAsBigDecimal(); + } + if (jsonObject.has("longitude")) { + + longitude = jsonObject.get("longitude").getAsBigDecimal(); + } + + if (jsonObject.has("createdBy")) { + createdBy = jsonObject.get("createdBy").getAsString(); + } + if (jsonObject.has("createdOn")) { + String createdOn = jsonObject.get("createdOn").getAsString(); + DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd"); + createdOnDate = LocalDate.parse(createdOn, formatter); + + } + if (jsonObject.has("updatedBy")) { + updatedBy = jsonObject.get("updatedBy").getAsString(); + } + if (jsonObject.has("updatedOn")) { + String updatedOn = jsonObject.get("updatedOn").getAsString(); + DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd"); + updatedOnDate = LocalDate.parse(updatedOn, formatter); + } + + return new Address(street, addressLine1, addressLine2, addressLine3, townVillage, city, countyDistrict, + state_province, country, postalCode, latitude, longitude, createdBy, createdOnDate, updatedBy, + updatedOnDate); + } + + public Set getClientaddress() { + return this.clientaddress; + } + + public void setClientaddress(Set clientaddress) { + this.clientaddress = clientaddress; + } + + public String getStreet() { + return this.street; + } + + public void setStreet(String street) { + this.street = street; + } + + public String getAddressLine1() { + return this.addressLine1; + } + + public void setAddressLine1(String addressLine1) { + this.addressLine1 = addressLine1; + } + + public String getAddressLine2() { + return this.addressLine2; + } + + public void setAddressLine2(String addressLine2) { + this.addressLine2 = addressLine2; + } + + public String getAddressLine3() { + return this.addressLine3; + } + + public void setAddressLine3(String addressLine3) { + this.addressLine3 = addressLine3; + } + + public String getTownVillage() { + return this.townVillage; + } + + public void setTownVillage(String townVillage) { + this.townVillage = townVillage; + } + + public String getCity() { + return this.city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getCountyDistrict() { + return this.countyDistrict; + } + + public void setCountyDistrict(String countyDistrict) { + this.countyDistrict = countyDistrict; + } + + public CodeValue getStateProvince() { + return this.stateProvince; + } + + public void setStateProvince(CodeValue stateProvince) { + this.stateProvince = stateProvince; + } + + public CodeValue getCountry() { + return this.country; + } + + public void setCountry(CodeValue country) { + this.country = country; + } + + public String getPostalCode() { + return this.postalCode; + } + + public void setPostalCode(String postalCode) { + this.postalCode = postalCode; + } + + public BigDecimal getLatitude() { + return this.latitude; + } + + public void setLatitude(BigDecimal latitude) { + this.latitude = latitude; + } + + public BigDecimal getLongitude() { + return this.longitude; + } + + public void setLongitude(BigDecimal longitude) { + this.longitude = longitude; + } + + public String getCreatedBy() { + return this.createdBy; + } + + public void setCreatedBy(String createdBy) { + this.createdBy = createdBy; + } + + public Date getCreatedOn() { + return this.createdOn; + } + + public void setCreatedOn(LocalDate createdOn) { + this.createdOn = createdOn.toDate(); + } + + public String getUpdatedBy() { + return this.updatedBy; + } + + public void setUpdatedBy(String updatedBy) { + this.updatedBy = updatedBy; + } + + public Date getUpdatedOn() { + return this.updatedOn; + } + + public void setUpdatedOn(LocalDate updatedOn) { + this.updatedOn = updatedOn.toDate();; + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/domain/AddressRepository.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/domain/AddressRepository.java new file mode 100644 index 000000000..40870020f --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/domain/AddressRepository.java @@ -0,0 +1,26 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.address.domain; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +public interface AddressRepository extends JpaRepository, JpaSpecificationExecutor
{ + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/domain/FieldConfiguration.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/domain/FieldConfiguration.java new file mode 100644 index 000000000..8afcb93c4 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/domain/FieldConfiguration.java @@ -0,0 +1,59 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.address.domain; + +import javax.persistence.Entity; +import javax.persistence.Table; + +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.springframework.data.jpa.domain.AbstractPersistable; + +@Entity +@Table(name = "m_field_configuration") +public class FieldConfiguration extends AbstractPersistable { + + private String entity; + + private String table; + + private String field; + + private boolean is_enabled; + + public FieldConfiguration() { + + } + + private FieldConfiguration(final String entity, final String table, final String field, final boolean is_enabled) { + this.entity = entity; + this.table = table; + this.field = field; + this.is_enabled = is_enabled; + + } + + private static FieldConfiguration fromJson(final JsonCommand command) { + final String entity = command.stringValueOfParameterNamed("entity"); + final String table = command.stringValueOfParameterNamed("table"); + final String field = command.stringValueOfParameterNamed("field"); + final boolean is_enabled = command.booleanPrimitiveValueOfParameterNamed("implementationKey"); + + return new FieldConfiguration(entity, table, field, is_enabled); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/domain/FieldConfigurationRepository.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/domain/FieldConfigurationRepository.java new file mode 100644 index 000000000..070373c74 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/domain/FieldConfigurationRepository.java @@ -0,0 +1,27 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.address.domain; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +public interface FieldConfigurationRepository + extends JpaRepository, JpaSpecificationExecutor { + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/exception/AddressNotFoundException.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/exception/AddressNotFoundException.java new file mode 100644 index 000000000..99351925a --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/exception/AddressNotFoundException.java @@ -0,0 +1,34 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.address.exception; + +import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException; + +public class AddressNotFoundException extends AbstractPlatformResourceNotFoundException { + + public AddressNotFoundException(final long clientId) { + super("error.msg.address.client.Identifier.not.found", + "Client with client ID `" + clientId + "` is not mapped with any address", clientId); + } + + public AddressNotFoundException(final long clientId, final long addressTypeId) { + super("error.msg.address.client.addresstype.not.found", + "Client with client ID`" + clientId + "` does not have address" + " type with id", addressTypeId); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/serialization/AddressCommandFromApiJsonDeserializer.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/serialization/AddressCommandFromApiJsonDeserializer.java new file mode 100644 index 000000000..dd054e1ec --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/serialization/AddressCommandFromApiJsonDeserializer.java @@ -0,0 +1,272 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.address.serialization; + +import java.lang.reflect.Type; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.lang.StringUtils; +import org.apache.fineract.infrastructure.core.data.ApiParameterError; +import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder; +import org.apache.fineract.infrastructure.core.exception.InvalidJsonException; +import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; +import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; +import org.apache.fineract.portfolio.address.data.FieldConfigurationData; +import org.apache.fineract.portfolio.address.service.FieldConfigurationReadPlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.google.gson.JsonElement; +import com.google.gson.reflect.TypeToken; + +@Component +public class AddressCommandFromApiJsonDeserializer { + private final FromJsonHelper fromApiJsonHelper; + private final FieldConfigurationReadPlatformService readservice; + + @Autowired + public AddressCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper, + final FieldConfigurationReadPlatformService readservice) { + this.fromApiJsonHelper = fromApiJsonHelper; + this.readservice = readservice; + } + + public void validateForUpdate(final String json) { + validate(json, false); + } + + public void validateForCreate(final String json, final boolean fromNewClient) { + validate(json, fromNewClient); + } + + public void validate(final String json, final boolean fromNewClient) { + if (StringUtils.isBlank(json)) { + throw new InvalidJsonException(); + } + + final Type typeOfMap = new TypeToken>() { + }.getType(); + + final List dataValidationErrors = new ArrayList<>(); + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) + .resource("Address"); + + final JsonElement element = this.fromApiJsonHelper.parse(json); + Set supportedParameters = new HashSet<>(); + + final List configurationData = new ArrayList<>( + this.readservice.retrieveFieldConfigurationList("ADDRESS")); + final List enabledFieldList = new ArrayList<>(); + + final Map madatoryFieldsMap = new HashMap(); + final Map enabledFieldsMap = new HashMap(); + final Map regexFieldsMap = new HashMap(); + + // validate the json fields from the configuration data fields + + for (final FieldConfigurationData data : configurationData) { + madatoryFieldsMap.put(data.getField(), data.isIs_mandatory()); + enabledFieldsMap.put(data.getField(), data.isIs_enabled()); + regexFieldsMap.put(data.getField(), data.getValidation_regex()); + if (data.isIs_enabled()) { + enabledFieldList.add(data.getField()); + } + } + if (fromNewClient) { + + enabledFieldList.add("addressTypeId"); + enabledFieldList.add("locale"); + enabledFieldList.add("dateFormat"); + supportedParameters = new HashSet<>(enabledFieldList); + // enabledFieldList.add("address"); + + madatoryFieldsMap.put("addressTypeId", true); + + } + if (!fromNewClient) { + enabledFieldList.add("locale"); + enabledFieldList.add("dateFormat"); + enabledFieldList.add("addressId"); + madatoryFieldsMap.put("addressId", true); + supportedParameters = new HashSet<>(enabledFieldList); + } + // final Set supportedParameters = new + // HashSet<>(enabledFieldList); + this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters); + + final String street = this.fromApiJsonHelper.extractStringNamed("street", element); + + if (enabledFieldsMap.get("street")) { + if (madatoryFieldsMap.get("street") && fromNewClient) { + + baseDataValidator.reset().parameter("street").value(street).notBlank(); + + } + if (!regexFieldsMap.get("street").isEmpty()) { + baseDataValidator.reset().parameter("street").value(street) + .matchesRegularExpression(regexFieldsMap.get("street")); + } + + } + final String addressLine1 = this.fromApiJsonHelper.extractStringNamed("addressLine1", element); + if (enabledFieldsMap.get("addressLine1")) { + if (madatoryFieldsMap.get("addressLine1") && fromNewClient) { + baseDataValidator.reset().parameter("addressLine1").value(addressLine1).notBlank(); + } + if (!regexFieldsMap.get("addressLine1").isEmpty()) { + baseDataValidator.reset().parameter("addressLine1").value(addressLine1) + .matchesRegularExpression(regexFieldsMap.get("addressLine1")); + } + + } + final String addressLine2 = this.fromApiJsonHelper.extractStringNamed("addressLine2", element); + if (enabledFieldsMap.get("addressLine2")) { + if (madatoryFieldsMap.get("addressLine2") && fromNewClient) { + baseDataValidator.reset().parameter("addressLine2").value(addressLine2).notBlank(); + } + if (!regexFieldsMap.get("addressLine2").isEmpty()) { + baseDataValidator.reset().parameter("addressLine2").value(addressLine2) + .matchesRegularExpression(regexFieldsMap.get("addressLine2")); + } + } + final String addressLine3 = this.fromApiJsonHelper.extractStringNamed("addressLine3", element); + if (enabledFieldsMap.get("addressLine3")) { + if (madatoryFieldsMap.get("addressLine3") && fromNewClient) { + baseDataValidator.reset().parameter("addressLine3").value(addressLine3).notBlank(); + } + if (!regexFieldsMap.get("addressLine3").isEmpty()) { + baseDataValidator.reset().parameter("addressLine3").value(addressLine3) + .matchesRegularExpression(regexFieldsMap.get("addressLine3")); + } + } + final String townVillage = this.fromApiJsonHelper.extractStringNamed("townVillage", element); + if (enabledFieldsMap.get("townVillage")) { + if (madatoryFieldsMap.get("townVillage") && fromNewClient) { + baseDataValidator.reset().parameter("townVillage").value(townVillage).notBlank(); + } + if (!regexFieldsMap.get("townVillage").isEmpty()) { + baseDataValidator.reset().parameter("townVillage").value(townVillage) + .matchesRegularExpression(regexFieldsMap.get("townVillage")); + } + } + final String city = this.fromApiJsonHelper.extractStringNamed("city", element); + + if (enabledFieldsMap.get("city")) { + if (madatoryFieldsMap.get("city") && fromNewClient) { + baseDataValidator.reset().parameter("city").value(city).notBlank(); + } + if (!regexFieldsMap.get("city").isEmpty()) { + baseDataValidator.reset().parameter("city").value(city) + .matchesRegularExpression(regexFieldsMap.get("city")); + } + } + final String countyDistrict = this.fromApiJsonHelper.extractStringNamed("countyDistrict", element); + if (enabledFieldsMap.get("countyDistrict")) { + if (madatoryFieldsMap.get("countyDistrict") && fromNewClient) { + baseDataValidator.reset().parameter("countyDistrict").value(countyDistrict).notBlank(); + } + if (!regexFieldsMap.get("countyDistrict").isEmpty()) { + baseDataValidator.reset().parameter("countyDistrict").value(countyDistrict) + .matchesRegularExpression(regexFieldsMap.get("countyDistrict")); + } + } + + if (this.fromApiJsonHelper.extractLongNamed("stateProvinceId", element) != null) { + + final long stateProvinceId = this.fromApiJsonHelper.extractLongNamed("stateProvinceId", element); + if (enabledFieldsMap.get("stateProvinceId")) { + if (madatoryFieldsMap.get("stateProvinceId") && fromNewClient) { + baseDataValidator.reset().parameter("stateProvinceId").value(stateProvinceId).notBlank(); + } + if (!regexFieldsMap.get("stateProvinceId").isEmpty()) { + baseDataValidator.reset().parameter("stateProvinceId").value(stateProvinceId) + .matchesRegularExpression(regexFieldsMap.get("stateProvinceId")); + } + } + } + + if (this.fromApiJsonHelper.extractLongNamed("countryId", element) != null) { + final long countryId = this.fromApiJsonHelper.extractLongNamed("countryId", element); + if (enabledFieldsMap.get("countryId")) { + if (madatoryFieldsMap.get("countryId") && fromNewClient) { + baseDataValidator.reset().parameter("countryId").value(countryId).notBlank(); + } + if (!regexFieldsMap.get("countryId").isEmpty()) { + baseDataValidator.reset().parameter("countryId").value(countryId) + .matchesRegularExpression(regexFieldsMap.get("countryId")); + } + } + } + + final String postalCode = this.fromApiJsonHelper.extractStringNamed("postalCode", element); + if (enabledFieldsMap.get("postalCode")) { + if (madatoryFieldsMap.get("postalCode") && fromNewClient) { + baseDataValidator.reset().parameter("postalCode").value(postalCode).notBlank(); + } + if (!regexFieldsMap.get("postalCode").isEmpty()) { + baseDataValidator.reset().parameter("postalCode").value(postalCode) + .matchesRegularExpression(regexFieldsMap.get("postalCode")); + } + } + + if (this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("latitude", element) != null) { + final BigDecimal latitude = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("latitude", element); + if (enabledFieldsMap.get("latitude")) { + if (madatoryFieldsMap.get("latitude") && fromNewClient) { + baseDataValidator.reset().parameter("latitude").value(latitude).notBlank(); + } + if (!regexFieldsMap.get("latitude").isEmpty()) { + baseDataValidator.reset().parameter("latitude").value(latitude) + .matchesRegularExpression(regexFieldsMap.get("latitude")); + } + } + } + + if (this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("longitude", element) != null) { + final BigDecimal longitude = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("longitude", element); + if (enabledFieldsMap.get("longitude")) { + if (madatoryFieldsMap.get("longitude") && fromNewClient) { + baseDataValidator.reset().parameter("longitude").value(longitude).notBlank(); + } + if (!regexFieldsMap.get("longitude").isEmpty()) { + baseDataValidator.reset().parameter("longitude").value(longitude) + .matchesRegularExpression(regexFieldsMap.get("longitude")); + } + } + } + + throwExceptionIfValidationWarningsExist(dataValidationErrors); + + } + + private void throwExceptionIfValidationWarningsExist(final List dataValidationErrors) { + if (!dataValidationErrors.isEmpty()) { + throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", + "Validation errors exist.", dataValidationErrors); + } + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/service/AddressReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/service/AddressReadPlatformService.java new file mode 100644 index 000000000..0a45e7aa8 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/service/AddressReadPlatformService.java @@ -0,0 +1,37 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.address.service; + +import java.util.Collection; + +import org.apache.fineract.portfolio.address.data.AddressData; + +public interface AddressReadPlatformService { + public Collection retrieveAddressFields(long clientid); + + public Collection retrieveAllClientAddress(long clientid); + + public Collection retrieveAddressbyType(long clientid, long typeid); + + Collection retrieveAddressbyTypeAndStatus(long clientid, long typeid, String status); + + Collection retrieveAddressbyStatus(long clientid, String status); + + AddressData retrieveTemplate(); +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/service/AddressReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/service/AddressReadPlatformServiceImpl.java new file mode 100644 index 000000000..dc88318e6 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/service/AddressReadPlatformServiceImpl.java @@ -0,0 +1,246 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.address.service; + +import java.math.BigDecimal; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.List; + +import org.apache.fineract.infrastructure.codes.data.CodeValueData; +import org.apache.fineract.infrastructure.codes.service.CodeValueReadPlatformService; +import org.apache.fineract.infrastructure.core.service.RoutingDataSource; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.apache.fineract.portfolio.address.data.AddressData; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Service; + +@Service +public class AddressReadPlatformServiceImpl implements AddressReadPlatformService { + + private final JdbcTemplate jdbcTemplate; + private final PlatformSecurityContext context; + private final CodeValueReadPlatformService readService; + + @Autowired + public AddressReadPlatformServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource, + final CodeValueReadPlatformService readService) { + this.context = context; + this.jdbcTemplate = new JdbcTemplate(dataSource); + this.readService = readService; + } + + private static final class AddFieldsMapper implements RowMapper { + public String schema() { + return "addr.id as id,client.id as client_id,addr.street as street,addr.address_line_1 as address_line_1,addr.address_line_2 as address_line_2," + + "addr.address_line_3 as address_line_3,addr.town_village as town_village, addr.city as city,addr.county_district as county_district," + + "addr.state_province_id as state_province_id, addr.country_id as country_id,addr.postal_code as postal_code,addr.latitude as latitude," + + "addr.longitude as longitude,addr.created_by as created_by,addr.created_on as created_on,addr.updated_by as updated_by," + + "addr.updated_on as updated_on from m_address as addr,m_client client"; + } + + @Override + public AddressData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) + throws SQLException { + + final long addressId = rs.getLong("id"); + + final long clientId = rs.getLong("client_id"); + + final String street = rs.getString("street"); + + final String address_line_1 = rs.getString("address_line_1"); + + final String address_line_2 = rs.getString("address_line_2"); + + final String address_line_3 = rs.getString("address_line_3"); + + final String town_village = rs.getString("town_village"); + + final String city = rs.getString("city"); + + final String county_district = rs.getString("county_district"); + + final long state_province_id = rs.getLong("state_province_id"); + + final long country_id = rs.getLong("country_id"); + + final String postal_code = rs.getString("postal_code"); + + final BigDecimal latitude = rs.getBigDecimal("latitude"); + + final BigDecimal longitude = rs.getBigDecimal("longitude"); + + final String created_by = rs.getString("created_by"); + + final Date created_on = rs.getDate("created_on"); + + final String updated_by = rs.getString("updated_by"); + + final Date updated_on = rs.getDate("updated_on"); + + return AddressData.instance1(addressId, street, address_line_1, address_line_2, address_line_3, + town_village, city, county_district, state_province_id, country_id, postal_code, latitude, + longitude, created_by, created_on, updated_by, updated_on); + + } + } + + private static final class AddMapper implements RowMapper { + public String schema() { + return "cv2.code_value as addressType,ca.client_id as client_id,addr.id as id,ca.address_type_id as addresstyp,ca.is_active as is_active,addr.street as street,addr.address_line_1 as address_line_1,addr.address_line_2 as address_line_2," + + "addr.address_line_3 as address_line_3,addr.town_village as town_village, addr.city as city,addr.county_district as county_district," + + "addr.state_province_id as state_province_id,cv.code_value as state_name, addr.country_id as country_id,c.code_value as country_name,addr.postal_code as postal_code,addr.latitude as latitude," + + "addr.longitude as longitude,addr.created_by as created_by,addr.created_on as created_on,addr.updated_by as updated_by," + + "addr.updated_on as updated_on" + + " from m_address addr left join m_code_value cv on addr.state_province_id=cv.id" + + " left join m_code_value c on addr.country_id=c.id" + + " join m_client_address ca on addr.id= ca.address_id" + + " join m_code_value cv2 on ca.address_type_id=cv2.id"; + + } + + @Override + public AddressData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) + throws SQLException { + + final String addressType = rs.getString("addressType"); + final long addressId = rs.getLong("id"); + + final long client_id = rs.getLong("client_id"); + + final String street = rs.getString("street"); + + final long address_type_id = rs.getLong("addresstyp"); + + final boolean is_active = rs.getBoolean("is_active"); + + final String address_line_1 = rs.getString("address_line_1"); + + final String address_line_2 = rs.getString("address_line_2"); + + final String address_line_3 = rs.getString("address_line_3"); + + final String town_village = rs.getString("town_village"); + + final String city = rs.getString("city"); + + final String county_district = rs.getString("county_district"); + + final long state_province_id = rs.getLong("state_province_id"); + + final long country_id = rs.getLong("country_id"); + + final String country_name = rs.getString("country_name"); + + final String state_name = rs.getString("state_name"); + + final String postal_code = rs.getString("postal_code"); + + final BigDecimal latitude = rs.getBigDecimal("latitude"); + + final BigDecimal longitude = rs.getBigDecimal("longitude"); + + final String created_by = rs.getString("created_by"); + + final Date created_on = rs.getDate("created_on"); + + final String updated_by = rs.getString("updated_by"); + + final Date updated_on = rs.getDate("updated_on"); + + return AddressData.instance(addressType, client_id, addressId, address_type_id, is_active, street, + address_line_1, address_line_2, address_line_3, town_village, city, county_district, + state_province_id, country_id, state_name, country_name, postal_code, latitude, longitude, + created_by, created_on, updated_by, updated_on); + + } + } + + @Override + public Collection retrieveAddressFields(final long clientid) { + this.context.authenticatedUser(); + + final AddFieldsMapper rm = new AddFieldsMapper(); + final String sql = "select " + rm.schema() + " where client.id=?"; + + return this.jdbcTemplate.query(sql, rm, new Object[] { clientid }); + } + + @Override + public Collection retrieveAllClientAddress(final long clientid) { + this.context.authenticatedUser(); + final AddMapper rm = new AddMapper(); + final String sql = "select " + rm.schema() + " and ca.client_id=?"; + return this.jdbcTemplate.query(sql, rm, new Object[] { clientid }); + } + + @Override + public Collection retrieveAddressbyType(final long clientid, final long typeid) { + this.context.authenticatedUser(); + + final AddMapper rm = new AddMapper(); + final String sql = "select " + rm.schema() + " and ca.client_id=? and ca.address_type_id=?"; + + return this.jdbcTemplate.query(sql, rm, new Object[] { clientid, typeid }); + } + + @Override + public Collection retrieveAddressbyTypeAndStatus(final long clientid, final long typeid, + final String status) { + this.context.authenticatedUser(); + Boolean temp = false; + temp = Boolean.parseBoolean(status); + + final AddMapper rm = new AddMapper(); + final String sql = "select " + rm.schema() + " and ca.client_id=? and ca.address_type_id=? and ca.is_active=?"; + + return this.jdbcTemplate.query(sql, rm, new Object[] { clientid, typeid, temp }); + } + + @Override + public Collection retrieveAddressbyStatus(final long clientid, final String status) { + this.context.authenticatedUser(); + Boolean temp = false; + temp = Boolean.parseBoolean(status); + + final AddMapper rm = new AddMapper(); + final String sql = "select " + rm.schema() + " and ca.client_id=? and ca.is_active=?"; + + return this.jdbcTemplate.query(sql, rm, new Object[] { clientid, temp }); + } + + @Override + public AddressData retrieveTemplate() { + final List countryoptions = new ArrayList<>( + this.readService.retrieveCodeValuesByCode("COUNTRY")); + + final List StateOptions = new ArrayList<>(this.readService.retrieveCodeValuesByCode("STATES")); + + final List addressTypeOptions = new ArrayList<>( + this.readService.retrieveCodeValuesByCode("ADDRESS_TYPE")); + + return AddressData.template(countryoptions, StateOptions, addressTypeOptions); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/service/AddressWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/service/AddressWritePlatformService.java new file mode 100644 index 000000000..fa1219aab --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/service/AddressWritePlatformService.java @@ -0,0 +1,31 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.address.service; + +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.client.domain.Client; + +public interface AddressWritePlatformService { + CommandProcessingResult addClientAddress(Long clientId, Long addressTypeId, JsonCommand command); + + CommandProcessingResult addNewClientAddress(Client client, JsonCommand command); + + CommandProcessingResult updateClientAddress(Long clientId, JsonCommand command); +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/service/AddressWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/service/AddressWritePlatformServiceImpl.java new file mode 100644 index 000000000..847b20d3b --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/service/AddressWritePlatformServiceImpl.java @@ -0,0 +1,284 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.address.service; + +import java.math.BigDecimal; + +import org.apache.fineract.infrastructure.codes.domain.CodeValue; +import org.apache.fineract.infrastructure.codes.domain.CodeValueRepository; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.apache.fineract.portfolio.address.domain.Address; +import org.apache.fineract.portfolio.address.domain.AddressRepository; +import org.apache.fineract.portfolio.address.serialization.AddressCommandFromApiJsonDeserializer; +import org.apache.fineract.portfolio.client.domain.Client; +import org.apache.fineract.portfolio.client.domain.ClientAddress; +import org.apache.fineract.portfolio.client.domain.ClientAddressRepository; +import org.apache.fineract.portfolio.client.domain.ClientAddressRepositoryWrapper; +import org.apache.fineract.portfolio.client.domain.ClientRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; + +@Service +public class AddressWritePlatformServiceImpl implements AddressWritePlatformService { + private final PlatformSecurityContext context; + private final CodeValueRepository codeValueRepository; + private final ClientAddressRepository clientAddressRepository; + private final ClientRepository clientRepository; + private final AddressRepository addressRepository; + private final ClientAddressRepositoryWrapper clientAddressRepositoryWrapper; + private final AddressCommandFromApiJsonDeserializer fromApiJsonDeserializer; + + @Autowired + public AddressWritePlatformServiceImpl(final PlatformSecurityContext context, + final CodeValueRepository codeValueRepository, final ClientAddressRepository clientAddressRepository, + final ClientRepository clientRepository, final AddressRepository addressRepository, + final ClientAddressRepositoryWrapper clientAddressRepositoryWrapper, + final AddressCommandFromApiJsonDeserializer fromApiJsonDeserializer) { + this.context = context; + this.codeValueRepository = codeValueRepository; + this.clientAddressRepository = clientAddressRepository; + this.clientRepository = clientRepository; + this.addressRepository = addressRepository; + this.clientAddressRepositoryWrapper = clientAddressRepositoryWrapper; + this.fromApiJsonDeserializer = fromApiJsonDeserializer; + + } + + @Override + public CommandProcessingResult addClientAddress(final Long clientId, final Long addressTypeId, + final JsonCommand command) { + CodeValue stateIdobj = null; + CodeValue countryIdObj = null; + long stateId; + long countryId; + + this.context.authenticatedUser(); + this.fromApiJsonDeserializer.validateForCreate(command.json(), true); + + System.out.println("request " + command.json()); + + if (command.longValueOfParameterNamed("stateProvinceId") != null) { + stateId = command.longValueOfParameterNamed("stateProvinceId"); + stateIdobj = this.codeValueRepository.getOne(stateId); + } + + if (command.longValueOfParameterNamed("countryId") != null) { + countryId = command.longValueOfParameterNamed("countryId"); + countryIdObj = this.codeValueRepository.getOne(countryId); + } + + final CodeValue addressTypeIdObj = this.codeValueRepository.getOne(addressTypeId); + + final Address add = Address.fromJson(command, stateIdobj, countryIdObj); + this.addressRepository.save(add); + final Long addressid = add.getId(); + final Address addobj = this.addressRepository.getOne(addressid); + + final Client client = this.clientRepository.getOne(clientId); + final boolean isActive = command.booleanPrimitiveValueOfParameterNamed("isActive"); + + final ClientAddress clientAddressobj = ClientAddress.fromJson(isActive, client, addobj, addressTypeIdObj); + this.clientAddressRepository.save(clientAddressobj); + + return new CommandProcessingResultBuilder().withCommandId(command.commandId()) + .withEntityId(clientAddressobj.getId()).build(); + } + + // following method is used for adding multiple addresses while creating new + // client + + @Override + public CommandProcessingResult addNewClientAddress(final Client client, final JsonCommand command) { + CodeValue stateIdobj = null; + CodeValue countryIdObj = null; + long stateId; + long countryId; + ClientAddress clientAddressobj = new ClientAddress(); + final JsonArray addressArray = command.arrayOfParameterNamed("address"); + + for (int i = 0; i < addressArray.size(); i++) { + final JsonObject jsonObject = addressArray.get(i).getAsJsonObject(); + + // validate every address + this.fromApiJsonDeserializer.validateForCreate(jsonObject.toString(), true); + + if (jsonObject.get("stateProvinceId") != null) { + stateId = jsonObject.get("stateProvinceId").getAsLong(); + stateIdobj = this.codeValueRepository.getOne(stateId); + } + + if (jsonObject.get("countryId") != null) { + countryId = jsonObject.get("countryId").getAsLong(); + countryIdObj = this.codeValueRepository.getOne(countryId); + } + + final long addressTypeId = jsonObject.get("addressTypeId").getAsLong(); + final CodeValue addressTypeIdObj = this.codeValueRepository.getOne(addressTypeId); + + final Address add = Address.fromJsonObject(jsonObject, stateIdobj, countryIdObj); + this.addressRepository.save(add); + final Long addressid = add.getId(); + final Address addobj = this.addressRepository.getOne(addressid); + + final boolean isActive = jsonObject.get("isActive").getAsBoolean(); + + clientAddressobj = ClientAddress.fromJson(isActive, client, addobj, addressTypeIdObj); + this.clientAddressRepository.save(clientAddressobj); + + } + + return new CommandProcessingResultBuilder().withCommandId(command.commandId()) + .withEntityId(clientAddressobj.getId()).build(); + } + + @Override + public CommandProcessingResult updateClientAddress(final Long clientId, final JsonCommand command) { + this.context.authenticatedUser(); + + long stateId; + + long countryId; + + CodeValue stateIdobj; + + CodeValue countryIdObj; + + boolean is_address_update = false; + + this.fromApiJsonDeserializer.validateForUpdate(command.json()); + + final long addressId = command.longValueOfParameterNamed("addressId"); + + final ClientAddress clientAddressObj = this.clientAddressRepositoryWrapper + .findOneByClientIdAndAddressId(clientId, addressId); + + final Address addobj = this.addressRepository.getOne(addressId); + + if (!(command.stringValueOfParameterNamed("street").isEmpty())) { + + is_address_update = true; + final String street = command.stringValueOfParameterNamed("street"); + addobj.setStreet(street); + } + + if (!(command.stringValueOfParameterNamed("addressLine1").isEmpty())) { + + is_address_update = true; + final String addressLine1 = command.stringValueOfParameterNamed("addressLine1"); + addobj.setAddressLine1(addressLine1); + + } + + if (!(command.stringValueOfParameterNamed("addressLine2").isEmpty())) { + + is_address_update = true; + final String addressLine2 = command.stringValueOfParameterNamed("addressLine2"); + addobj.setAddressLine2(addressLine2); + + } + + if (!(command.stringValueOfParameterNamed("addressLine3").isEmpty())) { + is_address_update = true; + final String addressLine3 = command.stringValueOfParameterNamed("addressLine3"); + addobj.setAddressLine3(addressLine3); + + } + + if (!(command.stringValueOfParameterNamed("townVillage").isEmpty())) { + + is_address_update = true; + final String townVillage = command.stringValueOfParameterNamed("townVillage"); + addobj.setTownVillage(townVillage); + } + + if (!(command.stringValueOfParameterNamed("city").isEmpty())) { + is_address_update = true; + final String city = command.stringValueOfParameterNamed("city"); + addobj.setCity(city); + } + + if (!(command.stringValueOfParameterNamed("countyDistrict").isEmpty())) { + is_address_update = true; + final String countyDistrict = command.stringValueOfParameterNamed("countyDistrict"); + addobj.setCountyDistrict(countyDistrict); + } + + if ((command.longValueOfParameterNamed("stateProvinceId") != null)) { + if ((command.longValueOfParameterNamed("stateProvinceId") != 0)) { + is_address_update = true; + stateId = command.longValueOfParameterNamed("stateProvinceId"); + stateIdobj = this.codeValueRepository.getOne(stateId); + addobj.setStateProvince(stateIdobj); + } + + } + if ((command.longValueOfParameterNamed("countryId") != null)) { + if ((command.longValueOfParameterNamed("countryId") != 0)) { + is_address_update = true; + countryId = command.longValueOfParameterNamed("countryId"); + countryIdObj = this.codeValueRepository.getOne(countryId); + addobj.setCountry(countryIdObj); + } + + } + + if (!(command.stringValueOfParameterNamed("postalCode").isEmpty())) { + is_address_update = true; + final String postalCode = command.stringValueOfParameterNamed("postalCode"); + addobj.setPostalCode(postalCode); + } + + if (command.bigDecimalValueOfParameterNamed("latitude") != null) { + + is_address_update = true; + final BigDecimal latitude = command.bigDecimalValueOfParameterNamed("latitude"); + + addobj.setLatitude(latitude); + } + if (command.bigDecimalValueOfParameterNamed("longitude") != null) { + is_address_update = true; + final BigDecimal longitude = command.bigDecimalValueOfParameterNamed("longitude"); + addobj.setLongitude(longitude); + + } + + if (is_address_update) { + + this.addressRepository.save(addobj); + + } + + final Boolean testActive = command.booleanPrimitiveValueOfParameterNamed("isActive"); + if (testActive != null) { + + final boolean active = command.booleanPrimitiveValueOfParameterNamed("isActive"); + clientAddressObj.setIs_active(active); + + } + + return new CommandProcessingResultBuilder().withCommandId(command.commandId()) + .withEntityId(clientAddressObj.getId()).build(); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/service/FieldConfigurationReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/service/FieldConfigurationReadPlatformService.java new file mode 100644 index 000000000..c3403f455 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/service/FieldConfigurationReadPlatformService.java @@ -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.portfolio.address.service; + +import java.util.Collection; +import java.util.List; + +import org.apache.fineract.portfolio.address.data.FieldConfigurationData; + +public interface FieldConfigurationReadPlatformService { + public Collection retrieveFieldConfiguration(String entity); + + List retrieveFieldConfigurationList(String entity); +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/service/FieldConfigurationReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/service/FieldConfigurationReadPlatformServiceImpl.java new file mode 100644 index 000000000..946a96f09 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/address/service/FieldConfigurationReadPlatformServiceImpl.java @@ -0,0 +1,89 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.address.service; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Collection; +import java.util.List; + +import org.apache.fineract.infrastructure.core.service.RoutingDataSource; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.apache.fineract.portfolio.address.data.FieldConfigurationData; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Service; + +@Service +public class FieldConfigurationReadPlatformServiceImpl implements FieldConfigurationReadPlatformService { + private final JdbcTemplate jdbcTemplate; + private final PlatformSecurityContext context; + + @Autowired + public FieldConfigurationReadPlatformServiceImpl(final PlatformSecurityContext context, + final RoutingDataSource dataSource) { + this.context = context; + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + private static final class FieldMapper implements RowMapper { + public String schema() { + return "fld.id as fieldConfigurationId,fld.entity as entity,fld.subentity as subentity,fld.field as field,fld.is_enabled as is_enabled," + + "fld.is_mandatory as is_mandatory,fld.validation_regex as validation_regex from m_field_configuration fld"; + } + + @Override + public FieldConfigurationData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) + throws SQLException { + final long fieldConfigurationId = rs.getLong("fieldConfigurationId"); + final String entity = rs.getString("entity"); + final String subentity = rs.getString("subentity"); + final String field = rs.getString("field"); + final boolean is_enabled = rs.getBoolean("is_enabled"); + final boolean is_mandatory = rs.getBoolean("is_mandatory"); + final String validation_regex = rs.getString("validation_regex"); + + return FieldConfigurationData.instance(fieldConfigurationId, entity, subentity, field, is_enabled, + is_mandatory, validation_regex); + + } + } + + @Override + public Collection retrieveFieldConfiguration(final String entity) { + this.context.authenticatedUser(); + + final FieldMapper rm = new FieldMapper(); + final String sql = "select " + rm.schema() + " where fld.entity=?"; + + return this.jdbcTemplate.query(sql, rm, new Object[] { entity }); + } + + @Override + public List retrieveFieldConfigurationList(final String entity) { + this.context.authenticatedUser(); + + final FieldMapper rm = new FieldMapper(); + final String sql = "select " + rm.schema() + " where fld.entity=?"; + + return this.jdbcTemplate.query(sql, new Object[] { entity }, rm); + + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientAddressApiResources.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientAddressApiResources.java new file mode 100644 index 000000000..67c72b4a0 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientAddressApiResources.java @@ -0,0 +1,151 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.client.api; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +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.UriInfo; + +import org.apache.fineract.commands.domain.CommandWrapper; +import org.apache.fineract.commands.service.CommandWrapperBuilder; +import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService; +import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings; +import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.apache.fineract.portfolio.address.data.AddressData; +import org.apache.fineract.portfolio.address.service.AddressReadPlatformServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +@Path("/client") +@Component +@Scope("singleton") +public class ClientAddressApiResources { + private final Set RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList("addressId", "street", + "addressLine1", "addressLine2", "addressLine3", "townVillage", "city", "countyDistrict", "stateProvinceId", + "countryId", "postalCode", "latitude", "longitude", "createdBy", "createdOn", "updatedBy", "updatedOn", + "clientAddressId", "client_id", "address_id", "address_type_id", "isActive", "fieldConfigurationId", + "entity", "table", "field", "is_enabled", "is_mandatory", "validation_regex")); + private final String resourceNameForPermissions = "Address"; + private final PlatformSecurityContext context; + private final AddressReadPlatformServiceImpl readPlatformService; + private final DefaultToApiJsonSerializer toApiJsonSerializer; + private final ApiRequestParameterHelper apiRequestParameterHelper; + private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; + + @Autowired + public ClientAddressApiResources(final PlatformSecurityContext context, + final AddressReadPlatformServiceImpl readPlatformService, + final DefaultToApiJsonSerializer toApiJsonSerializer, + final ApiRequestParameterHelper apiRequestParameterHelper, + final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) { + this.context = context; + this.readPlatformService = readPlatformService; + this.toApiJsonSerializer = toApiJsonSerializer; + this.apiRequestParameterHelper = apiRequestParameterHelper; + this.commandsSourceWritePlatformService = commandsSourceWritePlatformService; + } + + @GET + @Path("addresses/template") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String getAddressesTemplate(@Context final UriInfo uriInfo) { + this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions); + + final AddressData template = this.readPlatformService.retrieveTemplate(); + + final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper + .process(uriInfo.getQueryParameters()); + return this.toApiJsonSerializer.serialize(settings, template, this.RESPONSE_DATA_PARAMETERS); + + } + + @GET + @Path("/{clientid}/addresses") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String getAddresses(@QueryParam("status") final String status, @QueryParam("type") final long addressTypeId, + @PathParam("clientid") final long clientid, @Context final UriInfo uriInfo) { + Collection address; + + this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions); + + if (addressTypeId == 0 && status == null) { + address = this.readPlatformService.retrieveAllClientAddress(clientid); + } else if (addressTypeId != 0 && status == null) { + address = this.readPlatformService.retrieveAddressbyType(clientid, addressTypeId); + } else if (addressTypeId != 0 && status != null) { + address = this.readPlatformService.retrieveAddressbyTypeAndStatus(clientid, addressTypeId, status); + } else { + address = this.readPlatformService.retrieveAddressbyStatus(clientid, status); + } + + final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper + .process(uriInfo.getQueryParameters()); + return this.toApiJsonSerializer.serialize(settings, address, this.RESPONSE_DATA_PARAMETERS); + + } + + @POST + @Path("/{clientid}/addresses") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String AddClientAddress(@QueryParam("type") final long addressTypeId, + @PathParam("clientid") final long clientid, final String apiRequestBodyAsJson) { + + final CommandWrapper commandRequest = new CommandWrapperBuilder().addClientAddress(clientid, addressTypeId) + .withJson(apiRequestBodyAsJson).build(); + + final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + + return this.toApiJsonSerializer.serialize(result); + } + + @PUT + @Path("/{clientid}/addresses") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String UpdateClientAddress(@PathParam("clientid") final long clientid, final String apiRequestBodyAsJson) { + + final CommandWrapper commandRequest = new CommandWrapperBuilder().updateClientAddress(clientid) + .withJson(apiRequestBodyAsJson).build(); + + final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + + return this.toApiJsonSerializer.serialize(result); + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientApiConstants.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientApiConstants.java index 861358a88..fb07c0ede 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientApiConstants.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientApiConstants.java @@ -68,6 +68,7 @@ public class ClientApiConstants { // general public static final String localeParamName = "locale"; public static final String dateFormatParamName = "dateFormat"; + public static final String address = "address"; public static final String CLIENT_TYPE_INDIVIDUAL = "Individual"; @@ -175,14 +176,14 @@ public class ClientApiConstants { public static final String staffOptionsParamName = "staffOptions"; public static final Set CLIENT_CREATE_REQUEST_DATA_PARAMETERS = new HashSet<>( - Arrays.asList(localeParamName, dateFormatParamName, groupIdParamName, accountNoParamName, externalIdParamName, + Arrays.asList(address,localeParamName, dateFormatParamName, groupIdParamName, accountNoParamName, externalIdParamName, mobileNoParamName, firstnameParamName, middlenameParamName, lastnameParamName, fullnameParamName, officeIdParamName, activeParamName, activationDateParamName, staffIdParamName, submittedOnDateParamName, savingsProductIdParamName, dateOfBirthParamName, genderIdParamName, clientTypeIdParamName, clientClassificationIdParamName, clientNonPersonDetailsParamName, displaynameParamName, legalFormIdParamName)); public static final Set CLIENT_NON_PERSON_CREATE_REQUEST_DATA_PARAMETERS = new HashSet<>( - Arrays.asList(localeParamName, dateFormatParamName, incorpNumberParamName, remarksParamName, incorpValidityTillParamName, + Arrays.asList(address,localeParamName, dateFormatParamName, incorpNumberParamName, remarksParamName, incorpValidityTillParamName, constitutionIdParamName, mainBusinessLineIdParamName)); public static final Set CLIENT_UPDATE_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName, diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientData.java index 1984417df..bcba0fc8b 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientData.java @@ -29,6 +29,7 @@ import org.apache.fineract.infrastructure.codes.data.CodeValueData; import org.apache.fineract.infrastructure.core.data.EnumOptionData; import org.apache.fineract.organisation.office.data.OfficeData; import org.apache.fineract.organisation.staff.data.StaffData; +import org.apache.fineract.portfolio.address.data.AddressData; import org.apache.fineract.portfolio.group.data.GroupGeneralData; import org.apache.fineract.portfolio.savings.data.SavingsAccountData; import org.apache.fineract.portfolio.savings.data.SavingsProductData; @@ -95,13 +96,17 @@ final public class ClientData implements Comparable { private final List clientLegalFormOptions; private final ClientNonPersonData clientNonPersonDetails; + + private final AddressData address; + + private final Boolean isAddressEnabled; public static ClientData template(final Long officeId, final LocalDate joinedDate, final Collection officeOptions, final Collection staffOptions, final Collection narrations, final Collection genderOptions, final Collection savingProductOptions, final Collection clientTypeOptions, final Collection clientClassificationOptions, final Collection clientNonPersonConstitutionOptions, final Collection clientNonPersonMainBusinessLineOptions, - final List clientLegalFormOptions) { + final List clientLegalFormOptions, final AddressData address,final Boolean isAddressEnabled) { final String accountNo = null; final EnumOptionData status = null; final CodeValueData subStatus = null; @@ -136,7 +141,7 @@ final public class ClientData implements Comparable { staffName, officeOptions, groups, staffOptions, narrations, genderOptions, timeline, savingProductOptions, savingsProductId, savingsProductName, savingsAccountId, savingAccountOptions, clientType, clientClassification, clientTypeOptions, clientClassificationOptions, clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, - clientNonPersonDetails, clientLegalFormOptions, legalForm); + clientNonPersonDetails, clientLegalFormOptions, legalForm,address, isAddressEnabled); } @@ -151,7 +156,7 @@ final public class ClientData implements Comparable { clientData.savingsProductName, clientData.savingsAccountId, clientData.savingAccountOptions, clientData.clientType, clientData.clientClassification, templateData.clientTypeOptions, templateData.clientClassificationOptions, templateData.clientNonPersonConstitutionOptions, templateData.clientNonPersonMainBusinessLineOptions, clientData.clientNonPersonDetails, - templateData.clientLegalFormOptions, clientData.legalForm); + templateData.clientLegalFormOptions, clientData.legalForm, clientData.address,clientData.isAddressEnabled); } @@ -167,7 +172,7 @@ final public class ClientData implements Comparable { clientData.savingsProductName, clientData.savingsAccountId, savingAccountOptions, clientData.clientType, clientData.clientClassification, clientData.clientTypeOptions, clientData.clientClassificationOptions, clientData.clientNonPersonConstitutionOptions, clientData.clientNonPersonMainBusinessLineOptions, clientData.clientNonPersonDetails, - clientData.clientLegalFormOptions, clientData.legalForm); + clientData.clientLegalFormOptions, clientData.legalForm,clientData.address, clientData.isAddressEnabled); } @@ -180,7 +185,8 @@ final public class ClientData implements Comparable { clientData.savingProductOptions, clientData.savingsProductId, clientData.savingsProductName, clientData.savingsAccountId, clientData.savingAccountOptions, clientData.clientType, clientData.clientClassification, clientData.clientTypeOptions, clientData.clientClassificationOptions, clientData.clientNonPersonConstitutionOptions, clientData.clientNonPersonMainBusinessLineOptions, - clientData.clientNonPersonDetails, clientData.clientLegalFormOptions, clientData.legalForm); + clientData.clientNonPersonDetails, clientData.clientLegalFormOptions, clientData.legalForm,clientData.address, + clientData.isAddressEnabled); } @@ -224,7 +230,7 @@ final public class ClientData implements Comparable { staffName, allowedOffices, groups, staffOptions, closureReasons, genderOptions, timeline, savingProductOptions, savingsProductId, savingsProductName, savingsAccountId, savingAccountOptions, clientType, clientClassification, clientTypeOptions, clientClassificationOptions, clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, - clientNonPerson, clientLegalFormOptions, legalForm); + clientNonPerson, clientLegalFormOptions, legalForm,null,null); } public static ClientData lookup(final Long id, final String displayName, final Long officeId, final String officeName) { @@ -270,7 +276,7 @@ final public class ClientData implements Comparable { staffName, allowedOffices, groups, staffOptions, closureReasons, genderOptions, timeline, savingProductOptions, savingsProductId, savingsProductName, savingsAccountId, savingAccountOptions, clientType, clientClassification, clientTypeOptions, clientClassificationOptions, clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, - clientNonPerson, clientLegalFormOptions, legalForm); + clientNonPerson, clientLegalFormOptions, legalForm,null,null); } @@ -298,7 +304,7 @@ final public class ClientData implements Comparable { staffName, allowedOffices, groups, staffOptions, closureReasons, genderOptions, timeline, savingProductOptions, savingsProductId, savingsProductName, savingsAccountId, null, clientType, clientClassification, clientTypeOptions, clientClassificationOptions, clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, clientNonPerson, - clientLegalFormOptions, legalForm); + clientLegalFormOptions, legalForm,null,null); } @@ -315,7 +321,7 @@ final public class ClientData implements Comparable { final CodeValueData clientClassification, final Collection clientTypeOptions, final Collection clientClassificationOptions, final Collection clientNonPersonConstitutionOptions, final Collection clientNonPersonMainBusinessLineOptions, final ClientNonPersonData clientNonPerson, - final List clientLegalFormOptions, final EnumOptionData legalForm) { + final List clientLegalFormOptions, final EnumOptionData legalForm,final AddressData address, final Boolean isAddressEnabled) { this.accountNo = accountNo; this.status = status; if (status != null) { @@ -374,6 +380,9 @@ final public class ClientData implements Comparable { this.savingAccountOptions = savingAccountOptions; this.legalForm = legalForm; this.clientNonPersonDetails = clientNonPerson; + + this.address = address; + this.isAddressEnabled = isAddressEnabled; } @@ -455,4 +464,8 @@ final public class ClientData implements Comparable { public LocalDate getActivationDate() { return this.activationDate; } + + public Boolean getIsAddressEnabled() { + return this.isAddressEnabled; + } } \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientAddress.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientAddress.java new file mode 100644 index 000000000..1dbe0b903 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientAddress.java @@ -0,0 +1,100 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.client.domain; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; + +import org.apache.fineract.infrastructure.codes.domain.CodeValue; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.portfolio.address.domain.Address; +import org.springframework.data.jpa.domain.AbstractPersistable; + +@Entity +@Table(name = "m_client_address") +public class ClientAddress extends AbstractPersistable { + + @ManyToOne + private Client client; + + @ManyToOne + private Address address; + + @ManyToOne + @JoinColumn(name = "address_type_id") + private CodeValue addressType; + + @Column(name = "is_active") + private boolean isActive; + + private ClientAddress(final Client client, final Address address, final CodeValue addressType, + final boolean isActive) { + this.client = client; + this.address = address; + this.addressType = addressType; + this.isActive = isActive; + + } + + public ClientAddress() { + + } + + public static ClientAddress fromJson(final boolean isActive, final Client client, final Address address, + final CodeValue address_type) { + + return new ClientAddress(client, address, address_type, isActive); + } + + public Client getClient() { + return this.client; + } + + public Address getAddress() { + return this.address; + } + + public CodeValue getAddressType() { + return this.addressType; + } + + public void setAddressType(final CodeValue addressType) { + this.addressType = addressType; + } + + public boolean isIs_active() { + return this.isActive; + } + + public void setClient(final Client client) { + this.client = client; + } + + public void setAddress(final Address address) { + this.address = address; + } + + public void setIs_active(final boolean isActive) { + this.isActive = isActive; + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientAddressRepository.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientAddressRepository.java new file mode 100644 index 000000000..984b2ea3a --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientAddressRepository.java @@ -0,0 +1,35 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.client.domain; + +import org.apache.fineract.infrastructure.codes.domain.CodeValue; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +public interface ClientAddressRepository + extends JpaRepository, JpaSpecificationExecutor { + ClientAddress findByClientId(String clientId); + + // ClientAddress findByAddressId(long addressId); + + ClientAddress findByClientIdAndAddressTypeAndIsActive(final long clientId, final CodeValue addressTypeId, + final boolean isActive); + + ClientAddress findByClientIdAndAddressId(final long clientId, final long addressId); +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientAddressRepositoryWrapper.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientAddressRepositoryWrapper.java new file mode 100644 index 000000000..fbe7cd2a8 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientAddressRepositoryWrapper.java @@ -0,0 +1,50 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.client.domain; + +import org.apache.fineract.infrastructure.codes.domain.CodeValue; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class ClientAddressRepositoryWrapper { + private final ClientAddressRepository clientAddressRepository; + + @Autowired + public ClientAddressRepositoryWrapper(final ClientAddressRepository clientAddressRepository) { + this.clientAddressRepository = clientAddressRepository; + } + + public ClientAddress findOneByClientIdAndAddressTypeAndIsActive(final long clientId, final CodeValue addressType, + final boolean isActive) { + final ClientAddress clientAddress = this.clientAddressRepository + .findByClientIdAndAddressTypeAndIsActive(clientId, addressType, isActive); + // if (clientAddress == null) { throw new + // AddressNotFoundException(clientId, addressType); } + return clientAddress; + } + + public ClientAddress findOneByClientIdAndAddressId(final long clientId, final long addressId) { + final ClientAddress clientAddress = this.clientAddressRepository.findByClientIdAndAddressId(clientId, + addressId); + + return clientAddress; + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/handler/AddClientAddressCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/handler/AddClientAddressCommandHandler.java new file mode 100644 index 000000000..2e9d844ba --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/handler/AddClientAddressCommandHandler.java @@ -0,0 +1,45 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.client.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.address.service.AddressWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +@CommandType(entity = "ADDRESS", action = "CREATE") +public class AddClientAddressCommandHandler implements NewCommandSourceHandler { + private final AddressWritePlatformService writePlatformService; + + @Autowired + public AddClientAddressCommandHandler(final AddressWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; + } + + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + return this.writePlatformService.addClientAddress(command.getClientId(), command.entityId(), command); + + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/handler/UpdateClientAddressCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/handler/UpdateClientAddressCommandHandler.java new file mode 100644 index 000000000..a7892c9ee --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/handler/UpdateClientAddressCommandHandler.java @@ -0,0 +1,51 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.client.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.address.service.AddressWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +@CommandType(entity = "ADDRESS", action = "UPDATE") +public class UpdateClientAddressCommandHandler implements NewCommandSourceHandler { + + private final AddressWritePlatformService writePlatformService; + + @Autowired + public UpdateClientAddressCommandHandler(final AddressWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; + } + + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + /* + * return + * this.writePlatformService.updateClientAddress(command.getClientId(), + * command.entityId(), command.getStatus(), command); + */ + return this.writePlatformService.updateClientAddress(command.getClientId(), command); + + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientAddressReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientAddressReadPlatformService.java new file mode 100644 index 000000000..d33635f78 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientAddressReadPlatformService.java @@ -0,0 +1,29 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.client.service; + +import java.util.Collection; + +import org.apache.fineract.portfolio.address.data.ClientAddressData; + +public interface ClientAddressReadPlatformService { + + public Collection retrieveClientAddrConfiguration(String entity); + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientAddressReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientAddressReadPlatformServiceImpl.java new file mode 100644 index 000000000..63079ed1d --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientAddressReadPlatformServiceImpl.java @@ -0,0 +1,76 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.client.service; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Collection; + +import org.apache.fineract.infrastructure.core.service.RoutingDataSource; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.apache.fineract.portfolio.address.data.ClientAddressData; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Service; + +@Service +public class ClientAddressReadPlatformServiceImpl implements ClientAddressReadPlatformService { + + private final JdbcTemplate jdbcTemplate; + private final PlatformSecurityContext context; + + @Autowired + public ClientAddressReadPlatformServiceImpl(final PlatformSecurityContext context, + final RoutingDataSource dataSource) { + this.context = context; + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + private static final class ClientAddrMapper implements RowMapper { + public String schema() { + return "fld.id as fieldConfigurationId,fld.entity as entity,fld.table as entitytable,fld.field as field,fld.is_enabled as is_enabled," + + "fld.is_mandatory as is_mandatory,fld.validation_regex as validation_regex from m_field_configuration fld"; + } + + @Override + public ClientAddressData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) + throws SQLException { + final long clientAddressId = rs.getLong("clientAddressId"); + final long client_id = rs.getLong("client_id"); + final long address_id = rs.getLong("address_id"); + final long address_type_id = rs.getLong("address_type_id"); + final boolean is_active = rs.getBoolean("is_active"); + + return ClientAddressData.instance(clientAddressId, client_id, address_id, address_type_id, is_active); + + } + } + + @Override + public Collection retrieveClientAddrConfiguration(final String entity) { + this.context.authenticatedUser(); + + final ClientAddrMapper rm = new ClientAddrMapper(); + final String sql = "select " + rm.schema() + " where fld.entity=?"; + + return this.jdbcTemplate.query(sql, rm, new Object[] { entity }); + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformServiceImpl.java index 1cc335589..bec536939 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformServiceImpl.java @@ -27,6 +27,8 @@ import java.util.List; import org.apache.commons.lang.StringUtils; import org.apache.fineract.infrastructure.codes.data.CodeValueData; import org.apache.fineract.infrastructure.codes.service.CodeValueReadPlatformService; +import org.apache.fineract.infrastructure.configuration.data.GlobalConfigurationPropertyData; +import org.apache.fineract.infrastructure.configuration.service.ConfigurationReadPlatformService; import org.apache.fineract.infrastructure.core.api.ApiParameterHelper; import org.apache.fineract.infrastructure.core.data.EnumOptionData; import org.apache.fineract.infrastructure.core.domain.JdbcSupport; @@ -39,6 +41,8 @@ import org.apache.fineract.organisation.office.data.OfficeData; import org.apache.fineract.organisation.office.service.OfficeReadPlatformService; import org.apache.fineract.organisation.staff.data.StaffData; import org.apache.fineract.organisation.staff.service.StaffReadPlatformService; +import org.apache.fineract.portfolio.address.data.AddressData; +import org.apache.fineract.portfolio.address.service.AddressReadPlatformService; import org.apache.fineract.portfolio.client.api.ClientApiConstants; import org.apache.fineract.portfolio.client.data.ClientData; import org.apache.fineract.portfolio.client.data.ClientNonPersonData; @@ -74,18 +78,25 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService private final ClientLookupMapper lookupMapper = new ClientLookupMapper(); private final ClientMembersOfGroupMapper membersOfGroupMapper = new ClientMembersOfGroupMapper(); private final ParentGroupsMapper clientGroupsMapper = new ParentGroupsMapper(); + + private final AddressReadPlatformService addressReadPlatformService; + private final ConfigurationReadPlatformService configurationReadPlatformService; @Autowired public ClientReadPlatformServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource, final OfficeReadPlatformService officeReadPlatformService, final StaffReadPlatformService staffReadPlatformService, final CodeValueReadPlatformService codeValueReadPlatformService, - final SavingsProductReadPlatformService savingsProductReadPlatformService) { + final SavingsProductReadPlatformService savingsProductReadPlatformService, + final AddressReadPlatformService addressReadPlatformService, + final ConfigurationReadPlatformService configurationReadPlatformService) { this.context = context; this.officeReadPlatformService = officeReadPlatformService; this.jdbcTemplate = new JdbcTemplate(dataSource); this.staffReadPlatformService = staffReadPlatformService; this.codeValueReadPlatformService = codeValueReadPlatformService; this.savingsProductReadPlatformService = savingsProductReadPlatformService; + this.addressReadPlatformService=addressReadPlatformService; + this.configurationReadPlatformService=configurationReadPlatformService; } @Override @@ -93,10 +104,21 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService this.context.authenticatedUser(); final Long defaultOfficeId = defaultToUsersOfficeIfNull(officeId); + AddressData address=null; final Collection offices = this.officeReadPlatformService.retrieveAllOfficesForDropdown(); final Collection savingsProductDatas = this.savingsProductReadPlatformService.retrieveAllForLookupByType(null); + + final GlobalConfigurationPropertyData configuration=this.configurationReadPlatformService.retrieveGlobalConfiguration("Enable-Address"); + + final Boolean isAddressEnabled=configuration.isEnabled(); + if(isAddressEnabled) + { + address = this.addressReadPlatformService.retrieveTemplate(); + } + + Collection staffOptions = null; @@ -129,7 +151,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService return ClientData.template(defaultOfficeId, new LocalDate(), offices, staffOptions, null, genderOptions, savingsProductDatas, clientTypeOptions, clientClassificationOptions, clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, - clientLegalFormOptions); + clientLegalFormOptions,address,isAddressEnabled); } @Override @@ -760,7 +782,7 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService final Collection clientNonPersonMainBusinessLineOptions = null; final List clientLegalFormOptions = null; return ClientData.template(null, null, null, null, narrations, null, null, clientTypeOptions, clientClassificationOptions, - clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, clientLegalFormOptions); + clientNonPersonConstitutionOptions, clientNonPersonMainBusinessLineOptions, clientLegalFormOptions,null,null); } } \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java index 26a1d42f8..038c46d78 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java @@ -32,7 +32,9 @@ import org.apache.fineract.infrastructure.accountnumberformat.domain.AccountNumb import org.apache.fineract.infrastructure.accountnumberformat.domain.EntityAccountType; import org.apache.fineract.infrastructure.codes.domain.CodeValue; import org.apache.fineract.infrastructure.codes.domain.CodeValueRepositoryWrapper; +import org.apache.fineract.infrastructure.configuration.data.GlobalConfigurationPropertyData; import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService; +import org.apache.fineract.infrastructure.configuration.service.ConfigurationReadPlatformService; import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder; @@ -44,6 +46,7 @@ import org.apache.fineract.organisation.office.domain.OfficeRepository; import org.apache.fineract.organisation.office.exception.OfficeNotFoundException; import org.apache.fineract.organisation.staff.domain.Staff; import org.apache.fineract.organisation.staff.domain.StaffRepositoryWrapper; +import org.apache.fineract.portfolio.address.service.AddressWritePlatformService; import org.apache.fineract.portfolio.client.api.ClientApiConstants; import org.apache.fineract.portfolio.client.data.ClientDataValidator; import org.apache.fineract.portfolio.client.domain.AccountNumberGenerator; @@ -110,6 +113,8 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP private final ConfigurationDomainService configurationDomainService; private final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository; private final FromJsonHelper fromApiJsonHelper; + private final ConfigurationReadPlatformService configurationReadPlatformService; + private final AddressWritePlatformService addressWritePlatformService; @Autowired public ClientWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, @@ -120,7 +125,9 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP final SavingsAccountRepository savingsRepository, final SavingsProductRepository savingsProductRepository, final SavingsApplicationProcessWritePlatformService savingsApplicationProcessWritePlatformService, final CommandProcessingService commandProcessingService, final ConfigurationDomainService configurationDomainService, - final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository, final FromJsonHelper fromApiJsonHelper) { + final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository, final FromJsonHelper fromApiJsonHelper, + final ConfigurationReadPlatformService configurationReadPlatformService, + final AddressWritePlatformService addressWritePlatformService) { this.context = context; this.clientRepository = clientRepository; this.clientNonPersonRepository = clientNonPersonRepository; @@ -139,6 +146,8 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP this.configurationDomainService = configurationDomainService; this.accountNumberFormatRepository = accountNumberFormatRepository; this.fromApiJsonHelper = fromApiJsonHelper; + this.configurationReadPlatformService = configurationReadPlatformService; + this.addressWritePlatformService = addressWritePlatformService; } @Transactional @@ -200,6 +209,11 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP final AppUser currentUser = this.context.authenticatedUser(); this.fromApiJsonDeserializer.validateForCreate(command.json()); + + final GlobalConfigurationPropertyData configuration = this.configurationReadPlatformService + .retrieveGlobalConfiguration("Enable-Address"); + + final Boolean isAddressEnabled = configuration.isEnabled(); final Long officeId = command.longValueOfParameterNamed(ClientApiConstants.officeIdParamName); @@ -283,10 +297,20 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP CommandProcessingResult result = openSavingsAccount(newClient, fmt); if (result.getSavingsId() != null) { this.clientRepository.save(newClient); + } if(isEntity) extractAndCreateClientNonPerson(newClient, command); + + final long clientId = newClient.getId(); + + if (isAddressEnabled) { + + this.addressWritePlatformService.addNewClientAddress(newClient, command); + + } + return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // @@ -820,4 +844,4 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP .withEntityId(entityId) // .build(); } -} +} \ No newline at end of file diff --git a/fineract-provider/src/main/resources/sql/migrations/core_db/V312__address_module_tables_metadat.sql b/fineract-provider/src/main/resources/sql/migrations/core_db/V312__address_module_tables_metadat.sql new file mode 100644 index 000000000..3e85e93fe --- /dev/null +++ b/fineract-provider/src/main/resources/sql/migrations/core_db/V312__address_module_tables_metadat.sql @@ -0,0 +1,122 @@ +-- +-- 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. + + + +-- code inserts +INSERT INTO `m_code` (`code_name`, `is_system_defined`) VALUES ('STATE',1); +INSERT INTO `m_code` (`code_name`, `is_system_defined`) VALUES ('COUNTRY',1); +INSERT INTO `m_code` (`code_name`, `is_system_defined`) VALUES ('ADDRESS_TYPE',1); + + +-- configuration +INSERT INTO `c_configuration` (`name`, `value`, `date_value`, `enabled`, `is_trap_door`, `description`) VALUES ('Enable-Address', NULL, NULL, 1, 0, NULL); + +-- add address table +CREATE TABLE `m_address` ( + `id` BIGINT(20) NOT NULL AUTO_INCREMENT, + `street` VARCHAR(100) NULL DEFAULT NULL, + `address_line_1` VARCHAR(100) NULL DEFAULT NULL, + `address_line_2` VARCHAR(100) NULL DEFAULT NULL, + `address_line_3` VARCHAR(100) NULL DEFAULT NULL, + `town_village` VARCHAR(100) NULL DEFAULT NULL, + `city` VARCHAR(100) NULL DEFAULT NULL, + `county_district` VARCHAR(100) NULL DEFAULT NULL, + `state_province_id` INT(11) NULL DEFAULT NULL, + `country_id` INT(11) NULL DEFAULT NULL, + `postal_code` VARCHAR(10) NULL DEFAULT NULL, + `latitude` DECIMAL(10,8) UNSIGNED NULL DEFAULT '0.00000000', + `longitude` DECIMAL(10,8) UNSIGNED NULL DEFAULT '0.00000000', + `created_by` VARCHAR(100) NULL DEFAULT NULL, + `created_on` DATE NULL DEFAULT NULL, + `updated_by` VARCHAR(100) NULL DEFAULT NULL, + `updated_on` DATE NULL DEFAULT NULL, + PRIMARY KEY (`id`), + INDEX `address_fields_codefk1` (`state_province_id`), + INDEX `address_fields_codefk2` (`country_id`), + CONSTRAINT `address_fields_codefk1` FOREIGN KEY (`state_province_id`) REFERENCES `m_code_value` (`id`), + CONSTRAINT `address_fields_codefk2` FOREIGN KEY (`country_id`) REFERENCES `m_code_value` (`id`) +) +ENGINE=InnoDB +AUTO_INCREMENT=1 +; + + +-- entity address table +CREATE TABLE `m_client_address` ( + `id` BIGINT(20) NOT NULL AUTO_INCREMENT, + `client_id` BIGINT(20) NOT NULL DEFAULT '0', + `address_id` BIGINT(20) NOT NULL DEFAULT '0', + `address_type_id` INT(11) NOT NULL DEFAULT '0', + `is_active` TINYINT(4) NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + INDEX `addressIdFk` (`address_id`), + INDEX `address_codefk` (`address_type_id`), + INDEX `clientaddressfk` (`client_id`), + CONSTRAINT `address_codefk` FOREIGN KEY (`address_type_id`) REFERENCES `m_code_value` (`id`), + CONSTRAINT `clientaddressfk` FOREIGN KEY (`client_id`) REFERENCES `m_client` (`id`) +) +ENGINE=InnoDB +AUTO_INCREMENT=1 +; + + +-- field configuration +CREATE TABLE `m_field_configuration` ( + `id` BIGINT(20) NOT NULL AUTO_INCREMENT, + `entity` VARCHAR(100) NOT NULL, + `subentity` VARCHAR(100) NOT NULL, + `field` VARCHAR(100) NOT NULL, + `is_enabled` TINYINT(4) NOT NULL, + `is_mandatory` TINYINT(4) NOT NULL, + `validation_regex` VARCHAR(50) NULL DEFAULT NULL, + PRIMARY KEY (`id`) +) +ENGINE=InnoDB +AUTO_INCREMENT=1 +; + + +INSERT INTO `m_field_configuration` ( `entity`, `subentity`, `field`, `is_enabled`, `is_mandatory`, `validation_regex`) VALUES + ('ADDRESS', 'CLIENT', 'addressType', 1, 0, ''), + ('ADDRESS', 'CLIENT', 'street', 1, 1, ''), + ('ADDRESS', 'CLIENT', 'addressLine1', 1, 0, ''), + ('ADDRESS', 'CLIENT', 'addressLine2', 1, 0, ''), + ('ADDRESS', 'CLIENT', 'addressLine3', 1, 0, ''), + ('ADDRESS', 'CLIENT', 'townVillage', 0, 0, ''), + ('ADDRESS', 'CLIENT', 'city', 1, 0, ''), + ('ADDRESS', 'CLIENT', 'countyDistrict', 0, 0, ''), + ('ADDRESS', 'CLIENT', 'stateProvinceId', 1, 0, ''), + ('ADDRESS', 'CLIENT', 'countryId', 1, 0, ''), + ('ADDRESS', 'CLIENT', 'postalCode', 1, 0, ''), + ('ADDRESS', 'CLIENT', 'latitude', 0, 0, ''), + ('ADDRESS', 'CLIENT', 'longitude', 0, 0, ''), + ('ADDRESS', 'CLIENT', 'createdBy', 1, 0, ''), + ('ADDRESS', 'CLIENT', 'createdOn', 1, 0, ''), + ('ADDRESS', 'CLIENT', 'updatedBy', 1, 0, ''), + ('ADDRESS', 'CLIENT', 'updatedOn', 1, 0, ''), + ('ADDRESS', 'CLIENT', 'isActive', 1, 0, ''); + +-- inserts for permission +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'CREATE_ADDRESS', 'ADDRESS', 'CREATE', 0); +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'CREATE_ADDRESS_CHECKER', 'ADDRESS', 'CREATE_CHECKER', 1); +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'UPDATE_ADDRESS', 'ADDRESS', 'UPDATE', 0); +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'UPDATE_ADDRESS_CHECKER', 'ADDRESS', 'UPDATE_CHECKER', 1); +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'READ_ADDRESS', 'ADDRESS', 'READ', 0); +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'DELETE_ADDRESS', 'ADDRESS', 'DELETE', 0); +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'DELETE_ADDRESS_CHECKER', 'ADDRESS', 'DELETE_CHECKER', 1);