diff --git a/README.md b/README.md
index 3c50a82e8d..9b77fc77fa 100644
--- a/README.md
+++ b/README.md
@@ -21,7 +21,7 @@ curl TODO
## Backoffice screenshots
-
+
### Persons and accounts
@@ -61,6 +61,16 @@ You can set screening values from the "Person data" section ([More info](https:/
+### Seizure Protection
+When querying the balance for P-konto accounts, you will get a `seizure_protection` object as stated in this [API](https://docs.solarisgroup.com/api-reference/digital-banking/account-management/#tag/Accounts/paths/~1v1~1accounts~1{account_id}~1balance/get). Since solaris does not support changing an account to P-konto; we mocked the existence of seizure protection.
+
+You can modify the values of seizure protection in this section:
+
+
+
+You can also delete the object afterwards:
+
+
## Configuration
diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json
index f81843c802..665dd0fb0a 100644
--- a/npm-shrinkwrap.json
+++ b/npm-shrinkwrap.json
@@ -1,12 +1,12 @@
{
"name": "@kontist/mock-solaris",
- "version": "1.0.39",
+ "version": "1.0.54",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@kontist/mock-solaris",
- "version": "1.0.39",
+ "version": "1.0.54",
"license": "Apache-2.0",
"dependencies": {
"bluebird": "^3.4.7",
@@ -1753,9 +1753,7 @@
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
- "engines": [
- "node >=0.6.0"
- ]
+ "engines": ["node >=0.6.0"]
},
"node_modules/eyes": {
"version": "0.1.8",
@@ -1929,9 +1927,7 @@
"dev": true,
"hasInstallScript": true,
"optional": true,
- "os": [
- "darwin"
- ],
+ "os": ["darwin"],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
@@ -2936,9 +2932,7 @@
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
- "engines": [
- "node >=0.6.0"
- ],
+ "engines": ["node >=0.6.0"],
"dependencies": {
"assert-plus": "1.0.0",
"extsprintf": "1.3.0",
@@ -5251,9 +5245,7 @@
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
- "engines": [
- "node >=0.6.0"
- ],
+ "engines": ["node >=0.6.0"],
"dependencies": {
"assert-plus": "^1.0.0",
"core-util-is": "1.0.2",
diff --git a/package.json b/package.json
index c72d11659b..fc83d0a33b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@kontist/mock-solaris",
- "version": "1.0.49",
+ "version": "1.0.54",
"description": "Mock Service for Solaris API",
"main": "dist/src/index.js",
"types": "dist/src/index.d.ts",
diff --git a/src/app.ts b/src/app.ts
index 2cc36f6fba..496dabae30 100644
--- a/src/app.ts
+++ b/src/app.ts
@@ -605,6 +605,16 @@ app.post(
safeRequestHandler(standingOrdersAPI.triggerStandingOrderRequestHandler)
);
+// BACKOFFICE - SEIZURES PROTECTION
+app.post(
+ "/__BACKOFFICE__/addAccountSeizureProtection/:email",
+ safeRequestHandler(backofficeAPI.addAccountSeizureProtectionHandler)
+);
+app.post(
+ "/__BACKOFFICE__/deleteAccountSeizureProtection/:email",
+ safeRequestHandler(backofficeAPI.deleteAccountSeizureProtectionHandler)
+);
+
// BACKOFFICE - SEIZURES
app.post(
"/__BACKOFFICE__/createSeizure/:person_id",
diff --git a/src/db.ts b/src/db.ts
index 00cb1c36fa..72d9c6b5ad 100644
--- a/src/db.ts
+++ b/src/db.ts
@@ -3,7 +3,11 @@ import Promise from "bluebird";
import * as log from "./logger";
import { calculateOverdraftInterest } from "./helpers/overdraft";
-import { CustomerVettingStatus, RiskClarificationStatus, ScreeningProgress } from "./helpers/types";
+import {
+ CustomerVettingStatus,
+ RiskClarificationStatus,
+ ScreeningProgress,
+} from "./helpers/types";
let redis;
@@ -111,6 +115,7 @@ export const migrate = async () => {
available_balance: {
value: 100,
},
+ seizure_protection: null,
},
billing_account: {
id: process.env.SOLARIS_KONTIST_BILLING_ACCOUNT_ID,
diff --git a/src/routes/accounts.ts b/src/routes/accounts.ts
index 3c286b064d..35e978b94e 100644
--- a/src/routes/accounts.ts
+++ b/src/routes/accounts.ts
@@ -30,6 +30,7 @@ const DEFAULT_ACCOUNT = {
person_id: "66a692fdddc32c05ebe1c1f1c3145a3bcper",
status: "ACTIVE",
closure_reasons: null,
+ seizure_protection: null,
};
const requestAccountFields = [
@@ -73,17 +74,14 @@ export const showAccountBookings = async (req, res) => {
export const showAccountReservations = async (req, res) => {
const {
page: { size, number },
- filter: {
- reservation_type: reservationType,
- },
+ filter: { reservation_type: reservationType },
} = req.query;
const { account_id: accountId } = req.params;
const person = await findPersonByAccountId(accountId);
-
const reservations = _.get(person.account, "reservations", [])
- .filter(reservation => reservation.reservation_type === reservationType)
+ .filter((reservation) => reservation.reservation_type === reservationType)
.slice((number - 1) * size, number * size);
res.status(200).send(reservations);
@@ -206,7 +204,11 @@ export const createAccountSnapshot = async (req, res) => {
export const showAccountBalance = async (req, res) => {
const { account_id: accountId } = req.params;
const person = await findPersonByAccountId(accountId);
- const balance = _.pick(person.account, ["balance", "available_balance"]);
+ const balance = _.pick(person.account, [
+ "balance",
+ "available_balance",
+ "seizure_protection",
+ ]);
res.status(200).send(balance);
};
diff --git a/src/routes/backoffice.ts b/src/routes/backoffice.ts
index 32f57ac8ef..e693ad232e 100644
--- a/src/routes/backoffice.ts
+++ b/src/routes/backoffice.ts
@@ -13,11 +13,11 @@ import {
deleteMobileNumber,
saveSepaDirectDebitReturn,
getDevicesByPersonId,
- saveTaxIdentifications
+ saveTaxIdentifications,
} from "../db";
import {
createSepaDirectDebitReturn,
- triggerSepaDirectDebitReturnWebhook
+ triggerSepaDirectDebitReturnWebhook,
} from "../helpers/sepaDirectDebitReturn";
import { shouldReturnJSON } from "../helpers";
import { triggerWebhook } from "../helpers/webhooks";
@@ -37,11 +37,11 @@ import {
IdentificationStatus,
ScreeningProgress,
RiskClarificationStatus,
- CustomerVettingStatus
+ CustomerVettingStatus,
} from "../helpers/types";
import {
changeOverdraftApplicationStatus,
- issueInterestAccruedBooking
+ issueInterestAccruedBooking,
} from "../helpers/overdraft";
const triggerIdentificationWebhook = (payload) =>
@@ -56,7 +56,7 @@ const triggerAccountBlockWebhook = async (person) => {
business_id: null,
locking_status: lockingStatus,
updated_at: new Date().toISOString(),
- iban
+ iban,
};
await triggerWebhook(AccountWebhookEvent.ACCOUNT_BLOCK, payload);
@@ -67,6 +67,74 @@ export const triggerBookingsWebhook = async (solarisAccountId) => {
await triggerWebhook(TransactionWebhookEvent.BOOKING, payload);
};
+export const addAccountSeizureProtectionHandler = async (req, res) => {
+ const { email } = req.params;
+
+ const {
+ currentBlockedAmount,
+ protectedAmount,
+ protectedAmountExpiring,
+ protectedAmountExpiringDate,
+ } = req.body;
+
+ const persons = await getAllPersons();
+ const person = persons.find((item) => item.email === email);
+
+ if (!person?.account) return null;
+
+ person.account = {
+ ...person.account,
+ seizure_protection: {
+ current_blocked_amount: {
+ value: currentBlockedAmount,
+ currency: "EUR",
+ unit: "cents",
+ },
+ protected_amount: {
+ value: protectedAmount,
+ currency: "EUR",
+ unit: "cents",
+ },
+ protected_amount_expiring: {
+ value: protectedAmountExpiring,
+ currency: "EUR",
+ unit: "cents",
+ },
+ protected_amount_expiring_date: protectedAmountExpiringDate,
+ },
+ };
+
+ await savePerson(person);
+
+ if (shouldReturnJSON(req)) {
+ res.status(200).send(person.account);
+ } else {
+ res.redirect("back");
+ }
+};
+
+export const deleteAccountSeizureProtectionHandler = async (req, res) => {
+ const { email } = req.params;
+
+ const persons = await getAllPersons();
+ const person = persons.find((item) => item.email === email);
+
+ if (!person?.account) return null;
+
+ person.account = {
+ ...person.account,
+ seizure_protection: null,
+ };
+
+ await savePerson(person);
+
+ if (shouldReturnJSON(req)) {
+ res.status(204).send();
+ } else {
+ res.redirect("back");
+ }
+};
+
/**
* Handles changes on the provisioning token and redirects back to refresh data.
* Reads the personId and cardId from the url params and the status (if sent) from the body.
@@ -126,7 +194,7 @@ export const getPersonHandler = async (req, res) => {
if (!person) {
return res.status(HttpStatusCodes.NOT_FOUND).send({
message: "Couldn't find person",
- details: req.params
+ details: req.params,
});
}
@@ -143,7 +211,7 @@ export const getPersonHandler = async (req, res) => {
taxIdentifications,
devices,
identifications: person.identifications,
- SEIZURE_STATUSES
+ SEIZURE_STATUSES,
});
}
};
@@ -191,7 +259,7 @@ export const updatePersonHandler = async (req, res) => {
const shouldMarkMobileNumberAsVerified = (identification) =>
[
IdentificationStatus.PENDING_SUCCESSFUL,
- IdentificationStatus.SUCCESSFUL
+ IdentificationStatus.SUCCESSFUL,
].includes(identification.status) && identification.method === "idnow";
export const setIdentification = async (req, res) => {
@@ -206,7 +274,7 @@ export const setIdentification = async (req, res) => {
!(skipSettingScreeningValues === "true") &&
[
IdentificationStatus.SUCCESSFUL,
- IdentificationStatus.PENDING_SUCCESSFUL
+ IdentificationStatus.PENDING_SUCCESSFUL,
].includes(identification.status)
) {
person.screening_progress = ScreeningProgress.SCREENED_ACCEPTED;
@@ -231,7 +299,7 @@ export const setIdentification = async (req, res) => {
completed_at: identification.completed_at,
reference: identification.reference,
status: identification.status,
- method: "idnow"
+ method: "idnow",
});
res.status(204).send();
@@ -245,7 +313,7 @@ export const setScreening = async (req, res) => {
const {
screening_progress,
risk_classification_status,
- customer_vetting_status
+ customer_vetting_status,
} = req.body;
const person = (await getAllPersons()).find(
@@ -292,7 +360,7 @@ export const setIdentificationState = async (req, res) => {
!(skipSettingScreeningValues === "true") &&
[
IdentificationStatus.SUCCESSFUL,
- IdentificationStatus.PENDING_SUCCESSFUL
+ IdentificationStatus.PENDING_SUCCESSFUL,
].includes(identification.status)
) {
// TODO: assign these values manually from the backend tests and remove this
@@ -318,7 +386,7 @@ export const setIdentificationState = async (req, res) => {
completed_at: identification.completed_at,
reference: identification.reference,
method,
- status
+ status,
});
res.redirect(`/__BACKOFFICE__/person/${person.id}#identifications`);
@@ -345,8 +413,8 @@ const generateBookingFromStandingOrder = (standingOrder) => {
booking_date: moment().format("YYYY-MM-DD"),
booking_type: BookingType.SEPA_CREDIT_TRANSFER,
amount: {
- value: -Math.abs(standingOrder.amount.value)
- }
+ value: -Math.abs(standingOrder.amount.value),
+ },
};
};
@@ -392,7 +460,7 @@ export const processQueuedBooking = async (
const isDirectDebit = [
BookingType.DIRECT_DEBIT,
- BookingType.SEPA_DIRECT_DEBIT
+ BookingType.SEPA_DIRECT_DEBIT,
].includes(booking.booking_type);
const wouldOverdraw =
@@ -418,8 +486,8 @@ export const processQueuedBooking = async (
amount: {
value: booking.amount.value,
unit: "cents",
- currency: "EUR"
- }
+ currency: "EUR",
+ },
};
}
@@ -468,7 +536,7 @@ export const generateBookingForPerson = (bookingData) => {
transactionId,
bookingDate,
valutaDate,
- status
+ status,
} = bookingData;
const recipientName = `${person.salutation} ${person.first_name} ${person.last_name}`;
@@ -498,7 +566,7 @@ export const generateBookingForPerson = (bookingData) => {
booking_type: bookingType,
transaction_id: transactionId || uuid.v4(),
return_transaction_id: null,
- status
+ status,
};
};
@@ -522,7 +590,7 @@ export const queueBookingRequestHandler = async (req, res) => {
transactionId,
bookingDate,
valutaDate,
- status
+ status,
} = req.body;
senderName = senderName || "mocksolaris";
@@ -542,7 +610,7 @@ export const queueBookingRequestHandler = async (req, res) => {
transactionId,
bookingDate,
valutaDate,
- status
+ status,
});
person.queuedBookings.push(queuedBooking);
@@ -597,10 +665,10 @@ export const createDirectDebitReturn = async (personId, id) => {
amount: {
value: -directDebit.amount.value,
unit: "cents",
- currency: "EUR"
+ currency: "EUR",
},
booking_date: today,
- valuta_date: today
+ valuta_date: today,
};
person.transactions.push(directDebitReturn);
@@ -624,7 +692,7 @@ export const updateAccountLockingStatus = async (personId, lockingStatus) => {
person.account = {
...person.account,
- locking_status: lockingStatus
+ locking_status: lockingStatus,
};
await savePerson(person);
@@ -644,7 +712,7 @@ const changeCardStatusAllowed = async (personId, cardId, newCardStatus) => {
const cardData = person.account.cards.find(({ card }) => card.id === cardId);
const {
- card: { status: currentCardStatus, type }
+ card: { status: currentCardStatus, type },
} = cardData;
if (
@@ -668,7 +736,7 @@ const changeCardStatusAllowed = async (personId, cardId, newCardStatus) => {
CardStatus.INACTIVE,
CardStatus.PROCESSING,
CardStatus.CLOSED,
- CardStatus.CLOSED_BY_SOLARIS
+ CardStatus.CLOSED_BY_SOLARIS,
].includes(cardData.card.status)
) {
throw new Error(
@@ -695,7 +763,7 @@ export const createReservationHandler = async (req, res) => {
type,
recipient,
declineReason,
- posEntryMode
+ posEntryMode,
} = req.body;
if (!personId) {
@@ -714,7 +782,7 @@ export const createReservationHandler = async (req, res) => {
type,
recipient,
declineReason,
- posEntryMode
+ posEntryMode,
};
const reservation = await (type === TransactionType.CREDIT_PRESENTMENT
@@ -744,7 +812,7 @@ export const updateReservationHandler = async (req, res) => {
personId,
reservationId,
action,
- increaseAmount
+ increaseAmount,
});
res.redirect("back");
diff --git a/src/templates/person.html b/src/templates/person.html
index cbd5f2935c..be70f027b3 100644
--- a/src/templates/person.html
+++ b/src/templates/person.html
@@ -193,6 +193,64 @@
{{ JSON.stringify(person.account.seizure_protection, undefined, 2) }}+