From 176d0159ab0ddcfde3f65b8a5af12c9cc70b5dee Mon Sep 17 00:00:00 2001 From: Anoop P <44577841+anoopw3bdev@users.noreply.github.com> Date: Mon, 26 Feb 2024 02:58:39 +0530 Subject: [PATCH] Feat currency type optimistic cache (#3907) * feat: currency type in optimisitc cache update * Add test for optimisitc currency cache * Refactor error message for currency filter to be more accurate * Fix --------- Co-authored-by: Charles Bochet --- .../utils/isMatchingCurrencyFilter.spec.ts | 164 ++++++++++++++++++ .../utils/isMatchingCurrencyFilter.ts | 47 +++++ .../utils/isRecordMatchingFilter.ts | 8 + 3 files changed, 219 insertions(+) create mode 100644 packages/twenty-front/src/modules/object-record/record-filter/utils/isMatchingCurrencyFilter.spec.ts create mode 100644 packages/twenty-front/src/modules/object-record/record-filter/utils/isMatchingCurrencyFilter.ts diff --git a/packages/twenty-front/src/modules/object-record/record-filter/utils/isMatchingCurrencyFilter.spec.ts b/packages/twenty-front/src/modules/object-record/record-filter/utils/isMatchingCurrencyFilter.spec.ts new file mode 100644 index 000000000..a4563f1e8 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-filter/utils/isMatchingCurrencyFilter.spec.ts @@ -0,0 +1,164 @@ +import { CurrencyFilter } from '@/object-record/record-filter/types/ObjectRecordQueryFilter'; +import { isMatchingCurrencyFilter } from '@/object-record/record-filter/utils/isMatchingCurrencyFilter'; + +describe('isMatchingCurrencyFilter', () => { + describe('eq', () => { + it('value equals eq filter', () => { + const currencyFilter: CurrencyFilter = { + amountMicros: { eq: 10 }, + }; + expect(isMatchingCurrencyFilter({ currencyFilter, value: 10 })).toBe( + true, + ); + }); + + it('value does not equal eq filter', () => { + const currencyFilter: CurrencyFilter = { + amountMicros: { eq: 10 }, + }; + expect(isMatchingCurrencyFilter({ currencyFilter, value: 20 })).toBe( + false, + ); + }); + }); + + describe('gt', () => { + it('value is greater than gt filter', () => { + const currencyFilter: CurrencyFilter = { + amountMicros: { gt: 10 }, + }; + expect(isMatchingCurrencyFilter({ currencyFilter, value: 20 })).toBe( + true, + ); + }); + + it('value is not greater than gt filter', () => { + const currencyFilter: CurrencyFilter = { + amountMicros: { gt: 20 }, + }; + expect(isMatchingCurrencyFilter({ currencyFilter, value: 10 })).toBe( + false, + ); + }); + }); + + describe('gte', () => { + it('value is greater than or equal to gte filter', () => { + const currencyFilter: CurrencyFilter = { + amountMicros: { gte: 10 }, + }; + expect(isMatchingCurrencyFilter({ currencyFilter, value: 10 })).toBe( + true, + ); + }); + + it('value is not greater than or equal to gte filter', () => { + const currencyFilter: CurrencyFilter = { + amountMicros: { gte: 20 }, + }; + expect(isMatchingCurrencyFilter({ currencyFilter, value: 10 })).toBe( + false, + ); + }); + }); + + describe('in', () => { + it('value is in the array', () => { + const currencyFilter: CurrencyFilter = { + amountMicros: { in: [10, 20, 30] }, + }; + expect(isMatchingCurrencyFilter({ currencyFilter, value: 20 })).toBe( + true, + ); + }); + + it('value is not in the array', () => { + const currencyFilter: CurrencyFilter = { + amountMicros: { in: [10, 30, 40] }, + }; + expect(isMatchingCurrencyFilter({ currencyFilter, value: 20 })).toBe( + false, + ); + }); + }); + + describe('lt', () => { + it('value is less than lt filter', () => { + const currencyFilter: CurrencyFilter = { + amountMicros: { lt: 20 }, + }; + expect(isMatchingCurrencyFilter({ currencyFilter, value: 10 })).toBe( + true, + ); + }); + + it('value is not less than lt filter', () => { + const currencyFilter: CurrencyFilter = { + amountMicros: { lt: 10 }, + }; + expect(isMatchingCurrencyFilter({ currencyFilter, value: 20 })).toBe( + false, + ); + }); + }); + + describe('lte', () => { + it('value is less than or equal to lte filter', () => { + const currencyFilter: CurrencyFilter = { + amountMicros: { lte: 20 }, + }; + expect(isMatchingCurrencyFilter({ currencyFilter, value: 20 })).toBe( + true, + ); + }); + + it('value is not less than or equal to lte filter', () => { + const currencyFilter: CurrencyFilter = { + amountMicros: { lte: 10 }, + }; + expect(isMatchingCurrencyFilter({ currencyFilter, value: 20 })).toBe( + false, + ); + }); + }); + + describe('neq', () => { + it('value does not equal neq filter', () => { + const currencyFilter: CurrencyFilter = { + amountMicros: { neq: 10 }, + }; + expect(isMatchingCurrencyFilter({ currencyFilter, value: 20 })).toBe( + true, + ); + }); + + it('value equals neq filter', () => { + const currencyFilter: CurrencyFilter = { + amountMicros: { neq: 10 }, + }; + expect(isMatchingCurrencyFilter({ currencyFilter, value: 10 })).toBe( + false, + ); + }); + }); + + describe('is', () => { + it('value is NULL', () => { + const currencyFilter: CurrencyFilter = { + amountMicros: { is: 'NULL' }, + }; + expect( + isMatchingCurrencyFilter({ currencyFilter, value: null as any }), + ).toBe(true); + }); + + it('value is NOT_NULL', () => { + const currencyFilter: CurrencyFilter = { + amountMicros: { is: 'NOT_NULL' }, + }; + expect(isMatchingCurrencyFilter({ currencyFilter, value: 10 })).toBe( + true, + ); + }); + }); +}); diff --git a/packages/twenty-front/src/modules/object-record/record-filter/utils/isMatchingCurrencyFilter.ts b/packages/twenty-front/src/modules/object-record/record-filter/utils/isMatchingCurrencyFilter.ts new file mode 100644 index 000000000..19f6e9fea --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-filter/utils/isMatchingCurrencyFilter.ts @@ -0,0 +1,47 @@ +import { CurrencyFilter } from '@/object-record/record-filter/types/ObjectRecordQueryFilter'; + +export const isMatchingCurrencyFilter = ({ + currencyFilter, + value, +}: { + currencyFilter: CurrencyFilter; + value: number; +}) => { + switch (true) { + case currencyFilter.amountMicros?.eq !== undefined: { + return value === currencyFilter.amountMicros.eq; + } + case currencyFilter.amountMicros?.neq !== undefined: { + return value !== currencyFilter.amountMicros.neq; + } + case currencyFilter.amountMicros?.gt !== undefined: { + return value > currencyFilter.amountMicros.gt; + } + case currencyFilter.amountMicros?.gte !== undefined: { + return value >= currencyFilter.amountMicros.gte; + } + case currencyFilter.amountMicros?.lt !== undefined: { + return value < currencyFilter.amountMicros.lt; + } + case currencyFilter.amountMicros?.lte !== undefined: { + return value <= currencyFilter.amountMicros.lte; + } + case currencyFilter.amountMicros?.in !== undefined: { + return currencyFilter.amountMicros.in.includes(value); + } + case currencyFilter.amountMicros?.is !== undefined: { + if (currencyFilter.amountMicros.is === 'NULL') { + return value === null; + } else { + return value !== null; + } + } + default: { + throw new Error( + `Unexpected amountMicros for currency filter : ${JSON.stringify( + currencyFilter.amountMicros, + )}`, + ); + } + } +}; diff --git a/packages/twenty-front/src/modules/object-record/record-filter/utils/isRecordMatchingFilter.ts b/packages/twenty-front/src/modules/object-record/record-filter/utils/isRecordMatchingFilter.ts index c794e1b46..49347b22f 100644 --- a/packages/twenty-front/src/modules/object-record/record-filter/utils/isRecordMatchingFilter.ts +++ b/packages/twenty-front/src/modules/object-record/record-filter/utils/isRecordMatchingFilter.ts @@ -4,6 +4,7 @@ import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { AndObjectRecordFilter, BooleanFilter, + CurrencyFilter, DateFilter, FloatFilter, FullNameFilter, @@ -15,6 +16,7 @@ import { UUIDFilter, } from '@/object-record/record-filter/types/ObjectRecordQueryFilter'; import { isMatchingBooleanFilter } from '@/object-record/record-filter/utils/isMatchingBooleanFilter'; +import { isMatchingCurrencyFilter } from '@/object-record/record-filter/utils/isMatchingCurrencyFilter'; import { isMatchingDateFilter } from '@/object-record/record-filter/utils/isMatchingDateFilter'; import { isMatchingFloatFilter } from '@/object-record/record-filter/utils/isMatchingFloatFilter'; import { isMatchingStringFilter } from '@/object-record/record-filter/utils/isMatchingStringFilter'; @@ -202,6 +204,12 @@ export const isRecordMatchingFilter = ({ value: record[filterKey], }); } + case FieldMetadataType.Currency: { + return isMatchingCurrencyFilter({ + currencyFilter: filterValue as CurrencyFilter, + value: record[filterKey].amountMicros, + }); + } case FieldMetadataType.Relation: { throw new Error( `Not implemented yet, use UUID filter instead on the corredponding "${filterKey}Id" field`,