From ec3ae1449c8379c8d59f1c6866976785d8d5d84a Mon Sep 17 00:00:00 2001 From: ShruthiRajaram Date: Thu, 25 Oct 2018 18:06:13 +0530 Subject: [PATCH] FINERACT-628 Products APIs --- api-docs/apiLive.htm | 1187 +++++++++++++++++ .../AppuserClientMapperReadService.java | 2 + .../AppuserClientMapperReadServiceImpl.java | 20 +- .../api/SelfLoanProductsApiResource.java | 77 ++ .../api/SelfSavingsProductsApiResource.java | 78 ++ .../api/SelfShareProductsApiResource.java | 79 ++ 6 files changed, 1442 insertions(+), 1 deletion(-) create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/self/products/api/SelfLoanProductsApiResource.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/self/products/api/SelfSavingsProductsApiResource.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/self/products/api/SelfShareProductsApiResource.java diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm index 00751bc2c..9e10be258 100644 --- a/api-docs/apiLive.htm +++ b/api-docs/apiLive.htm @@ -3617,6 +3617,40 @@ + + Loan Product + self/loanproducts?clientId={clientId} + + List Loan Products + + + + + + self/loanproducts/{productId}?clientId={clientId} + + Retrieve a Loan + Product + + + + + Savings Product + self/savingsproducts?clientId={clientId} + + List Savings products + + + + + + + self/savingsproducts/{productId}?clientId={clientId} + + Retrieve a savings product + + + self/clients/{clientId}/images @@ -3625,6 +3659,22 @@ Delete client image + + Share Product + self/shareproducts?clientId={clientId} + + List Share products + + + + + + self/shareproducts/{productId}?clientId={clientId} + + Retrieve a share product + + + Loans self/loans/template?templateType=individual @@ -49222,11 +49272,1148 @@ No Request Body: "resourceId": 14, "changes": {}, "resourceIdentifier": "14" +} + + +  +
+
+

Loan Products

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Field Descriptions
name
Name associated with loan product on system.
shortName
Short name associated with a loan product.
+ An abbreviated version of the name, used in reports or menus where space is limited, such as Collection Sheets. +
description
For providing helpful description of product offering.
fundId
For associating a loan product with a given fund by default.
includeInBorrowerCycle
It is a flag, Used to denote whether the loans should include in loan cycle counter or not.
useBorrowerCycle
It is a flag, Used to denote whether the loans should depend on
borrower loan cycle counter or not.
currencyCode
A three letter ISO code of currency.
digitsAfterDecimal
Override the currency default value for digitsAfterDecimal.
inMultiplesOf
Override the default value for rounding currency to multiples of value provided.
installmentAmountInMultiplesOf
Override the default value for rounding instalment amount to multiples of value provided.
principal
The loan amount to be disbursed to through loan.
numberOfRepayments
Number of installments to repay.
+ Used like: numberOfRepayments Every repaymentEvery + repaymentFrequencyType
e.g. 10 (repayments) Every 12 Weeks +
repaymentEvery
Used like: numberOfRepayments Every + repaymentEvery repaymentFrequencyType
e.g. 10 + (repayments) Every 12 Weeks +
repaymentFrequencyType
Used like: numberOfRepayments Every + repaymentEvery repaymentFrequencyType
e.g. 10 + (repayments) Every 12 Weeks
+ Example Values: 0=Days, 1=Weeks, 2=Months +
interestRatePerPeriod
Interest Rate.
Used like: + interestRatePerPeriod % interestRateFrequencyType - interestType
+ e.g. 12.0000% Per year - Declining Balance +
interestRateFrequencyType
Used like: interestRatePerPeriod% + interestRateFrequencyType - interestType
e.g. 12.0000% + Per year - Declining Balance
+ Example Values: 2=Per month, 3=Per year +
amortizationType
Example Values: 0=Equal + principle payments, 1=Equal installments
interestType
Used like: interestRatePerPeriod% + interestRateFrequencyType - interestType
e.g. 12.0000% + Per year - Declining Balance
+ Example Values: 0=Declining Balance, 1=Flat +
interestCalculationPeriodType
Example Values: 0=Daily, 1=Same as repayment period
allowPartialPeriodInterestCalcualtion
This value will be supported along with interestCalculationPeriodType as Same as repayment period to calculate interest for partial periods. + Example: Interest charged from is 5th of April , Principal is 10000 and interest is 1% per month then the interest will be (10000 * 1%)* (25/30) , it calculates for the month first then calculates exact periods between start date and end date(can be a decimal) +
inArrearsTolerance
The amount that can be 'waived' at end + of all loan payments because it is too small to worry about.
+ This is also the tolerance amount assessed when determining if a + loan is in arrears. +
principalVariationsForBorrowerCycle,interestRateVariationsForBorrowerCycle,
numberOfRepaymentVariationsForBorrowerCycle
Variations for loan, based on borrower cycle number +
minimumDaysBetweenDisbursalAndFirstRepayment
The minimum number of days allowed between a Loan disbursal and its first repayment. +
principalThresholdForLastInstalment
Field represents percentage of current instalment principal amount for comparing against principal outstanding to add another repayment instalment. If the outstanding principal amount is less then calculated amount, remaining outstanding amount will be added to current instalment. Default value for multi disburse loan is 50% and non-multi disburse loan is 0% +
canDefineInstallmentAmount
if provided as true, then fixed instalment amount can be provided from loan account. +
transactionProcessingStrategyId
+An enumeration that indicates the type of transaction processing strategy to be used. This relates to functionality that is also known as Payment Application Logic. + +

