Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add payments by product backend validation #7077

Merged
merged 11 commits into from
Feb 14, 2024
148 changes: 145 additions & 3 deletions src/app/modules/payments/__tests__/payments.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,147 @@ describe('payments.service', () => {
InvalidPaymentProductsError,
)
expect(result._unsafeUnwrapErr().message).toContain(
'Invalid product selected.',
'There has been a change in the products available.',
)
})

it('should return with error if the description has changed', () => {
// Arrange
const mockInvalidProductSubmission: ProductItem[] = [
{
data: {
...mockValidProduct,
description: 'some other description',
_id: new ObjectId(),
} as unknown as Product,
quantity: 1,
selected: true,
},
{
data: mockValidProduct,
quantity: 1,
selected: true,
},
]

// Act
const result = PaymentsService.validatePaymentProducts(
mockValidProductsDefinition,
mockInvalidProductSubmission,
)

// Assert
expect(result.isErr()).toBeTrue()
expect(result._unsafeUnwrapErr()).toBeInstanceOf(
InvalidPaymentProductsError,
)
expect(result._unsafeUnwrapErr().message).toContain(
'There has been a change in the products available.',
)
})

it('should return with error if the name has changed', () => {
// Arrange
const mockInvalidProductSubmission: ProductItem[] = [
{
data: {
...mockValidProduct,
name: 'some other name',
_id: new ObjectId(),
} as unknown as Product,
quantity: 1,
selected: true,
},
{
data: mockValidProduct,
quantity: 1,
selected: true,
},
]

// Act
const result = PaymentsService.validatePaymentProducts(
mockValidProductsDefinition,
mockInvalidProductSubmission,
)

// Assert
expect(result.isErr()).toBeTrue()
expect(result._unsafeUnwrapErr()).toBeInstanceOf(
InvalidPaymentProductsError,
)
expect(result._unsafeUnwrapErr().message).toContain(
'There has been a change in the products available.',
)
})

it('should return with error if multi_qty has changed', () => {
// Arrange
const mockInvalidProductSubmission: ProductItem[] = [
{
data: {
...mockValidProduct,
multi_qty: true,
_id: new ObjectId(),
} as unknown as Product,
quantity: 1,
selected: true,
},
{
data: mockValidProduct,
quantity: 1,
selected: true,
},
]

// Act
const result = PaymentsService.validatePaymentProducts(
mockValidProductsDefinition,
mockInvalidProductSubmission,
)

// Assert
expect(result.isErr()).toBeTrue()
expect(result._unsafeUnwrapErr()).toBeInstanceOf(
InvalidPaymentProductsError,
)
expect(result._unsafeUnwrapErr().message).toContain(
'There has been a change in the products available.',
)
})

it('should return with error if the max_qty has changed', () => {
// Arrange
const mockInvalidProductSubmission: ProductItem[] = [
{
data: {
...mockValidProduct,
max_qty: 5,
_id: new ObjectId(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to remove _id since we only want to test rejection from max_qty changed instead of _id

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 thanks for catching

} as unknown as Product,
quantity: 1,
selected: true,
},
{
data: mockValidProduct,
quantity: 1,
selected: true,
},
]

// Act
const result = PaymentsService.validatePaymentProducts(
mockValidProductsDefinition,
mockInvalidProductSubmission,
)

// Assert
expect(result.isErr()).toBeTrue()
expect(result._unsafeUnwrapErr()).toBeInstanceOf(
InvalidPaymentProductsError,
)
expect(result._unsafeUnwrapErr().message).toContain(
'There has been a change in the products available.',
)
})

Expand Down Expand Up @@ -264,7 +404,7 @@ describe('payments.service', () => {
)
})

it('should return with error if submitted price is not the same as in form defintion', () => {
it('should return with error if submitted price is not the same as in form definition', () => {
// Arrange
const mockProductWithCorrectPrice = {
name: 'some name',
Expand Down Expand Up @@ -303,7 +443,9 @@ describe('payments.service', () => {
expect(result._unsafeUnwrapErr()).toBeInstanceOf(
InvalidPaymentProductsError,
)
expect(result._unsafeUnwrapErr().message).toContain('Price has changed')
expect(result._unsafeUnwrapErr().message).toContain(
'There has been a change in the products available',
)
})
})

Expand Down
17 changes: 5 additions & 12 deletions src/app/modules/payments/payments.service.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isEqual } from 'lodash'
import moment from 'moment-timezone'
import mongoose, { Types } from 'mongoose'
import { err, errAsync, ok, okAsync, Result, ResultAsync } from 'neverthrow'
Expand Down Expand Up @@ -404,20 +405,20 @@ export const validatePaymentProducts = (
}

for (const product of submittedPaymentProducts) {
// Check that every selected product is in the form definition
// Check that every selected product matches the form definition

const productIdSubmitted = product.data._id
const productDefinition = formProductsDefinition.find(
(product) => String(product._id) === String(productIdSubmitted),
)

if (!productDefinition) {
if (!productDefinition || !isEqual(productDefinition, product.data)) {
logger.error({
message: 'Invalid payment product selected.',
meta: logMeta,
})
return err(
new InvalidPaymentProductsError(
'Invalid product selected. Please refresh and try again.',
'There has been a change in the products available. Please refresh and try again.',
),
)
}
Expand Down Expand Up @@ -464,14 +465,6 @@ export const validatePaymentProducts = (
)
}
}

if (product.data.amount_cents !== productDefinition.amount_cents) {
return err(
new InvalidPaymentProductsError(
`Price has changed. Please refresh and try again.`,
),
)
}
}

return ok(true)
Expand Down
Loading