Skip to content

Commit

Permalink
Settlement v2 (#271)
Browse files Browse the repository at this point in the history
* feature/1095 Close Settlement Window Changes (#220)

* Refactor scripts tree structure

* Dependencies upgrade

* Changed server setup and init. Registered Settlement Window Handler. Added CLI handler management. Shortened {id} paths. Window to PROCESSING state. Settlement window producer. Settlement window consumer. Default config added. Updated package.json scripts

* Added broker service health check

* SettlementWindowHandler ErrorHandling and async-retry

* Fix unit tests. Coverage fails at 91.32%

* SettlementWindowHandler Processing

* Fix integration tests

* Switched the latest release of central-services-shared

* Added unit test for API index.js . Code coverage now 89.5 percent

* Removed unnecessary commented lines from test

* Added unit tests for lib/healthcheck

* feature/1096 Create Settlement Changes #1 (#224)

* Changed swagger definition

* Settlement model validation. Unit tests fail

* select distinct

* Settlement window content validation. Fixed unit tests

* Deleted code to fix the two plugin issues and unit test for Handler - index.js

* feature/1097 Create Settlement Changes #2 (#225)

* Implemented inserts (not tested). Changed response definition. Unit tests fail

* Generate response. Validate proper implementation. Disable failing unit tests to be adjusted

* feature/1099 Update Settlement by ID Changes (#229)

* Implement updateSettlementByIdChanges enhancement

* Entire settlement process verified using various scenarios. Corrections made where applicable

* feature/1165 Unit tests for central-settlement part1

* Completed the unit test for register handlers code.

* Domain settlement windows close , added unit test

* Added more unit testing code to the settlement  windows models facade

* Added unit tests and fixed existing ones  to cover unhappy lines in process

* Added unit tests to shared/setup to cope with the service types

* Added unit test for shared setup : handler service type - and run handler true without any modules.

* Added unit test for settlement window with a handler list

* Added unit test to increase code coverage for settlement window facade

* Add unit test testing the settlement window state "not Processing"

* Added unit test to roll back settlement window facade when error occurs

* Added unit test on process to cover rollback on critical error and updated the version on central services shared to "8.8.2",

* Added unit testcode to close window

* Fixed the knex raw and .join isn't a function errors

* Changes:

- Added a unit test file and unit tests for SettlementWindow handler
- Made some fixes on the SettlementWindow handler

* Added last unit test on the facade. the tests are being ran in isolation still.

* Added last knex builder stubs to facade unit tests

* Combined the Stubs for the facade

* Worked on branches to increase covereage

Co-authored-by: lazolalucas <lazolalucas@users.noreply.github.com>

* feature/1100 Settlement By Currency Wrap Up (#231)

* Fixed and extended integration testing for settlement-v2

* Add anchore summary report upload, bump package version to 8.8.0 (#230)

* Full coverage for domain/settlement/index & models/lib/enums

* Full coverage for inculded scripts

* Integration testing config to run properly

* Finilize unit tests and full coverage

Co-authored-by: Lewis Daly <lewisdaly@me.com>

* Feature/1180 enhance get settlement windows by (#238)

* Added code changes to DAO and handler to include settlementwindow content

* Added code changes to DAO and handler to include settlementwindow content

* Added code changes to unit test to increase code coverage

* Changed code to fix the integration error

* Code review changes : added  SettlementWindowContentModel.getBySettlementWindowId function. Unit tests are still failing

* Code review changes : Added unit test and fixed unit tests to increase code coverage.

* Code review II : Removed settlement window id from response object and added settlement id to it.

* Trigger a rebuild. Previous commit failed due to internet failure

* Updated swagger definition with the settlementId as integer on the settlementWindowContent

* Fixed vulnerabilities

* feature/1211 Auto position reset (#240)

* Auto position reset functionality

* Re-run integration tests

* Use newest central-ledger snapshot release for integration tests

* feature/1209 Restrict Create Settlement (#249)

* Forbid GROSS/IMMEDATE models, when creating new settlement

* Corrected typo as per PR request

* Feature/926 enhanced get settlement windows by params (#254)

*  feature/926-EnhancegetSettlementWindowsByParams

 - Enhanced getSettlementWindowsByParams to query with currency param
 - Updated the response object to include content

*  feature/926-EnhancegetSettlementWindowsByParams

 - Enhanced getSettlementWindowsByParams to query with currency param
 - Updated the response object to include content

*  feature/926-EnhancegetSettlementWindowsByParams

 - Enhanced getSettlementWindowsByParams to query with currency param
 - Updated the response object to include content

* Added async-retry

* - Update the facade to be able to query using currency
- removed the caret sign ^ from package.json

* - Trigger rebuild

* Prepare version for PR against master

* Trigger circle CI re-run

* Downgrade @mojaloop/central-services-database due to integration tests failure

* Address PR review request and update dependencies

* Updated dependancy

* Another test for integration tests

* Feature/1241 get settlements by params to include currency (#268)

* Re-do code changes to the updated settlements v2

* Added async-retry

* Remove caret in package.json

* Fixed the filtering on the settlement window(s) per settlement id, added unit test

* Fixed the filtering on the settlement window(s) per settlement id, added unit test

* Fixed vulnerabilities

* Removed the settlement model line in the response object

* Removed the settlement model line in the response object

* update central ledger

* Fix vulnerability

* attempt to fix vulnerability

* Updated Happi to version 19.1.1

* Fixed the filtering on the settlement window(s) per settlement id, added unit test

* Crazy shit happening

* test commit

* Fixed code review changes

* Re-trigger pull request

* Revert Recreate DB script

* Updated Hapi to LTS version

* * Fixed get settlement by params
* Included content on the response object

* * Fixed Circle ci tests failing

* Trigger a rebuild

* Removed cache for dependencies under unit test/coverage

* Updated circle ci config.yml

* Updated circle ci config.yml

Co-authored-by: deonbotha <deon.botha@modusbox.com>

* Enhance central-settlement : Return settlement window content for every settlement window when getting settlements by id. (#263)

* Re-do code changes to the updated settlements v2

* Added async-retry

* Remove caret in package.json

* Fixed the filtering on the settlement window(s) per settlement id, added unit test

* Fixed the filtering on the settlement window(s) per settlement id, added unit test

* Fixed vulnerabilities

* Removed the settlement model line in the response object

* Removed the settlement model line in the response object

* update central ledger

* Fix vulnerability

* attempt to fix vulnerability

* Updated Happi to version 19.1.1

* Fixed the filtering on the settlement window(s) per settlement id, added unit test

* Crazy shit happening

* test commit

* Fixed code review changes

* Re-trigger pull request

* Revert Recreate DB script

* Updated Hapi to LTS version

* Added Neal's code review changes for pull request 263

* Update vulnerability issue

* Replaced the recursive delete object logic by a "map over"

* Ignore the vulnerablity rewire > eslint > espree > acorn for a week

Co-authored-by: Georgi Georgiev <georgi.georgiev@modusbox.com>
Co-authored-by: Deon Botha <darkwingduck@Deons-MacBook-Pro.local>
Co-authored-by: lazolalucas <lazolalucas@users.noreply.github.com>
Co-authored-by: Lewis Daly <lewisdaly@me.com>
  • Loading branch information
5 people authored Mar 9, 2020
1 parent 895f326 commit 85614de
Show file tree
Hide file tree
Showing 12 changed files with 606 additions and 264 deletions.
237 changes: 162 additions & 75 deletions .circleci/config.yml

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions audit-resolve.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
"decision": "ignore",
"madeAt": 1582888595088,
"expiresAt": 1585480556972
},
"1488|rewire>eslint>espree>acorn": {
"decision": "ignore",
"madeAt": 1583750630347,
"expiresAt": 1584355380671
}
},
"rules": {},
Expand Down
429 changes: 272 additions & 157 deletions package-lock.json

Large diffs are not rendered by default.

11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "central-settlement",
"description": "Central settlements hosted by a scheme to record and make settlements",
"description": "Central settlements hosted by a scheme to record and make settlements.",
"version": "9.2.2",
"license": "Apache-2.0",
"private": false,
Expand All @@ -10,7 +10,8 @@
"Valentin Genev <valentin.genev@modusbox.com>",
"Deon Botha <deon.botha@modusbox.com>",
"Miguel de Barros <miguel.debarros@modusbox.com>",
"Rajiv Mothilal <rajiv.mothilal@modusbox.com>"
"Rajiv Mothilal <rajiv.mothilal@modusbox.com>",
"Lazola Lucas <lazola.lucas@modusbox.com>"
],
"repository": {
"type": "git",
Expand All @@ -33,7 +34,7 @@
"@mojaloop/central-services-error-handling": "9.1.0",
"@mojaloop/central-services-health": "9.2.0",
"@mojaloop/central-services-logger": "9.1.0",
"@mojaloop/central-services-shared": "9.2.0",
"@mojaloop/central-services-shared": "9.3.0",
"@mojaloop/central-services-stream": "9.2.0",
"@mojaloop/ml-number": "8.2.0",
"@now-ims/hapi-now-auth": "2.0.1",
Expand All @@ -57,7 +58,7 @@
"node-fetch": "2.6.0",
"nodemon": "2.0.2",
"npm-audit-resolver": "2.2.0",
"npm-check-updates": "4.0.2",
"npm-check-updates": "4.0.4",
"nyc": "15.0.0",
"pre-commit": "1.2.2",
"proxyquire": "2.1.3",
Expand All @@ -66,7 +67,7 @@
"standard": "14.3.1",
"swagmock": "1.0.0",
"tap-xunit": "2.4.1",
"tape": "4.13.0",
"tape": "4.13.2",
"tapes": "4.1.0"
},
"pre-commit": [
Expand Down
39 changes: 29 additions & 10 deletions src/domain/settlement/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,25 @@ module.exports = {
const settlementWindowsList = await SettlementWindowModel.getBySettlementId({ settlementId }, enums)
const participantCurrenciesList = await SettlementModel.settlementParticipantCurrency.getParticipantCurrencyBySettlementId({ settlementId }, enums)
const participants = prepareParticipantsResult(participantCurrenciesList)

// Build settlement window content array and insert into settlement window list object
const windowContentRecords = []
let windowContentResponseData = {}

for (var key of Object.keys(settlementWindowsList)) {
const windowContentRecord = await SettlementWindowContentModel.getBySettlementAndWindowId(settlementId, settlementWindowsList[key].id)
windowContentResponseData = {
id: windowContentRecord[key].id,
state: windowContentRecord[key].state,
ledgerAccountType: windowContentRecord[key].ledgerAccountType,
currencyId: windowContentRecord[key].currencyId,
createdDate: windowContentRecord[key].createdDate,
changedDate: windowContentRecord[key].changedDate
}
windowContentRecords.push(windowContentResponseData)
settlementWindowsList[key].content = windowContentRecords
}

return {
id: settlement.settlementId,
state: settlement.state,
Expand Down Expand Up @@ -119,24 +138,24 @@ module.exports = {
if (settlementsData && settlementsData.length > 0) {
for (const s of settlementsData) {
if (!settlements[s.settlementId]) {
const settlementId = s.settlementId
const settlementWindowsList = await SettlementWindowModel.getBySettlementId({ settlementId })
for (var key of Object.keys(settlementWindowsList)) {
settlementWindowsList[key].content = await SettlementWindowContentModel.getBySettlementAndWindowId(s.settlementId, settlementWindowsList[key].id)
}
settlements[s.settlementId] = {
id: s.settlementId,
state: s.settlementStateId
state: s.settlementStateId,
reason: s.settlementWindowReason,
createdDate: s.createdDate,
changedDate: s.changedDate,
settlementWindows: settlementWindowsList
}
}
settlement = settlements[s.settlementId]
if (!settlement.settlementWindows) {
settlement.settlementWindows = {}
}
if (!settlement.settlementWindows[s.settlementWindowId]) {
settlement.settlementWindows[s.settlementWindowId] = {
id: s.settlementWindowId,
state: s.settlementWindowStateId,
reason: s.settlementWindowReason,
createdDate: s.createdDate,
changedDate: s.changedDate
}
}
if (!settlement.participants) {
settlement.participants = {}
}
Expand Down
11 changes: 3 additions & 8 deletions src/models/settlement/facade.js
Original file line number Diff line number Diff line change
Expand Up @@ -1332,6 +1332,7 @@ const Facade = {
return builder
.join('settlementStateChange AS ssc', 'ssc.settlementStateChangeId', 'settlement.currentStateChangeId')
.select('settlement.settlementId',
'settlement.settlementModelId',
'ssc.settlementStateId AS state',
'ssc.reason',
'settlement.createdDate',
Expand All @@ -1348,14 +1349,8 @@ const Facade = {
.innerJoin('settlementSettlementWindow AS ssw', 'ssw.settlementId', 'settlement.settlementId')
.innerJoin('settlementWindow AS sw', 'sw.settlementWindowId', 'ssw.settlementWindowId')
.innerJoin('settlementWindowStateChange AS swsc', 'swsc.settlementWindowStateChangeId', 'sw.currentStateChangeId')
.innerJoin('settlementTransferParticipant AS stp', function () {
this.on('stp.settlementId', 'settlement.settlementId')
.andOn('stp.settlementWindowId', 'sw.settlementWindowId')
})
.innerJoin('settlementParticipantCurrency AS spc', function () {
this.on('spc.settlementId', 'stp.settlementId')
.andOn('spc.participantCurrencyId', 'stp.participantCurrencyId')
})
.innerJoin('settlementContentAggregation AS sca', 'sca.settlementId', 'settlement.settlementId')
.innerJoin('settlementParticipantCurrency AS spc', 'spc.settlementId', 'sca.settlementId')
.innerJoin('settlementParticipantCurrencyStateChange AS spcsc', 'spcsc.settlementParticipantCurrencyStateChangeId', 'spc.currentStateChangeId')
.innerJoin('participantCurrency AS pc', 'pc.participantCurrencyId', 'spc.participantCurrencyId')
.distinct('settlement.settlementId', 'ssc.settlementStateId', 'ssw.settlementWindowId',
Expand Down
9 changes: 9 additions & 0 deletions src/models/settlementWindowContent/facade.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ const Facade = {
.where('swc.settlementWindowId', id)
.select('swc.settlementWindowContentId AS id', 'swcsc.settlementWindowStateId AS state',
'lat.name AS ledgerAccountType', 'swc.currencyId', 'swc.createdDate', 'swcsc.createdDate AS changedDate', 'swc.settlementId')
},
getBySettlementAndWindowId: async (settlementId, settlementWindowId) => {
const knex = await Db.getKnex()
return knex('settlementWindowContent AS swc')
.join('settlementWindowContentStateChange AS swcsc', 'swcsc.settlementWindowContentStateChangeId', 'swc.currentStateChangeId')
.join('ledgerAccountType AS lat', 'lat.ledgerAccountTypeId', 'swc.ledgerAccountTypeId')
.where({ 'swc.settlementId': settlementId, 'swc.settlementWindowId': settlementWindowId })
.select('swc.settlementWindowContentId AS id', 'swc.settlementWindowId', 'swcsc.settlementWindowStateId AS state',
'lat.name AS ledgerAccountType', 'swc.currencyId', 'swc.createdDate', 'swcsc.createdDate AS changedDate')
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/models/settlementWindowContent/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@ module.exports = {
createSettlementWindowContentState: SettlementWindowContentStateChangeModel.create,
getApplicableByWindowIdList: Facade.getApplicableByWindowIdList,
getBySettlementId: Facade.getBySettlementId,
getBySettlementWindowId: Facade.getBySettlementWindowId
getBySettlementWindowId: Facade.getBySettlementWindowId,
getBySettlementAndWindowId: Facade.getBySettlementAndWindowId
}
67 changes: 66 additions & 1 deletion test/unit/domain/settlement/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ Test('SettlementService', async (settlementServiceTest) => {
await settlementServiceTest.test('getById should', async getByIdTest => {
try {
const settlementId = 1
const settlementWindowId = 1
const enums = {}
const options = {
logger: Logger
Expand All @@ -62,6 +63,26 @@ Test('SettlementService', async (settlementServiceTest) => {
id: 1,
state: 'PENDING_SETTLEMENT'
}]
const settlementWindowContentMock = [
{
id: 10,
state: 'PENDING_SETTLEMENT',
ledgerAccountType: 'POSITION',
currencyId: 'USD',
createdDate: '2020-02-07T11:07:07.000Z',
changedDate: '2020-02-07T09:07:07.000Z',
settlementId: 6
},
{
id: 11,
state: 'CLOSED',
ledgerAccountType: 'POSITION',
currencyId: 'TZS',
createdDate: '2020-02-07T11:07:07.000Z',
changedDate: '2020-02-07T11:07:07.000Z',
settlementId: null
}
]
const participantCurrenciesListMock = [{
id: 1,
participantCurrencyId: 1,
Expand All @@ -79,11 +100,26 @@ Test('SettlementService', async (settlementServiceTest) => {
currency: 'ZAR',
key: 2
}]
const settlementModelModelNameMock = {
settlementModelId: 1,
name: 'DEFERRED_NET',
isActive: 1,
settlementGranularityId: 2,
settlementInterchangeId: 2,
settlementDelayId: 2,
currencyId: null,
requireLiquidityCheck: 1,
ledgerAccountTypeId: 1,
autoPositionReset: 1
}

SettlementModel.getById = sandbox.stub().returns(settlementMock)
SettlementWindowModel.getBySettlementId = sandbox.stub().returns(settlementWindowsListMock)
SettlementModel.settlementParticipantCurrency = {
getParticipantCurrencyBySettlementId: sandbox.stub().returns(participantCurrenciesListMock)
}
SettlementWindowContentModel.getBySettlementAndWindowId = sandbox.stub().returns(settlementWindowContentMock)
SettlementModelModel.getById = sandbox.stub().returns(settlementModelModelNameMock)

await getByIdTest.test('return settlement participant accounts', async test => {
try {
Expand All @@ -92,6 +128,7 @@ Test('SettlementService', async (settlementServiceTest) => {
test.ok(SettlementModel.getById.withArgs({ settlementId }, enums).calledOnce, 'SettlementModel.getById with args ... called once')
test.ok(SettlementWindowModel.getBySettlementId.withArgs({ settlementId }, enums).calledOnce, 'SettlementWindowModel.getBySettlementId with args ... called once')
test.ok(SettlementModel.settlementParticipantCurrency.getParticipantCurrencyBySettlementId.withArgs({ settlementId }, enums).calledOnce, 'SettlementModel.spc.getParticipantCurrencyBySettlementId with args ... called once')
test.ok(SettlementWindowContentModel.getBySettlementAndWindowId.withArgs(settlementId, settlementWindowId).calledOnce, 'SettlementWindowContentModel.getBySettlementAndWindowId with args ... called once')
test.end()
} catch (err) {
Logger.error(`getByIdTest failed with error - ${err}`)
Expand Down Expand Up @@ -146,6 +183,33 @@ Test('SettlementService', async (settlementServiceTest) => {
const options = {
logger: Logger
}
const settlementWindowContentMock = [
{
id: 10,
state: 'PENDING_SETTLEMENT',
ledgerAccountType: 'POSITION',
currencyId: 'USD',
createdDate: '2020-02-07T11:07:07.000Z',
changedDate: '2020-02-07T09:07:07.000Z',
settlementId: 6

},
{
id: 11,
state: 'CLOSED',
ledgerAccountType: 'POSITION',
currencyId: 'TZS',
createdDate: '2020-02-07T11:07:07.000Z',
changedDate: '2020-02-07T11:07:07.000Z',
settlementId: null

}
]
const settlementWindowsListMock = [{
id: 1,
state: 'PENDING_SETTLEMENT',
reason: 'settlement window reason text'
}]
const settlementsMockData = [{
settlementId: 1,
settlementStateId: 'PENDING_SETTLEMENT',
Expand Down Expand Up @@ -175,8 +239,9 @@ Test('SettlementService', async (settlementServiceTest) => {
accountAmount: 100,
accountCurrency: 'USD'
}]
SettlementWindowModel.getBySettlementId = sandbox.stub().returns(settlementWindowsListMock)
SettlementWindowContentModel.getBySettlementAndWindowId = sandbox.stub().returns(settlementWindowContentMock)
SettlementModel.getByParams = sandbox.stub().returns(settlementsMockData)

await getSettlementsByParamsTest.test('return settlement participant accounts', async test => {
try {
const result = await SettlementService.getSettlementsByParams(params, enums, options)
Expand Down
8 changes: 2 additions & 6 deletions test/unit/models/settlement/facade.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4038,17 +4038,13 @@ Test('Settlement facade', async (settlementFacadeTest) => {
context.on.returns({
andOn: sandbox.stub()
})
const innerJoin5 = sandbox.stub()
innerJoin5.callsArgOn(1, context)
const innerJoin6 = sandbox.stub()
innerJoin6.callsArgOn(1, context)

builderStub.innerJoin.returns({
innerJoin: sandbox.stub().returns({
innerJoin: sandbox.stub().returns({
innerJoin: sandbox.stub().returns({
innerJoin: innerJoin5.returns({
innerJoin: innerJoin6.returns({
innerJoin: sandbox.stub().returns({
innerJoin: sandbox.stub().returns({
innerJoin: sandbox.stub().returns({
innerJoin: sandbox.stub().returns({
distinct: sandbox.stub().returns({
Expand Down
1 change: 0 additions & 1 deletion test/unit/models/settlement/settlementModel.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,5 @@ Test('SettlementModelModel', async (settlementModelModelTest) => {
test.end()
}
})

settlementModelModelTest.end()
})
50 changes: 50 additions & 0 deletions test/unit/models/settlementWindowContent/facade.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -211,5 +211,55 @@ Test('SettlementWindowContentFacade', async (settlementWindowContentModelTest) =
}
})

await settlementWindowContentModelTest.test('getBySettlementAndWindowId', async getBySettlementWindowContentIdTest => {
try {
await getBySettlementWindowContentIdTest.test('return content for a specific settlementId and windowId ', async test => {
try {
const settlementId = 1
const settlementWindowId = 1
const settlementWindowContent = [{
id: 1,
settlementWindowId: 1,
state: 'PENDING_SETTLEMENT',
ledgerAccountType: 1,
currencyId: 'USD',
createdDate: 'date',
changedDate: 'date'
}, {
id: 2,
settlementWindowId: 1,
state: 'SETTLED',
ledgerAccountType: 6,
currencyId: 'USD',
createdDate: 'date',
changedDate: 'date'
}]
Db.getKnex = sandbox.stub()
const knexStub = sandbox.stub()
Db.getKnex.returns(knexStub)
knexStub.returns({
join: sandbox.stub().returns({
join: sandbox.stub().returns({
where: sandbox.stub().returns({
select: sandbox.stub().returns(settlementWindowContent)
})
})
})
})
const result = await SettlementWindowContentFacade.getBySettlementAndWindowId(settlementId, settlementWindowId)
test.deepEqual(result, settlementWindowContent, 'results match')
test.end()
} catch (err) {
test.pass('Error thrown')
test.end()
}
})
await getBySettlementWindowContentIdTest.end()
} catch (err) {
Logger.error(`getBySettlementWindowContentIdTest failed with error - ${err}`)
getBySettlementWindowContentIdTest.fail()
getBySettlementWindowContentIdTest.end()
}
})
await settlementWindowContentModelTest.end()
})

0 comments on commit 85614de

Please sign in to comment.