A number of out of the box approaches exist, some are custom to specific MFIs, some are more general and indicate the order in which payments are processed.

+ +

Refer to the Payment Application Logic / Transaction Processing Strategy section in the appendix for more detailed overview of each available payment application logic provided out of the box.

+ +List of current approaches:
+
    +
  • 1 = Mifos style (Similar to Old Mifos)
  • +
  • 2 = Heavensfamily (Custom MFI approach)
  • +
  • 3 = Creocore (Custom MFI approach)
  • +
  • 4 = RBI (India)
  • +
  • 5 = Principal Interest Penalties Fees Order
  • +
  • 6 = Interest Principal Penalties Fees Order
  • +
  • 7 = Early Payment Strategy
  • +
+
graceOnPrincipalPayment
Optional: Integer - represents the number of repayment periods that grace should apply to the principal component of a repayment period. +
graceOnInterestPayment
Optional: Integer - represents the number of repayment periods that grace should apply to the interest component of a repayment period. Interest is still calculated but offset to later repayment periods. +
graceOnInterestCharged
Optional: Integer - represents the number of repayment periods that should be interest-free. +
graceOnArrearsAgeing
Optional: Integer - Used in Arrears calculation to only take into account loans that are more than graceOnArrearsAgeing days overdue. +
overdueDaysForNPA
Optional: Integer - represents the maximum number of days a Loan may + be overdue before being classified as a NPA (non performing asset) +
accountMovesOutOfNPAOnlyOnArrearsCompletion
Optional: Boolean - if provided as true, Loan Account moves out of NPA state only when all arrears are cleared +
accountingRule
Specifies if accounting is enabled for the particular + product and the type of the accounting rule to be used + Example Values:1=NONE, 2=CASH_BASED, 3=ACCRUAL_PERIODIC, 4=ACCRUAL_UPFRONT
isInterestRecalculationEnabled
It is a flag, Used to denote whether interest recalculation is enabled or disabled for the particular product
daysInYearType
Specifies the number of days in a year.
+ Example Values:1=ACTUAL(Actual number of days in year), 360=360 DAYS, 364=364 DAYS(52 WEEKS), 365=365 DAYS
daysInMonthType
Specifies the number of days in a month.
+ Example Values:1=ACTUAL(Actual number of days in month), 30=30 DAYS
interestRecalculationCompoundingMethod
Specifies which amount portion should be added to principal for interest recalculation.
+ Example Values:0=NONE(Only on principal), 1=INTEREST(Principal+Interest), 2=FEE(Principal+Fee), 3=FEE And INTEREST (Principal+Fee+Interest)
rescheduleStrategyMethod
Specifies what action should perform on loan repayment schedule for advance payments.
+ Example Values:1=Reschedule next repayments, 2=Reduce number of installments, 3=Reduce EMI amount
recalculationCompoundingFrequencyType
Specifies effective date from which the compounding of interest or fee amounts will be considered in recalculation on late payment.
+ Example Values:1=Same as repayment period, 2=Daily, 3=Weekly, 4=Monthly
recalculationCompoundingFrequencyInterval
Specifies compounding frequency interval for interest recalculation.
+
recalculationCompoundingFrequencyDate
Specifies compounding frequency start date for interest recalculation.
+
recalculationRestFrequencyType
Specifies effective date from which the late or advanced payment amounts will be considered in recalculation.
+ Example Values:1=Same as repayment period, 2=Daily, 3=Weekly, 4=Monthly
recalculationRestFrequencyInterval
Specifies rest frequency interval for interest recalculation.
+
recalculationRestFrequencyDate
Specifies rest frequency start date for interest recalculation.
+
preClosureInterestCalculationStrategy
Specifies applicable days for interest calculation on pre closure of a loan.
+ Example Values:1=Calculate till pre closure date, 2=Calculate till rest frequency date
isArrearsBasedOnOriginalSchedule
If Specified as true, arrears will be identified based on original schedule.
+
allowAttributeOverrides
Specifies if select attributes may be overridden for individual loan accounts.
+
+
+
+ +   +
+
+

