Null equivalence - update filter (#16123)

This commit is contained in:
Etienne
2025-11-27 14:31:39 +01:00
committed by GitHub
parent 76ed82b598
commit 57ae12ff7c
7 changed files with 475 additions and 56 deletions
@@ -4,10 +4,6 @@ export const POSTGRES_DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE = '';
export const DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE = '';
export const DEFAULT_RAW_JSON_FIELD_NULL_EQUIVALENT_VALUE = {};
export const POSTGRES_DEFAULT_RAW_JSON_FIELD_NULL_EQUIVALENT_VALUE = '{}';
export const DEFAULT_ARRAY_FIELD_NULL_EQUIVALENT_VALUE = [];
export const POSTGRES_DEFAULT_ARRAY_FIELD_NULL_EQUIVALENT_VALUE = '{}';
@@ -46,7 +42,6 @@ const DEFAULT_FULL_NAME_FIELD_NULL_EQUIVALENT_VALUE = {
const DEFAULT_ACTOR_FIELD_NULL_EQUIVALENT_VALUE = {
name: DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE,
context: DEFAULT_RAW_JSON_FIELD_NULL_EQUIVALENT_VALUE,
};
const DEFAULT_RICH_TEXT_V2_FIELD_NULL_EQUIVALENT_VALUE = {
@@ -2,7 +2,6 @@ import { FieldMetadataType } from 'twenty-shared/types';
import {
POSTGRES_DEFAULT_ARRAY_FIELD_NULL_EQUIVALENT_VALUE,
POSTGRES_DEFAULT_RAW_JSON_FIELD_NULL_EQUIVALENT_VALUE,
POSTGRES_DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE,
} from 'src/engine/api/common/common-args-processors/data-arg-processor/constants/null-equivalent-values.constant';
import { findPostgresDefaultNullEquivalentValue } from 'src/engine/api/common/common-args-processors/data-arg-processor/utils/find-postgres-default-null-equivalent-value.util';
@@ -41,35 +40,6 @@ describe('findPostgresDefaultNullEquivalentValue', () => {
});
});
describe('RAW_JSON', () => {
it('should return POSTGRES_DEFAULT_RAW_JSON_FIELD_NULL_EQUIVALENT_VALUE for null', () => {
expect(
findPostgresDefaultNullEquivalentValue(
null,
FieldMetadataType.RAW_JSON,
),
).toBe(POSTGRES_DEFAULT_RAW_JSON_FIELD_NULL_EQUIVALENT_VALUE);
});
it('should return POSTGRES_DEFAULT_RAW_JSON_FIELD_NULL_EQUIVALENT_VALUE for empty object', () => {
expect(
findPostgresDefaultNullEquivalentValue(
{},
FieldMetadataType.RAW_JSON,
),
).toBe(POSTGRES_DEFAULT_RAW_JSON_FIELD_NULL_EQUIVALENT_VALUE);
});
it("should return POSTGRES_DEFAULT_RAW_JSON_FIELD_NULL_EQUIVALENT_VALUE for 'NULL'", () => {
expect(
findPostgresDefaultNullEquivalentValue(
'NULL',
FieldMetadataType.RAW_JSON,
),
).toBe(POSTGRES_DEFAULT_RAW_JSON_FIELD_NULL_EQUIVALENT_VALUE);
});
});
describe('ARRAY', () => {
it('should return POSTGRES_DEFAULT_ARRAY_FIELD_NULL_EQUIVALENT_VALUE for null', () => {
expect(
@@ -112,7 +82,7 @@ describe('findPostgresDefaultNullEquivalentValue', () => {
FieldMetadataType.ACTOR,
'context',
),
).toBe(POSTGRES_DEFAULT_RAW_JSON_FIELD_NULL_EQUIVALENT_VALUE);
).toBe(undefined);
});
});
@@ -209,7 +179,7 @@ describe('findPostgresDefaultNullEquivalentValue', () => {
FieldMetadataType.RICH_TEXT_V2,
'blocknote',
),
).toBe(POSTGRES_DEFAULT_RAW_JSON_FIELD_NULL_EQUIVALENT_VALUE);
).toBe(undefined);
});
it('should return text default for markdown', () => {
@@ -2,11 +2,9 @@ import { FieldMetadataType } from 'twenty-shared/types';
import {
POSTGRES_DEFAULT_ARRAY_FIELD_NULL_EQUIVALENT_VALUE,
POSTGRES_DEFAULT_RAW_JSON_FIELD_NULL_EQUIVALENT_VALUE,
POSTGRES_DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE,
} from 'src/engine/api/common/common-args-processors/data-arg-processor/constants/null-equivalent-values.constant';
import { isNullEquivalentArrayFieldValue } from 'src/engine/api/common/common-args-processors/data-arg-processor/utils/is-null-equivalent-array-field-value.util';
import { isNullEquivalentRawJsonFieldValue } from 'src/engine/api/common/common-args-processors/data-arg-processor/utils/is-null-equivalent-raw-json-field-value.util';
import { isNullEquivalentTextFieldValue } from 'src/engine/api/common/common-args-processors/data-arg-processor/utils/is-null-equivalent-text-field-value.util';
export const findPostgresDefaultNullEquivalentValue = (
@@ -19,10 +17,7 @@ export const findPostgresDefaultNullEquivalentValue = (
return isNullEquivalentTextFieldValue(value) || value === 'NULL'
? POSTGRES_DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE
: undefined;
case FieldMetadataType.RAW_JSON:
return isNullEquivalentRawJsonFieldValue(value) || value === 'NULL'
? POSTGRES_DEFAULT_RAW_JSON_FIELD_NULL_EQUIVALENT_VALUE
: undefined;
case FieldMetadataType.MULTI_SELECT:
case FieldMetadataType.ARRAY:
return isNullEquivalentArrayFieldValue(value) || value === 'NULL'
? POSTGRES_DEFAULT_ARRAY_FIELD_NULL_EQUIVALENT_VALUE
@@ -33,10 +28,6 @@ export const findPostgresDefaultNullEquivalentValue = (
return isNullEquivalentTextFieldValue(value) || value === 'NULL'
? POSTGRES_DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE
: undefined;
case 'context':
return isNullEquivalentRawJsonFieldValue(value) || value === 'NULL'
? POSTGRES_DEFAULT_RAW_JSON_FIELD_NULL_EQUIVALENT_VALUE
: undefined;
default:
return undefined;
}
@@ -128,10 +119,6 @@ export const findPostgresDefaultNullEquivalentValue = (
}
case FieldMetadataType.RICH_TEXT_V2: {
switch (key) {
case 'blocknote':
return isNullEquivalentRawJsonFieldValue(value) || value === 'NULL'
? POSTGRES_DEFAULT_RAW_JSON_FIELD_NULL_EQUIVALENT_VALUE
: undefined;
case 'markdown':
return isNullEquivalentTextFieldValue(value) || value === 'NULL'
? POSTGRES_DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE
@@ -501,8 +501,24 @@ describe('evaluateFilterConditions', () => {
'TEXT',
);
const filter3 = createFilter(
ViewFilterOperand.CONTAINS,
null,
'',
'TEXT',
);
const filter4 = createFilter(
ViewFilterOperand.CONTAINS,
'',
null,
'TEXT',
);
expect(evaluateFilterConditions({ filters: [filter1] })).toBe(true);
expect(evaluateFilterConditions({ filters: [filter2] })).toBe(false);
expect(evaluateFilterConditions({ filters: [filter3] })).toBe(true);
expect(evaluateFilterConditions({ filters: [filter4] })).toBe(true);
});
it('should handle DoesNotContain operand with strings', () => {
@@ -519,8 +535,16 @@ describe('evaluateFilterConditions', () => {
'TEXT',
);
const filter3 = createFilter(
ViewFilterOperand.DOES_NOT_CONTAIN,
null,
'',
'TEXT',
);
expect(evaluateFilterConditions({ filters: [filter1] })).toBe(false);
expect(evaluateFilterConditions({ filters: [filter2] })).toBe(true);
expect(evaluateFilterConditions({ filters: [filter3] })).toBe(false);
});
it('should handle Contains operand with arrays', () => {
@@ -537,8 +561,32 @@ describe('evaluateFilterConditions', () => {
'ARRAY',
);
const filter3 = createFilter(
ViewFilterOperand.CONTAINS,
null,
[],
'ARRAY',
);
const filter4 = createFilter(
ViewFilterOperand.CONTAINS,
[],
null,
'ARRAY',
);
const filter5 = createFilter(
ViewFilterOperand.CONTAINS,
null,
['apple'],
'ARRAY',
);
expect(evaluateFilterConditions({ filters: [filter1] })).toBe(true);
expect(evaluateFilterConditions({ filters: [filter2] })).toBe(false);
expect(evaluateFilterConditions({ filters: [filter3] })).toBe(true);
expect(evaluateFilterConditions({ filters: [filter4] })).toBe(true);
expect(evaluateFilterConditions({ filters: [filter5] })).toBe(false);
});
it('should handle DoesNotContain operand with arrays', () => {
@@ -555,8 +603,16 @@ describe('evaluateFilterConditions', () => {
'ARRAY',
);
const filter3 = createFilter(
ViewFilterOperand.DOES_NOT_CONTAIN,
null,
['apple'],
'ARRAY',
);
expect(evaluateFilterConditions({ filters: [filter1] })).toBe(false);
expect(evaluateFilterConditions({ filters: [filter2] })).toBe(true);
expect(evaluateFilterConditions({ filters: [filter3] })).toBe(true);
});
});
@@ -0,0 +1,233 @@
import { FieldMetadataType } from 'twenty-shared/types';
import {
DEFAULT_ARRAY_FIELD_NULL_EQUIVALENT_VALUE,
DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE,
} from 'src/engine/api/common/common-args-processors/data-arg-processor/constants/null-equivalent-values.constant';
import { findDefaultNullEquivalentValue } from 'src/modules/workflow/workflow-executor/workflow-actions/filter/utils/find-default-null-equivalent-value.util';
describe('findDefaultNullEquivalentValue', () => {
describe('Simple Types', () => {
describe('TEXT', () => {
it('should return DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE for null', () => {
expect(
findDefaultNullEquivalentValue({
value: null,
fieldMetadataType: FieldMetadataType.TEXT,
}),
).toBe(DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE);
});
it('should return DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE for empty string', () => {
expect(
findDefaultNullEquivalentValue({
value: '',
fieldMetadataType: FieldMetadataType.TEXT,
}),
).toBe(DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE);
});
it('should return undefined for non-null equivalent value', () => {
expect(
findDefaultNullEquivalentValue({
value: 'value',
fieldMetadataType: FieldMetadataType.TEXT,
}),
).toBeUndefined();
});
});
describe('ARRAY', () => {
it('should return DEFAULT_ARRAY_FIELD_NULL_EQUIVALENT_VALUE for null', () => {
expect(
findDefaultNullEquivalentValue({
value: null,
fieldMetadataType: FieldMetadataType.ARRAY,
}),
).toBe(DEFAULT_ARRAY_FIELD_NULL_EQUIVALENT_VALUE);
});
it('should return DEFAULT_ARRAY_FIELD_NULL_EQUIVALENT_VALUE for empty array', () => {
expect(
findDefaultNullEquivalentValue({
value: [],
fieldMetadataType: FieldMetadataType.ARRAY,
}),
).toBe(DEFAULT_ARRAY_FIELD_NULL_EQUIVALENT_VALUE);
});
});
});
describe('ACTOR', () => {
it('should return text default for name', () => {
expect(
findDefaultNullEquivalentValue({
value: '',
fieldMetadataType: FieldMetadataType.ACTOR,
key: 'name',
}),
).toBe(DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE);
});
it('should return undefined for context', () => {
expect(
findDefaultNullEquivalentValue({
value: {},
fieldMetadataType: FieldMetadataType.ACTOR,
key: 'context',
}),
).toBe(undefined);
});
});
describe('ADDRESS', () => {
it.each([
'addressStreet1',
'addressStreet2',
'addressCity',
'addressState',
'addressPostcode',
'addressCountry',
])('should return text default for %s', (key) => {
expect(
findDefaultNullEquivalentValue({
value: '',
fieldMetadataType: FieldMetadataType.ADDRESS,
key,
}),
).toBe(DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE);
});
});
describe('EMAILS', () => {
it('should return text default for primaryEmail', () => {
expect(
findDefaultNullEquivalentValue({
value: '',
fieldMetadataType: FieldMetadataType.EMAILS,
key: 'primaryEmail',
}),
).toBe(DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE);
});
it('should return array default for additionalEmails', () => {
expect(
findDefaultNullEquivalentValue({
value: [],
fieldMetadataType: FieldMetadataType.EMAILS,
key: 'additionalEmails',
}),
).toBe(DEFAULT_ARRAY_FIELD_NULL_EQUIVALENT_VALUE);
});
});
describe('LINKS', () => {
it('should return text default for primaryLinkUrl', () => {
expect(
findDefaultNullEquivalentValue({
value: '',
fieldMetadataType: FieldMetadataType.LINKS,
key: 'primaryLinkUrl',
}),
).toBe(DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE);
});
it('should return text default for primaryLinkLabel', () => {
expect(
findDefaultNullEquivalentValue({
value: '',
fieldMetadataType: FieldMetadataType.LINKS,
key: 'primaryLinkLabel',
}),
).toBe(DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE);
});
});
describe('PHONES', () => {
it('should return text default for primaryPhoneNumber', () => {
expect(
findDefaultNullEquivalentValue({
value: '',
fieldMetadataType: FieldMetadataType.PHONES,
key: 'primaryPhoneNumber',
}),
).toBe(DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE);
});
it('should return text default for primaryPhoneCountryCode', () => {
expect(
findDefaultNullEquivalentValue({
value: '',
fieldMetadataType: FieldMetadataType.PHONES,
key: 'primaryPhoneCountryCode',
}),
).toBe(DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE);
});
it('should return text default for primaryPhoneCallingCode', () => {
expect(
findDefaultNullEquivalentValue({
value: '',
fieldMetadataType: FieldMetadataType.PHONES,
key: 'primaryPhoneCallingCode',
}),
).toBe(DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE);
});
});
describe('RICH_TEXT_V2', () => {
it('should return undefined for blocknote', () => {
expect(
findDefaultNullEquivalentValue({
value: {},
fieldMetadataType: FieldMetadataType.RICH_TEXT_V2,
key: 'blocknote',
}),
).toBe(undefined);
});
it('should return text default for markdown', () => {
expect(
findDefaultNullEquivalentValue({
value: '',
fieldMetadataType: FieldMetadataType.RICH_TEXT_V2,
key: 'markdown',
}),
).toBe(DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE);
});
});
describe('FULL_NAME', () => {
it.each(['firstName', 'lastName'])(
'should return text default for %s',
(key) => {
expect(
findDefaultNullEquivalentValue({
value: '',
fieldMetadataType: FieldMetadataType.FULL_NAME,
key,
}),
).toBe(DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE);
},
);
});
});
it('should return undefined for unknown type', () => {
expect(
findDefaultNullEquivalentValue({
value: null,
fieldMetadataType: 'UNKNOWN' as any,
}),
).toBeUndefined();
});
it('should return undefined for unknown composite key', () => {
expect(
findDefaultNullEquivalentValue({
value: '',
fieldMetadataType: FieldMetadataType.ACTOR,
key: 'unknown',
}),
).toBeUndefined();
});
@@ -10,9 +10,13 @@ import {
ViewFilterOperand,
type ViewFilterOperandDeprecated,
} from 'twenty-shared/types';
import { convertViewFilterOperandToCoreOperand as convertViewFilterOperandDeprecated } from 'twenty-shared/utils';
import {
convertViewFilterOperandToCoreOperand as convertViewFilterOperandDeprecated,
isDefined,
} from 'twenty-shared/utils';
import { parseBooleanFromStringValue } from 'twenty-shared/workflow';
import { findDefaultNullEquivalentValue } from 'src/modules/workflow/workflow-executor/workflow-actions/filter/utils/find-default-null-equivalent-value.util';
import { parseAndEvaluateRelativeDateFilter } from 'src/modules/workflow/workflow-executor/workflow-actions/filter/utils/parse-and-evaluate-relative-date-filter.util';
type ResolvedFilterWithPotentiallyDeprecatedOperand = Omit<
@@ -59,7 +63,11 @@ function evaluateFilter(
case 'ARRAY':
case 'array':
case 'RAW_JSON':
return evaluateTextAndArrayFilter(filterWithConvertedOperand);
return evaluateTextAndArrayFilter(
filterWithConvertedOperand,
filter.type,
filter.compositeFieldSubFieldName,
);
case 'SELECT':
return evaluateSelectFilter(filterWithConvertedOperand);
case 'BOOLEAN':
@@ -146,12 +154,31 @@ function contains(leftValue: unknown, rightValue: unknown): boolean {
return String(leftValue).includes(String(rightValue));
}
function evaluateTextAndArrayFilter(filter: ResolvedFilter): boolean {
function evaluateTextAndArrayFilter(
filter: ResolvedFilter,
filterType: string,
compositeFieldSubFieldName: string | undefined,
): boolean {
//TODO : nullEquivalentRightValue to remove once feature flag removed + workflow action based on common api
const nullEquivalentRightValue = findDefaultNullEquivalentValue({
value: filter.rightOperand,
fieldMetadataType: filterType,
key: compositeFieldSubFieldName,
});
switch (filter.operand) {
case ViewFilterOperand.CONTAINS:
return contains(filter.leftOperand, filter.rightOperand);
return (
contains(filter.leftOperand, filter.rightOperand) ||
(isDefined(nullEquivalentRightValue) &&
!isNotEmptyTextOrArray(filter.leftOperand))
);
case ViewFilterOperand.DOES_NOT_CONTAIN:
return !contains(filter.leftOperand, filter.rightOperand);
return (
!contains(filter.leftOperand, filter.rightOperand) ||
(isDefined(nullEquivalentRightValue) &&
isNotEmptyTextOrArray(filter.leftOperand))
);
case ViewFilterOperand.IS_EMPTY:
return !isNotEmptyTextOrArray(filter.leftOperand);
@@ -0,0 +1,151 @@
import { FieldMetadataType } from 'twenty-shared/types';
import {
DEFAULT_ARRAY_FIELD_NULL_EQUIVALENT_VALUE,
DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE,
} from 'src/engine/api/common/common-args-processors/data-arg-processor/constants/null-equivalent-values.constant';
import { isNullEquivalentArrayFieldValue } from 'src/engine/api/common/common-args-processors/data-arg-processor/utils/is-null-equivalent-array-field-value.util';
import { isNullEquivalentTextFieldValue } from 'src/engine/api/common/common-args-processors/data-arg-processor/utils/is-null-equivalent-text-field-value.util';
export const findDefaultNullEquivalentValue = ({
value,
fieldMetadataType,
key,
}: {
value: unknown;
fieldMetadataType: string;
key?: string;
}) => {
switch (fieldMetadataType) {
case FieldMetadataType.TEXT:
return isNullEquivalentTextFieldValue(value)
? DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE
: undefined;
case FieldMetadataType.MULTI_SELECT:
case FieldMetadataType.ARRAY:
return isNullEquivalentArrayFieldValue(value)
? DEFAULT_ARRAY_FIELD_NULL_EQUIVALENT_VALUE
: undefined;
case FieldMetadataType.ACTOR: {
switch (key) {
case 'name':
return isNullEquivalentTextFieldValue(value)
? DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE
: undefined;
default:
return undefined;
}
}
case FieldMetadataType.ADDRESS: {
switch (key) {
case 'addressStreet1':
return isNullEquivalentTextFieldValue(value)
? DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE
: undefined;
case 'addressStreet2':
return isNullEquivalentTextFieldValue(value)
? DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE
: undefined;
case 'addressCity':
return isNullEquivalentTextFieldValue(value)
? DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE
: undefined;
case 'addressState':
return isNullEquivalentTextFieldValue(value)
? DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE
: undefined;
case 'addressPostcode':
return isNullEquivalentTextFieldValue(value)
? DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE
: undefined;
case 'addressCountry':
return isNullEquivalentTextFieldValue(value)
? DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE
: undefined;
default:
return undefined;
}
}
case FieldMetadataType.EMAILS: {
switch (key) {
case 'primaryEmail':
return isNullEquivalentTextFieldValue(value)
? DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE
: undefined;
case 'additionalEmails':
return isNullEquivalentArrayFieldValue(value)
? DEFAULT_ARRAY_FIELD_NULL_EQUIVALENT_VALUE
: undefined;
default:
return undefined;
}
}
case FieldMetadataType.LINKS: {
switch (key) {
case 'primaryLinkUrl':
return isNullEquivalentTextFieldValue(value)
? DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE
: undefined;
case 'primaryLinkLabel':
return isNullEquivalentTextFieldValue(value)
? DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE
: undefined;
case 'secondaryLinks':
return isNullEquivalentArrayFieldValue(value)
? DEFAULT_ARRAY_FIELD_NULL_EQUIVALENT_VALUE
: undefined;
default:
return undefined;
}
}
case FieldMetadataType.PHONES: {
switch (key) {
case 'primaryPhoneNumber':
return isNullEquivalentTextFieldValue(value)
? DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE
: undefined;
case 'primaryPhoneCountryCode':
return isNullEquivalentTextFieldValue(value)
? DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE
: undefined;
case 'primaryPhoneCallingCode':
return isNullEquivalentTextFieldValue(value)
? DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE
: undefined;
case 'additionalPhones':
return isNullEquivalentArrayFieldValue(value)
? DEFAULT_ARRAY_FIELD_NULL_EQUIVALENT_VALUE
: undefined;
default:
return undefined;
}
}
case FieldMetadataType.RICH_TEXT_V2: {
switch (key) {
case 'markdown':
return isNullEquivalentTextFieldValue(value)
? DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE
: undefined;
default:
return undefined;
}
}
case FieldMetadataType.FULL_NAME: {
switch (key) {
case 'firstName':
return isNullEquivalentTextFieldValue(value)
? DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE
: undefined;
case 'lastName':
return isNullEquivalentTextFieldValue(value)
? DEFAULT_TEXT_FIELD_NULL_EQUIVALENT_VALUE
: undefined;
default:
return undefined;
}
}
}
return undefined;
};