generated from DEFRA/ffc-template-node
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
216e9bd
commit 8e760a8
Showing
26 changed files
with
1,196 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
|
||
const calculateDelta = async (paymentRequest, previousPaymentRequests) => { | ||
return [paymentRequest] | ||
} | ||
|
||
module.exports = calculateDelta |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
const db = require('../data') | ||
|
||
const completePaymentRequest = async (scheduleId, paymentRequests) => { | ||
const transaction = await db.sequelize.transaction() | ||
try { | ||
const schedule = await db.schedule.findByPk(scheduleId, { transaction }) | ||
|
||
// Check if completed already in case of duplicate processing | ||
if (schedule.completed === null) { | ||
await db.schedule.update({ completed: new Date() }, { where: { scheduleId }, transaction }) | ||
for (const paymentRequest of paymentRequests) { | ||
// Extract data values from Sequelize object if exists | ||
const completedPaymentRequest = paymentRequest.dataValues ?? paymentRequest | ||
const savedCompletedPaymentRequest = await db.completedPaymentRequest.create(completedPaymentRequest, { transaction }) | ||
for (const invoiceLine of paymentRequest.invoiceLines) { | ||
// Extract data values from Sequelize object if exists | ||
const completedInvoiceLine = invoiceLine.dataValues ?? invoiceLine | ||
completedInvoiceLine.completedPaymentRequestId = savedCompletedPaymentRequest.completedPaymentRequestId | ||
await db.completedInvoiceLine.create(completedInvoiceLine, { transaction }) | ||
} | ||
} | ||
} | ||
await transaction.commit() | ||
} catch (error) { | ||
await transaction.rollback() | ||
throw (error) | ||
} | ||
} | ||
|
||
module.exports = completePaymentRequest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
const db = require('../data') | ||
|
||
const getCompletedPaymentRequests = async (schemeId, frn, marketingYear) => { | ||
return db.completedPaymentRequest.findAll({ | ||
where: { | ||
schemeId, | ||
frn, | ||
marketingYear | ||
}, | ||
include: [{ | ||
model: db.completedInvoiceLine, | ||
as: 'invoiceLines' | ||
}] | ||
}) | ||
} | ||
|
||
module.exports = getCompletedPaymentRequests |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
const db = require('../data') | ||
const moment = require('moment') | ||
const config = require('../config') | ||
|
||
const getPaymentRequests = async (started = new Date()) => { | ||
const transaction = await db.sequelize.transaction() | ||
try { | ||
const paymentRequests = await getScheduledPaymentRequests(started, transaction) | ||
const paymentRequestsWithoutPending = await removePending(paymentRequests, started, transaction) | ||
const paymentRequestsWithoutHolds = await removeHolds(paymentRequestsWithoutPending, transaction) | ||
const uniquePaymentRequests = removeDuplicates(paymentRequestsWithoutHolds) | ||
const cappedPaymentRequests = restrictToBatchSize(uniquePaymentRequests) | ||
await updateScheduled(cappedPaymentRequests, started, transaction) | ||
await transaction.commit() | ||
return cappedPaymentRequests | ||
} catch (error) { | ||
await transaction.rollback() | ||
throw (error) | ||
} | ||
} | ||
|
||
const getScheduledPaymentRequests = async (started, transaction) => { | ||
return db.schedule.findAll({ | ||
transaction, | ||
order: ['planned'], | ||
include: [{ | ||
model: db.paymentRequest, | ||
as: 'paymentRequest', | ||
required: true, | ||
include: [{ | ||
model: db.invoiceLine, | ||
as: 'invoiceLines', | ||
required: true | ||
}, { | ||
model: db.scheme, | ||
as: 'scheme', | ||
required: true | ||
}] | ||
}], | ||
where: { | ||
'$paymentRequest.scheme.active$': true, | ||
planned: { [db.Sequelize.Op.lte]: started }, | ||
completed: null, | ||
[db.Sequelize.Op.or]: [{ | ||
started: null | ||
}, { | ||
started: { [db.Sequelize.Op.lte]: moment(started).subtract(5, 'minutes').toDate() } | ||
}] | ||
} | ||
}) | ||
} | ||
|
||
const removePending = async (scheduledPaymentRequests, started, transaction) => { | ||
const pending = await getPending(started, transaction) | ||
return scheduledPaymentRequests.filter(x => | ||
!pending.some(y => y.paymentRequest.schemeId === x.paymentRequest.schemeId && y.paymentRequest.frn === x.paymentRequest.frn && y.paymentRequest.marketingYear === x.paymentRequest.marketingYear)) | ||
} | ||
|
||
const getPending = async (started, transaction) => { | ||
return db.schedule.findAll({ | ||
where: { | ||
completed: null, | ||
started: { [db.Sequelize.Op.gt]: moment(started).subtract(5, 'minutes').toDate() } | ||
}, | ||
include: [{ | ||
model: db.paymentRequest, | ||
as: 'paymentRequest' | ||
}], | ||
transaction | ||
}) | ||
} | ||
|
||
const removeHolds = async (scheduledPaymentRequests, transaction) => { | ||
const holds = await getHolds(transaction) | ||
return scheduledPaymentRequests.filter(x => | ||
!holds.some(y => y.holdCategory.schemeId === x.paymentRequest.schemeId && y.frn === x.paymentRequest.frn)) | ||
} | ||
|
||
const getHolds = async (transaction) => { | ||
return db.hold.findAll({ | ||
where: { closed: null }, | ||
include: [{ | ||
model: db.holdCategory, | ||
as: 'holdCategory' | ||
}], | ||
transaction | ||
}) | ||
} | ||
|
||
const removeDuplicates = (scheduledPaymentRequests) => { | ||
return scheduledPaymentRequests.reduce((x, y) => { | ||
const isDuplicate = (currentSchedule) => { | ||
return x.some((schedule) => { | ||
return (schedule.paymentRequest.schemeId === currentSchedule.paymentRequest.schemeId && | ||
schedule.paymentRequest.frn === currentSchedule.paymentRequest.frn && | ||
schedule.paymentRequest.marketingYear === currentSchedule.paymentRequest.marketingYear) | ||
}) | ||
} | ||
|
||
if (isDuplicate(y)) { | ||
return x | ||
} else { | ||
return [...x, y] | ||
} | ||
}, []) | ||
} | ||
|
||
const restrictToBatchSize = (scheduledPaymentRequests) => { | ||
return scheduledPaymentRequests.slice(0, config.processingBatchSize) | ||
} | ||
|
||
const updateScheduled = async (scheduledPaymentRequests, started, transaction) => { | ||
for (const scheduledPaymentRequest of scheduledPaymentRequests) { | ||
await db.schedule.update({ started }, { | ||
where: { | ||
scheduleId: scheduledPaymentRequest.scheduleId | ||
}, | ||
transaction | ||
}) | ||
} | ||
} | ||
|
||
module.exports = getPaymentRequests |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
const processPaymentRequests = require('./process-payment-requests') | ||
const config = require('../config') | ||
|
||
const start = async () => { | ||
try { | ||
await processPaymentRequests() | ||
} catch (err) { | ||
console.error(err) | ||
} finally { | ||
setTimeout(start, config.paymentProcessingInterval) | ||
} | ||
} | ||
|
||
module.exports = { | ||
start | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
const db = require('../data') | ||
|
||
const mapAccountCodes = async (paymentRequest) => { | ||
for (const invoiceLine of paymentRequest.invoiceLines) { | ||
const accountCode = await db.accountCode.findOne({ | ||
include: [{ | ||
model: db.schemeCode, | ||
as: 'schemeCode' | ||
}], | ||
where: { | ||
'$schemeCode.schemeCode$': invoiceLine.schemeCode, | ||
lineDescription: invoiceLine.description | ||
} | ||
}) | ||
|
||
invoiceLine.accountCode = paymentRequest.ledger === 'AP' ? accountCode.accountCodeAP : accountCode.accountCodeAR | ||
} | ||
} | ||
|
||
module.exports = mapAccountCodes |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
const getPaymentRequests = require('./get-payment-requests') | ||
const mapAccountCodes = require('./map-account-codes') | ||
const completePaymentRequests = require('./complete-payment-requests') | ||
const transformPaymentRequest = require('./transform-payment-request') | ||
|
||
const processPaymentRequests = async () => { | ||
const scheduledPaymentRequests = await getPaymentRequests() | ||
for (const scheduledPaymentRequest of scheduledPaymentRequests) { | ||
await processPaymentRequest(scheduledPaymentRequest) | ||
} | ||
} | ||
|
||
const processPaymentRequest = async (scheduledPaymentRequest) => { | ||
const paymentRequests = await transformPaymentRequest(scheduledPaymentRequest.paymentRequest) | ||
for (const paymentRequest of paymentRequests) { | ||
await mapAccountCodes(paymentRequest) | ||
} | ||
await completePaymentRequests(scheduledPaymentRequest.scheduleId, paymentRequests) | ||
} | ||
|
||
module.exports = processPaymentRequests |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
const calculateDelta = require('./calculate-delta') | ||
const getCompletedPaymentRequests = require('./get-completed-payment-requests') | ||
|
||
const transformPaymentRequest = async (paymentRequest) => { | ||
// Check to see if payment request has had a previous payment request. | ||
// if yes, need to treat as post payment adjustment and calculate Delta which can result in payment request splitting | ||
const previousPaymentRequests = await getCompletedPaymentRequests(paymentRequest.schemeId, paymentRequest.frn, paymentRequest.marketingYear) | ||
if (previousPaymentRequests.length) { | ||
return calculateDelta(paymentRequest, previousPaymentRequests) | ||
} | ||
// otherwise original payment request does not require further processing so can be returned without modification | ||
return [paymentRequest] | ||
} | ||
|
||
module.exports = transformPaymentRequest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<?xml version="1.1" encoding="UTF-8" standalone="no"?> | ||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:pro="http://www.liquibase.org/xml/ns/pro" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-3.9.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.9.xsd"> | ||
<changeSet author="John Watson" id="36"> | ||
<tagDatabase tag="v1.3.0" /> | ||
</changeSet> | ||
<changeSet author="John Watson" id="37"> | ||
<addColumn tableName="invoiceLines"> | ||
<column name="schemeCode" afterColumn="sbi" type="VARCHAR(10)" /> | ||
</addColumn> | ||
<addColumn tableName="completedInvoiceLines"> | ||
<column name="schemeCode" afterColumn="sbi" type="VARCHAR(10)" /> | ||
</addColumn> | ||
</changeSet> | ||
</databaseChangeLog> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.