List Loan Products

+

Example Requests:

+
self/loanproducts?clientId=1
+
+
+
self/loanproducts?fields=name,description&clientId=1
+
+
+ +GET https://DomainName/api/v1/self/loanproducts?clientId={clientId} + + +[ + { + "name":"Personal loan", + "description":"Loan", + "useBorrowerCycle":false, + "status":"loanProduct.active", + "allowVariableInstallments":false, + "minimumGap":0, + "maximumGap":0, + "daysInMonthType":{ + "code":"DaysInMonthType.actual", + "value":"Actual" + }, + "daysInYearType":{ + "code":"DaysInYearType.actual", + "value":"Actual" + }, + "isInterestRecalculationEnabled":false, + "canDefineInstallmentAmount":false, + "installmentAmountInMultiplesOf":1, + "principalVariationsForBorrowerCycle":[ + + ], + "interestRateVariationsForBorrowerCycle":[ + + ], + "numberOfRepaymentVariationsForBorrowerCycle":[ + + ], + "multiDisburseLoan":false, + "maxTrancheCount":0, + "principalThresholdForLastInstallment":0, + "holdGuaranteeFunds":false, + "accountMovesOutOfNPAOnlyOnArrearsCompletion":false, + "allowAttributeOverrides":{ + "graceOnPrincipalAndInterestPayment":true, + "graceOnArrearsAgeing":true + }, + "syncExpectedWithDisbursementDate":false + } +] + +
+
+ + +   +
+
+

Retrieve a Loan Product

+

Example Requests:

+
self/loanproducts/1?clientId=1
+
+
+
self/loanproducts/1?fields=name,description&clientId=1
+
+
+ +GET https://DomainName/api/v1/self/loanproducts/{productId}?clientId={clientId} + + +{ + "id": 11, + "name": "advanced accounting", + "shortName": "ad11", + "includeInBorrowerCycle": true, + "useBorrowerCycle": true, + "status": "loanProduct.active", + "currency": { + "code": "USD", + "name": "US Dollar", + "decimalPlaces": 2, + "inMultiplesOf": 0, + "displaySymbol": "$", + "nameCode": "currency.USD", + "displayLabel": "US Dollar ($)" + }, + "principal": 10000.000000, + "minPrincipal": 2000.000000, + "maxPrincipal": 15000.000000, + "numberOfRepayments": 7, + "repaymentEvery": 7, + "repaymentFrequencyType": { + "id": 0, + "code": "repaymentFrequency.periodFrequencyType.days", + "value": "Days" + }, + "interestRatePerPeriod": 5.000000, + "interestRateFrequencyType": { + "id": 2, + "code": "interestRateFrequency.periodFrequencyType.months", + "value": "Per month" + }, + "annualInterestRate": 60.000000, + "amortizationType": { + "id": 1, + "code": "amortizationType.equal.installments", + "value": "Equal installments" + }, + "interestType": { + "id": 0, + "code": "interestType.declining.balance", + "value": "Declining Balance" + }, + "interestCalculationPeriodType": { + "id": 1, + "code": "interestCalculationPeriodType.same.as.repayment.period", + "value": "Same as repayment period" + }, + "transactionProcessingStrategyId": 1, + "transactionProcessingStrategyName": "Mifos style", + "charges": [], + "principalVariationsForBorrowerCycle": [ + { + "id": 21, + "borrowerCycleNumber": 1, + "paramType": { + "id": 1, + "code": "LoanProductParamType.principal", + "value": "principal" + }, + "valueConditionType": { + "id": 2, + "code": "LoanProductValueConditionType.equal", + "value": "equals" + }, + "minValue": 2000.000000, + "maxValue": 20000.000000, + "defaultValue": 15000.000000 + }, + { + "id": 20, + "borrowerCycleNumber": 1, + "paramType": { + "id": 1, + "code": "LoanProductParamType.principal", + "value": "principal" + }, + "valueConditionType": { + "id": 3, + "code": "LoanProductValueConditionType.greterthan", + "value": "greter than" + }, + "minValue": 3000.000000, + "maxValue": 25000.000000, + "defaultValue": 20000.000000 + } + ], + "interestRateVariationsForBorrowerCycle": [], + "numberOfRepaymentVariationsForBorrowerCycle": [], + "accountingRule": { + "id": 2, + "code": "accountingRuleType.cash", + "value": "CASH BASED" + }, + "accountingMappings": { + "fundSourceAccount": { + "id": 1, + "name": "fund source", + "glCode": "01" + }, + "loanPortfolioAccount": { + "id": 2, + "name": "Loan portfolio", + "glCode": "02" + }, + "transfersInSuspenseAccount": { + "id": 3, + "name": "transfers", + "glCode": "03" + }, + "interestOnLoanAccount": { + "id": 4, + "name": "income from interest", + "glCode": "04" + }, + "incomeFromFeeAccount": { + "id": 8, + "name": "income from fees 2", + "glCode": "10" + }, + "incomeFromPenaltyAccount": { + "id": 9, + "name": "income from penalities 2", + "glCode": "11" + }, + "writeOffAccount": { + "id": 10, + "name": "loans written off 2", + "glCode": "12" + }, + "overpaymentLiabilityAccount": { + "id": 11, + "name": "over payment", + "glCode": "13" + } + }, + "paymentChannelToFundSourceMappings": [ + { + "paymentType": { + "id": 10, + "name": "check" + }, + "fundSourceAccount": { + "id": 1, + "name": "fund source", + "glCode": "01" + } + } + ], + "feeToIncomeAccountMappings": [ + { + "charge": { + "id": 1, + "name": "flat install", + "active": false, + "penalty": false + }, + "incomeAccount": { + "id": 8, + "name": "income from fees 2", + "glCode": "10" + } + }, + { + "charge": { + "id": 2, + "name": "install per", + "active": false, + "penalty": false + }, + "incomeAccount": { + "id": 4, + "name": "income from interest", + "glCode": "04" + } + }, + { + "charge": { + "id": 5, + "name": "des charge", + "active": false, + "penalty": false + }, + "incomeAccount": { + "id": 9, + "name": "income from penalities 2", + "glCode": "11" + } + }, + "multiDisburseLoan":true,"maxTrancheCount":3,"outstandingLoanBalance":36000.000000, + "overdueDaysForNPA":2, + "principalThresholdForLastInstalment":50 + ] }
+ +  +
+
+

