field-applicability.js
Overview
services/api/src/modules/match/field-applicability.js defines the backend applicability rules for Match. It is a minimal, read-only port of the canonical frontend table, limited to the 11 fields that Match compares in this phase. The source explicitly says Match never imports apps/backoffice-web code, so this file exists as a deliberate duplication with manual synchronization.
The module serves one narrow purpose: decide whether a given Match field makes sense for a propertyType. It does not inspect field values, and it does not infer not_applicable from missing data. The source treats null or absence as a separate concern from structural applicability.
[!IMPORTANT] This file is a deliberate backend copy of the frontend applicability table. If the frontend table changes, this file must be updated manually.
How it works
The module keeps two frozen lookup tables and one exported function. The exported function chooses a table for the given propertyType, falls back to a permissive default, and returns false only when the field is explicitly marked false. The comparison layer uses this check before physical and infrastructure comparisons. fileciteturn0file6turn0file3
flowchart TD
A[isMatchFieldApplicableToPropertyType] --> B[Select propertyType table]
B --> C{propertyType known}
C -->|yes| D[MATCH_APPLICABILITY_BY_PROPERTY_TYPE]
C -->|no| E[PERMISSIVE_MATCH_APPLICABILITY]
D --> F[Check field entry]
E --> F
F --> G[Return true unless explicit false]
The runtime flow is intentionally small. A caller passes a field name and an optional propertyType. The module resolves a table, checks the field, and returns a boolean. Tests confirm that unknown propertyType values use the permissive default. fileciteturn0file8turn0file9
Key components
{
"title": "isMatchFieldApplicableToPropertyType",
"content": "Public function that decides whether a Match field applies to a given propertyType. It returns a boolean and treats any value other than explicit false as applicable.",
"type": "function",
"filePath": "services/api/src/modules/match/field-applicability.js",
"badges": [
"public"
]
}
The module is centered on read-only lookup data. All tables are wrapped with Object.freeze, which makes the applicability definitions immutable at runtime.
Data & fields
The file exports one field list and one function. It also defines two internal frozen maps that control the applicability decision. The source describes this as the backend mirror of the frontend table, limited to Match’s current comparison scope. fileciteturn0file0turn0file6
[
{
"name": "MATCH_APPLICABILITY_FIELDS",
"type": "string[]",
"required": true,
"description": "Ordered list of the 11 fields that Match checks for structural applicability."
},
{
"name": "PERMISSIVE_MATCH_APPLICABILITY",
"type": "Record<string, boolean>",
"required": true,
"description": "Internal fallback table where every supported field resolves to true."
},
{
"name": "MATCH_APPLICABILITY_BY_PROPERTY_TYPE",
"type": "Record<string, Record<string, boolean>>",
"required": true,
"description": "Internal propertyType matrix used to resolve field applicability."
},
{
"name": "field",
"type": "string",
"required": true,
"description": "One of MATCH_APPLICABILITY_FIELDS."
},
{
"name": "propertyType",
"type": "string",
"description": "meta.propertyType for the Offer or Requirement already resolved by the pair gate."
}
]
MATCH_APPLICABILITY_FIELDS
This exported array contains exactly 11 fields. The file states that they are the 8 physical fields plus the 3 infrastructure declarations used by Match today.
bedroomsbathroomshalfBathroomsparkingSpotsconstructionArealandAreafrontagedepthwaterDeclarationelectricityDeclarationdrainageDeclaration
PERMISSIVE_MATCH_APPLICABILITY
This internal table marks all 11 fields as applicable. The module uses it as the fallback for other and any unknown propertyType. The tests confirm that unknown types keep the permissive behavior. fileciteturn0file6turn0file8
MATCH_APPLICABILITY_BY_PROPERTY_TYPE
This internal matrix defines the structural applicability per propertyType. Its entries are the source of truth for the file’s boolean result. The function does not derive applicability from values; it only reads this map.
-
housetrue:bedrooms,bathrooms,halfBathrooms,parkingSpots,constructionArea,landAreafalse:frontage,depth,waterDeclaration,electricityDeclaration,drainageDeclaration
-
apartmenttrue:bedrooms,bathrooms,halfBathrooms,parkingSpots,constructionAreafalse:landArea,frontage,depth,waterDeclaration,electricityDeclaration,drainageDeclaration
-
landtrue:landArea,frontage,depth,waterDeclaration,electricityDeclaration,drainageDeclarationfalse:bedrooms,bathrooms,halfBathrooms,parkingSpots,constructionArea
-
officetrue:bathrooms,parkingSpots,constructionAreafalse:bedrooms,halfBathrooms,landArea,frontage,depth,waterDeclaration,electricityDeclaration,drainageDeclaration
-
commercialtrue:bathrooms,halfBathrooms,parkingSpots,constructionArea,landArea,frontage,depth,waterDeclaration,electricityDeclaration,drainageDeclarationfalse:bedrooms
-
warehousetrue:parkingSpots,constructionArea,landArea,frontage,depth,waterDeclaration,electricityDeclaration,drainageDeclarationfalse:bedrooms,bathrooms,halfBathrooms
-
industrialtrue:parkingSpots,constructionArea,landArea,frontage,depth,waterDeclaration,electricityDeclaration,drainageDeclarationfalse:bedrooms,bathrooms,halfBathrooms
-
other- Uses
PERMISSIVE_MATCH_APPLICABILITY - All 11 fields resolve to
true
- Uses
Behaviors
isMatchFieldApplicableToPropertyType[badge:public] — Resolves a boolean applicability result for one field and onepropertyType.return table[field] !== false— Treats only explicitfalseas non-applicable.Object.freeze(...)— Keeps the exported and internal tables read-only.- Default fallback to
PERMISSIVE_MATCH_APPLICABILITY— Preserves permissive behavior forotherand unknownpropertyTypevalues.
[!NOTE] The function does not validate the
fieldname itself. It only checks the selected table entry and returnstrueunless the entry is exactlyfalse.
Gotchas & edge cases
[!WARNING]
nullor missing values do not meannot_applicablehere. This file answers only the structural question: whether a field belongs to apropertyType. The source says evidence absence and structural non-applicability are different states.
[!IMPORTANT] The backend copy must stay aligned with the frontend copy. The source explicitly references
apps/backoffice-web/src/features/publish-wizard/lib/fieldApplicability.jsas the canonical origin for this duplication.
[!CAUTION]
otherand unknownpropertyTypevalues do not fail closed. They use the permissive table, which marks all 11 fields as applicable. The tests confirm that behavior. fileciteturn0file8turn0file9
Related
This module sits inside the Match comparison path. The source ties it to services/api/src/modules/match/comparison-contract.js, where applicability is resolved before physical and infrastructure comparisons. It also records the frontend mirror in apps/backoffice-web/src/features/publish-wizard/lib/fieldApplicability.js, and mentions docs/03-architecture/data-models.md as the place where the intentional duplication is documented. fileciteturn0file1turn0file4
services/api/src/modules/match/comparison-contract.js— consumes this applicability result before Match compares physical and infrastructure fields.apps/backoffice-web/src/features/publish-wizard/lib/fieldApplicability.js— canonical frontend source mirrored here.docs/03-architecture/data-models.md— referenced by the source as the duplication record.