Savings Product:

+

An MFIs savings product offerings are modeled using this API.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Field Descriptions
name
The name of the product offering.
shortName
Shortname associated with a saving product.
+ An abbreviated version of the name, used in reports or menus where space is limited. +
description
A description of the product offering.
currencyCode
Three letter ISO code representing currency.
digitsAfterDecimal
Override the currency default value for digitsAfterDecimal.
inMultiplesOf
Override the default value for rounding currency to multiples of provided value.
nominalAnnualInterestRate
The default interest rate set when creating savings accounts of this type of product. e.g. 5% Per year - It number here is always expressed as the Nominal APR.
interestCompoundingPeriodType
The period at which interest rate is compounded. 1=Daily, 4=Monthly (at end of month)
interestPostingPeriodType
The period at which interest rate is posted or credited to savings account. 4=Monthly (at end of month), 5=Quarterly (at end of quarter, 31st Mar, 30th Jun, 30th Sep, 31st Dec)
interestCalculationType
The interest calculation method used: 1=Daily Balance or 2=Average Daily Balance
interestCalculationDaysInYearType
The setting for number of days in year to use: 360=360 Days, 365=365 Days
minRequiredOpeningBalance
Optional: If provided, sets the minimum deposit amount required to open a savings account e.g. 2,000
lockinPeriodFrequency
Optional: If provided, used along with lockinPeriodFrequencyType to indicate the length of time that the savings account is 'locked in' and withdrawals are not allowed. e.g. 6 Months
lockinPeriodFrequencyType
Optional: If provided, used along with lockinPeriodFrequency to indicate the length of time that the savings account is 'locked in' and withdrawals are not allowed. 0=Days, 1=Weeks, 2=Months, 3=Years + e.g. 6 Months
withdrawalFeeForTransfers
Optional: Used along with withdrawalFeeAmount to indicate whether the withdrawal fee should be applied on the account for account transfers .
accountingRule
Specifies if accounting is enabled for the particular + product and the type of the accounting rule to be used + Example Values:1=NONE,2=CASH_BASED
allowOverdraft
Optional: If provided, depending on the value mark the savings account as overdraft account
overdraftLimit
Optional: If provided, sets the maximum allowed overdraft amount for a savings account e.g. 5,000 else set the limit as zero
minBalanceForInterestCalculation
Optional: If provided, balance must be greater than provided value for calculation of interest e.g. 5,000
enforceMinRequiredBalance
Optional: If set to true, validates that the account balance does not + fall below minRequiredBalance
minRequiredBalance
Optional: If provided, sets an indicator of the minimum required balance of the savings account e.g. 5,000 else set the limit as zero. Note that enforceMinRequiredBalance determines if the minimum required balance is enforced
withHoldTax
Optional: If provided, sets an indicator for applying withhold tax on interest posting for savings account
taxGroupId
Optional: If withhold tax set as true, with hold tax will be applied as per the tax group provided
+
+
+   +
+
+

List Savings Products

+

Example Requests:

+
self/savingsproducts?clientId=1
+
+
+ GET https://domainname/api/v1/self/savingsproducts?clientid={clientid} + +[ + { + "id": 1, + "name": "Savings product", + "shortName": "sa1", + "description": "savings", + "currency": { + "code": "USD", + "name": "US Dollar", + "decimalPlaces": 2, + "displaySymbol": "$", + "nameCode": "currency.USD", + "displayLabel": "US Dollar ($)" + }, + "nominalAnnualInterestRate": 5.000000, + "interestCompoundingPeriodType": { + "id": 1, + "code": "savings.interest.period.savingsCompoundingInterestPeriodType.daily", + "value": "Daily" + }, + "interestPostingPeriodType": { + "id": 4, + "code": "savings.interest.posting.period.savingsPostingInterestPeriodType.monthly", + "value": "Monthly" + }, + "interestCalculationType": { + "id": 1, + "code": "savingsInterestCalculationType.dailybalance", + "value": "Daily Balance" + }, + "interestCalculationDaysInYearType": { + "id": 365, + "code": "savingsInterestCalculationDaysInYearType.days365", + "value": "365 Days" + }, + "withdrawalFeeForTransfers": false, + "accountingRule": { + "id": 2, + "code": "accountingRuleType.cash", + "value": "CASH BASED" + } + } +] +
+
+ +   +
+
+

Retrieve a Savings Product

+

Example Requests:

+
self/savingsproducts/1?clientId=1
+

+
self/savingsproducts/1?fields=name,description&clientId=1
+
+
+ GET https://DomainName/api/v1/self/savingsproducts/{productId}&clientId={clientId} + +{ + "id": 1, + "name": "savings product", + "shortName": "sa1", + "description": "savings", + "currency": { + "code": "USD", + "name": "US Dollar", + "decimalPlaces": 2, + "displaySymbol": "$", + "nameCode": "currency.USD", + "displayLabel": "US Dollar ($)" + }, + "nominalAnnualInterestRate": 5.000000, + "interestCompoundingPeriodType": { + "id": 1, + "code": "savings.interest.period.savingsCompoundingInterestPeriodType.daily", + "value": "Daily" + }, + "interestPostingPeriodType": { + "id": 4, + "code": "savings.interest.posting.period.savingsPostingInterestPeriodType.monthly", + "value": "Monthly" + }, + "interestCalculationType": { + "id": 1, + "code": "savingsInterestCalculationType.dailybalance", + "value": "Daily Balance" + }, + "interestCalculationDaysInYearType": { + "id": 365, + "code": "savingsInterestCalculationDaysInYearType.days365", + "value": "365 Days" + }, + "withdrawalFeeForTransfers": false, + "accountingRule": { + "id": 2, + "code": "accountingRuleType.cash", + "value": "CASH BASED" + }, + "accountingMappings": { + "savingsReferenceAccount": { + "id": 12, + "name": "savings ref", + "glCode": "20" + }, + "incomeFromFeeAccount": { + "id": 16, + "name": "income from savings fee", + "glCode": "24" + }, + "incomeFromPenaltyAccount": { + "id": 17, + "name": "income from sav penalites", + "glCode": "25" + }, + "interestOnSavingsAccount": { + "id": 15, + "name": "interest on savings", + "glCode": "23" + }, + "savingsControlAccount": { + "id": 13, + "name": "savings ref tool kit", + "glCode": "21" + }, + "transfersInSuspenseAccount": { + "id": 14, + "name": "saving transfers", + "glCode": "22" + } + }, + "paymentChannelToFundSourceMappings": [ + { + "paymentType": { + "id": 10, + "name": "check" + }, + "fundSourceAccount": { + "id": 12, + "name": "savings ref", + "glCode": "20" + } + } + ], + "feeToIncomeAccountMappings": [ + { + "charge": { + "id": 11, + "name": "sav charge", + "active": false, + "penalty": false + }, + "incomeAccount": { + "id": 16, + "name": "income from savings fee", + "glCode": "24" + } + } + ], + "penaltyToIncomeAccountMappings": [ + { + "charge": { + "id": 12, + "name": "sav 2", + "active": false, + "penalty": true + }, + "incomeAccount": { + "id": 17, + "name": "income from sav penalites", + "glCode": "25" + } + } + ], + "charges": [] +} + +
+
+ +   +
+
+

List Share Products

+

Example Requests:

+
self/products/share?clientId=1
+
+
+ + GET https://DomainName/api/v1/self/products/share?clientId={clientId} + + +{ + "totalFilteredRecords": 2, + "pageItems": [ + { + "id": 1, + "name": "Share P1", + "shortName": "shar", + "description": "Share", + "currency": { + "code": "USD", + "name": "US Dollar", + "decimalPlaces": 2, + "inMultiplesOf": 1, + "displaySymbol": "$", + "nameCode": "currency.USD", + "displayLabel": "US Dollar ($)" + }, + "totalShares": 1000, + "totalSharesIssued": 450, + "unitPrice": 5, + "shareCapital": 2250, + "minimumShares": 2, + "nominalShares": 5, + "maximumShares": 8, + "allowDividendCalculationForInactiveClients": false, + "lockinPeriod": 1, + "lockPeriodTypeEnum": { + "id": 1, + "code": "shares.lockin.sharePeriodFrequencyType.weeks", + "value": "Weeks" + }, + "minimumActivePeriod": 10, + "minimumActivePeriodForDividendsTypeEnum": { + "id": 0, + "code": "shares.minimumactive.sharePeriodFrequencyType.days", + "value": "Days" + }, + "accountingRule": { + "id": 1, + "code": "accountingRuleType.none", + "value": "NONE" + } + }, + { + "id": 2, + "name": "ShareP2", + "shortName": "comp", + "description": "Company shares", + "currency": { + "code": "USD", + "name": "US Dollar", + "decimalPlaces": 2, + "inMultiplesOf": 1, + "displaySymbol": "$", + "nameCode": "currency.USD", + "displayLabel": "US Dollar ($)" + }, + "totalShares": 500, + "totalSharesIssued": 200, + "unitPrice": 2, + "shareCapital": 400, + "nominalShares": 5, + "allowDividendCalculationForInactiveClients": false, + "lockinPeriod": 1, + "lockPeriodTypeEnum": { + "id": 0, + "code": "shares.lockin.sharePeriodFrequencyType.days", + "value": "Days" + }, + "minimumActivePeriod": 10, + "minimumActivePeriodForDividendsTypeEnum": { + "id": 0, + "code": "shares.minimumactive.sharePeriodFrequencyType.days", + "value": "Days" + }, + "accountingRule": { + "id": 2, + "code": "accountingRuleType.cash", + "value": "CASH BASED" + } + } + ] +} + +
+
+ +   +
+
+

Retrieve a Share Product

+

Example Requests:

+
self/products/share/2?clientId=1
+

+
self/products/share/2?clientId=1&template=true
+
+
+ GET https://DomainName/api/v1/self/products/share/{productId}?clientId={clientId} + +{ + "id": 2, + "name": "ShareP2", + "shortName": "comp", + "description": "Company shares", + "currency": { + "code": "USD", + "name": "US Dollar", + "decimalPlaces": 2, + "inMultiplesOf": 1, + "displaySymbol": "$", + "nameCode": "currency.USD", + "displayLabel": "US Dollar ($)" + }, + "totalShares": 500, + "totalSharesIssued": 200, + "unitPrice": 2, + "shareCapital": 400, + "nominalShares": 5, + "marketPrice": [ + { + "id": 2, + "fromDate": "May 27, 2018", + "shareValue": 1 + } + ], + "charges": [ + { + "id": 1, + "name": "Activation", + "active": true, + "penalty": false, + "currency": { + "code": "USD", + "name": "US Dollar", + "decimalPlaces": 2, + "displaySymbol": "$", + "nameCode": "currency.USD", + "displayLabel": "US Dollar ($)" + }, + "amount": 1, + "chargeTimeType": { + "id": 13, + "code": "chargeTimeType.activation", + "value": "Share Account Activate" + }, + "chargeAppliesTo": { + "id": 4, + "code": "chargeAppliesTo.shares", + "value": "Shares" + }, + "chargeCalculationType": { + "id": 1, + "code": "chargeCalculationType.flat", + "value": "Flat" + }, + "chargePaymentMode": { + "id": 0, + "code": "chargepaymentmode.regular", + "value": "Regular" + } + } + ], + "allowDividendCalculationForInactiveClients": false, + "lockinPeriod": 1, + "lockPeriodTypeEnum": { + "id": 0, + "code": "shares.lockin.sharePeriodFrequencyType.days", + "value": "Days" + }, + "minimumActivePeriod": 10, + "minimumActivePeriodForDividendsTypeEnum": { + "id": 0, + "code": "shares.minimumactive.sharePeriodFrequencyType.days", + "value": "Days" + }, + "accountingRule": { + "id": 2, + "code": "accountingRuleType.cash", + "value": "CASH BASED" + }, + "accountingMappings": { + "shareReferenceId": { + "id": 1, + "name": "GLAsset", + "glCode": "GL1" + }, + "incomeFromFeeAccountId": { + "id": 4, + "name": "GLIncome", + "glCode": "GL4" + }, + "shareEquityId": { + "id": 3, + "name": "GLEquity", + "glCode": "GL3" + }, + "shareSuspenseId": { + "id": 2, + "name": "GL2Liabilities", + "glCode": "GL2" + } + } +} + +
+
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/client/service/AppuserClientMapperReadService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/client/service/AppuserClientMapperReadService.java index e69fad964..2090756ad 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/client/service/AppuserClientMapperReadService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/client/service/AppuserClientMapperReadService.java @@ -21,5 +21,7 @@ package org.apache.fineract.portfolio.self.client.service; public interface AppuserClientMapperReadService { public Boolean isClientMappedToUser(Long clientId, Long appUserId); + + public void validateAppuserClientsMapping(final Long clientId); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/client/service/AppuserClientMapperReadServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/client/service/AppuserClientMapperReadServiceImpl.java index 8711dfd78..408166e34 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/client/service/AppuserClientMapperReadServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/client/service/AppuserClientMapperReadServiceImpl.java @@ -19,6 +19,9 @@ package org.apache.fineract.portfolio.self.client.service; import org.apache.fineract.infrastructure.core.service.RoutingDataSource; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.apache.fineract.portfolio.client.exception.ClientNotFoundException; +import org.apache.fineract.useradministration.domain.AppUser; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; @@ -28,10 +31,12 @@ public class AppuserClientMapperReadServiceImpl implements AppuserClientMapperReadService { private final JdbcTemplate jdbcTemplate; + private final PlatformSecurityContext context; @Autowired - public AppuserClientMapperReadServiceImpl(final RoutingDataSource dataSource) { + public AppuserClientMapperReadServiceImpl(final RoutingDataSource dataSource, final PlatformSecurityContext context) { this.jdbcTemplate = new JdbcTemplate(dataSource); + this.context = context; } @Override @@ -42,5 +47,18 @@ public class AppuserClientMapperReadServiceImpl implements + " from m_selfservice_user_client_mapping where client_id = ? and appuser_id = ?", new Object[] { clientId, appUserId }, Boolean.class); } + + @Override + public void validateAppuserClientsMapping(final Long clientId) { + AppUser user = this.context.authenticatedUser(); + if (clientId != null) { + final boolean mappedClientId = isClientMappedToUser(clientId, user.getId()); + if (!mappedClientId) { + throw new ClientNotFoundException(clientId); + } + } else + throw new ClientNotFoundException(clientId); + + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/products/api/SelfLoanProductsApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/products/api/SelfLoanProductsApiResource.java new file mode 100644 index 000000000..dece2df8c --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/products/api/SelfLoanProductsApiResource.java @@ -0,0 +1,77 @@ +/** + * 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.self.products.api; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.UriInfo; + +import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants; +import org.apache.fineract.portfolio.loanproduct.api.LoanProductsApiResource; +import org.apache.fineract.portfolio.self.client.service.AppuserClientMapperReadService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +@Path("/self/loanproducts") +@Component +@Scope("singleton") +public class SelfLoanProductsApiResource { + + private final LoanProductsApiResource loanProductsApiResource; + private final AppuserClientMapperReadService appUserClientMapperReadService; + + @Autowired + public SelfLoanProductsApiResource(final LoanProductsApiResource loanProductsApiResource, + final AppuserClientMapperReadService appUserClientMapperReadService) { + this.loanProductsApiResource = loanProductsApiResource; + this.appUserClientMapperReadService = appUserClientMapperReadService; + + } + + @GET + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String retrieveAllLoanProducts(@QueryParam(LoanApiConstants.clientIdParameterName) final Long clientId, + @Context final UriInfo uriInfo) { + + this.appUserClientMapperReadService.validateAppuserClientsMapping(clientId); + return this.loanProductsApiResource.retrieveAllLoanProducts(uriInfo); + + } + + @GET + @Path("{productId}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String retrieveLoanProductDetails(@QueryParam(LoanApiConstants.clientIdParameterName) final Long clientId, + @PathParam(LoanApiConstants.productIdParameterName) final Long productId, @Context final UriInfo uriInfo) { + + this.appUserClientMapperReadService.validateAppuserClientsMapping(clientId); + return this.loanProductsApiResource.retrieveLoanProductDetails(productId, uriInfo); + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/products/api/SelfSavingsProductsApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/products/api/SelfSavingsProductsApiResource.java new file mode 100644 index 000000000..d3753637d --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/products/api/SelfSavingsProductsApiResource.java @@ -0,0 +1,78 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.fineract.portfolio.self.products.api; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.UriInfo; + +import org.apache.fineract.portfolio.savings.SavingsApiConstants; +import org.apache.fineract.portfolio.savings.api.SavingsProductsApiResource; +import org.apache.fineract.portfolio.self.client.service.AppuserClientMapperReadService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +@Path("/self/savingsproducts") +@Component +@Scope("singleton") +public class SelfSavingsProductsApiResource { + + private final SavingsProductsApiResource savingsProductsApiResource; + private final AppuserClientMapperReadService appUserClientMapperReadService; + + @Autowired + public SelfSavingsProductsApiResource(final SavingsProductsApiResource savingsProductsApiResource, + final AppuserClientMapperReadService appUserClientMapperReadService) { + this.savingsProductsApiResource = savingsProductsApiResource; + this.appUserClientMapperReadService = appUserClientMapperReadService; + + } + + @GET + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String retrieveAll(@QueryParam(SavingsApiConstants.clientIdParamName) final Long clientId, + @Context final UriInfo uriInfo) { + + this.appUserClientMapperReadService.validateAppuserClientsMapping(clientId); + return this.savingsProductsApiResource.retrieveAll(uriInfo); + + } + + @GET + @Path("{productId}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String retrieveOne(@PathParam(SavingsApiConstants.productIdParamName) final Long productId, + @QueryParam(SavingsApiConstants.clientIdParamName) final Long clientId, @Context final UriInfo uriInfo) { + + this.appUserClientMapperReadService.validateAppuserClientsMapping(clientId); + return this.savingsProductsApiResource.retrieveOne(productId, uriInfo); + + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/products/api/SelfShareProductsApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/products/api/SelfShareProductsApiResource.java new file mode 100644 index 000000000..97035d486 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/products/api/SelfShareProductsApiResource.java @@ -0,0 +1,79 @@ +/** + * 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.self.products.api; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.UriInfo; + +import org.apache.fineract.portfolio.accounts.constants.ShareAccountApiConstants; +import org.apache.fineract.portfolio.products.api.ProductsApiResource; +import org.apache.fineract.portfolio.self.client.service.AppuserClientMapperReadService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +@Path("/self/products/share") +@Component +@Scope("singleton") +public class SelfShareProductsApiResource { + + private final ProductsApiResource productsApiResource; + private final AppuserClientMapperReadService appUserClientMapperReadService; + + @Autowired + public SelfShareProductsApiResource(final ProductsApiResource productsApiResource, + final AppuserClientMapperReadService appUserClientMapperReadService) { + this.productsApiResource = productsApiResource; + this.appUserClientMapperReadService = appUserClientMapperReadService; + + } + + @GET + @Path("{productId}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String retrieveProduct(@QueryParam(ShareAccountApiConstants.clientid_paramname) final Long clientId, + @PathParam("productId") final Long productId, @PathParam("type") final String productType, + @Context final UriInfo uriInfo) { + this.appUserClientMapperReadService.validateAppuserClientsMapping(clientId); + return this.productsApiResource.retrieveProduct(productId, ShareAccountApiConstants.shareEntityType, uriInfo); + + } + + @GET + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String retrieveAllProducts(@QueryParam(ShareAccountApiConstants.clientid_paramname) final Long clientId, + @QueryParam("offset") final Integer offset, @QueryParam("limit") final Integer limit, + @Context final UriInfo uriInfo) { + this.appUserClientMapperReadService.validateAppuserClientsMapping(clientId); + return this.productsApiResource.retrieveAllProducts(ShareAccountApiConstants.shareEntityType, offset, limit, + uriInfo); + + } + +}