COD_ON_OFF Flags
Overview
COD_ON_OFF is a visibility bitmask stored in TB_COST that controls field accessibility across different operations. Each flag represents a specific context where the field can be accessed.
Five Flags:
- L - List view (GET collection)
- D - Detail view (GET single record)
- N - New record (POST create)
- M - Modify record (PUT/PATCH update)
- R - Search/filter (query parameters)
Key Principle: A field is only accessible in an operation if the corresponding flag is present in its COD_ON_OFF value.
Flag Definitions
L - List View
Context: GET /api/v4/core/{dim} (collection query)
Meaning: Field is included in list view responses
Usage:
GET /api/v4/core/PRD?$num_rows=10
# Response includes fields with 'L' flag
{
"data": [
{
"PRD_ID": 1,
"XPRD01": "Product Name", # Has 'L' flag
"XPRD02": 99.99, # Has 'L' flag
# XPRD99 (internal notes) not returned - no 'L' flag
}
]
}
Examples:
COD_ON_OFF = "LDRNM"- ✅ Visible in listCOD_ON_OFF = "DRN"- ❌ Not visible in listCOD_ON_OFF = ""- ❌ Not visible in list
D - Detail View
Context: GET /api/v4/core/{dim}/{id} (single record query)
Meaning: Field is included in detail view responses
Usage:
GET /api/v4/core/PRD/123
# Response includes fields with 'D' flag
{
"data": {
"PRD_ID": 123,
"XPRD01": "Product Name", # Has 'D' flag
"XPRD02": 99.99, # Has 'D' flag
"XPRD99": "Internal notes...", # Has 'D' but not 'L' (detail-only)
}
}
Examples:
COD_ON_OFF = "LDRNM"- ✅ Visible in detailCOD_ON_OFF = "LNM"- ❌ Not visible in detailCOD_ON_OFF = "D"- ✅ Visible only in detail (not in list)
Pattern - Detail-Only Fields:
-- XPRD99 (internal notes) - visible in detail only, not in list
COD_ON_OFF = "D" -- or "DR", "DNM", etc.
N - New Record
Context: POST /api/v4/core/{dim} (create operation)
Meaning: Field can be set during record creation
Usage:
POST /api/v4/core/PRD
{
"data": {
"XPRD01": "New Product", # Has 'N' flag - allowed
"XPRD02": 99.99, # Has 'N' flag - allowed
"XPRD03": "PRD-001" # No 'N' flag - ERROR!
}
}
# Error response
{
"error": "FieldNotAllowedOnCreate",
"field": "XPRD03",
"message": "Field XPRD03 cannot be set on creation (COD_ON_OFF missing 'N' flag)"
}
Examples:
COD_ON_OFF = "LDRNM"- ✅ Can be set on creationCOD_ON_OFF = "LDRM"- ❌ Cannot be set on creation (read-only on create)COD_ON_OFF = "N"- ✅ Can only be set on creation (immutable after)
Pattern - Immutable After Creation:
-- XPRD03 (SKU) - can be set on creation, but read-only after
COD_ON_OFF = "LDN" -- List, Detail, New (no M flag = immutable)
M - Modify Record
Context: PUT/PATCH /api/v4/core/{dim}/{id} (update operations)
Meaning: Field can be updated after creation
Usage:
PATCH /api/v4/core/PRD/123
{
"data": {
"XPRD02": 89.99, # Has 'M' flag - allowed
"XPRD03": "NEW" # No 'M' flag - ERROR!
}
}
# Error response
{
"error": "FieldNotModifiable",
"field": "XPRD03",
"message": "Field XPRD03 cannot be modified (COD_ON_OFF missing 'M' flag)"
}
Examples:
COD_ON_OFF = "LDRNM"- ✅ Can be modifiedCOD_ON_OFF = "LDRN"- ❌ Cannot be modified (immutable after creation)COD_ON_OFF = "M"- ✅ Can only be modified (not set on creation)
Pattern - Modify-Only Fields:
-- XPRD_STATUS (order status) - can only be changed via workflow, not on creation
COD_ON_OFF = "LDM" -- List, Detail, Modify (no N flag = can't set on create)
R - Search/Filter
Context: Query parameters ?filter[field]=value
Meaning: Field can be used in filter conditions
Usage:
# Search by product name (has 'R' flag) - allowed
GET /api/v4/core/PRD?filter[XPRD01][$like]=Widget%
# Search by internal notes (no 'R' flag) - ERROR!
GET /api/v4/core/PRD?filter[XPRD99]=something
# Error response
{
"error": "FieldNotSearchable",
"field": "XPRD99",
"message": "Field XPRD99 cannot be used in filters (COD_ON_OFF missing 'R' flag)"
}
Examples:
COD_ON_OFF = "LDRNM"- ✅ Can be used in filtersCOD_ON_OFF = "LDNM"- ❌ Cannot be used in filtersCOD_ON_OFF = "R"- ✅ Can only be used in filters (not visible)
Pattern - Searchable But Hidden:
-- Searchable foreign key, but dimension name shown instead
COD_ON_OFF = "R" -- Can filter by ID, but not displayed (use $expand instead)
Common COD_ON_OFF Patterns
Full Access (Most Common)
COD_ON_OFF = "LDRNM"
Meaning:
- ✅ Visible in list views
- ✅ Visible in detail views
- ✅ Can be set on creation
- ✅ Can be modified
- ✅ Can be used in searches
Use Cases:
- Standard editable fields (name, description, price, quantity)
- User-controlled attributes
- Most business data fields
Example:
-- Product name - full access
INSERT INTO TB_COST (COD_DIM, NUM_COST, COD_VAR, COD_ON_OFF, REQUIRED)
VALUES ('PRD', 1, 'XPRD01', 'LDRNM', TRUE);
Read-Only (Display Only)
COD_ON_OFF = "LDR"
Meaning:
- ✅ Visible in list views
- ✅ Visible in detail views
- ❌ Cannot be set on creation
- ❌ Cannot be modified
- ✅ Can be used in searches
Use Cases:
- System-generated fields (timestamps, counters)
- Calculated/derived fields
- Auto-populated fields (via pre-insert functions)
Example:
-- Created timestamp - read-only
INSERT INTO TB_COST (COD_DIM, NUM_COST, COD_VAR, COD_ON_OFF, VALUE_TEMP)
VALUES ('PRD', 99, 'CREATED_AT', 'LDR', '{timestamp}');
Immutable After Creation
COD_ON_OFF = "LDRN"
Meaning:
- ✅ Visible in list views
- ✅ Visible in detail views
- ✅ Can be set on creation
- ❌ Cannot be modified after creation
- ✅ Can be used in searches
Use Cases:
- Unique identifiers (SKU, reference numbers)
- Immutable configuration (record type, category on creation)
- Audit fields that shouldn't change
Example:
-- Product SKU - immutable after creation
INSERT INTO TB_COST (COD_DIM, NUM_COST, COD_VAR, COD_ON_OFF, REQUIRED)
VALUES ('PRD', 3, 'XPRD03', 'LDRN', TRUE);
Modify-Only (Workflow Fields)
COD_ON_OFF = "LDRM"
Meaning:
- ✅ Visible in list views
- ✅ Visible in detail views
- ❌ Cannot be set on creation
- ✅ Can be modified
- ✅ Can be used in searches
Use Cases:
- Workflow status fields (updated via state machine)
- Approval flags (set by reviewers, not creators)
- System-managed state
Example:
-- Order status - set by workflow, not on creation
INSERT INTO TB_COST (COD_DIM, NUM_COST, COD_VAR, COD_ON_OFF, VALUE_TEMP)
VALUES ('ORD', 10, 'XORD_STATUS', 'LDRM', '{default:pending}');
Detail-Only (Sensitive Data)
COD_ON_OFF = "DNMR"
Meaning:
- ❌ Not visible in list views
- ✅ Visible in detail views
- ✅ Can be set on creation
- ✅ Can be modified
- ✅ Can be used in searches
Use Cases:
- Sensitive fields (internal notes, comments)
- Large text fields (descriptions, specifications)
- Fields too detailed for list view
Example:
-- Internal notes - detail only
INSERT INTO TB_COST (COD_DIM, NUM_COST, COD_VAR, COD_ON_OFF)
VALUES ('PRD', 99, 'XPRD99', 'DNMR');
Hidden (Internal Use)
COD_ON_OFF = ""
Meaning:
- ❌ Not visible in any view
- ❌ Cannot be set on creation
- ❌ Cannot be modified
- ❌ Cannot be used in searches
Use Cases:
- Internal system fields
- Deprecated fields (backward compatibility)
- Technical metadata
Example:
-- Internal processing flag - hidden from API
INSERT INTO TB_COST (COD_DIM, NUM_COST, COD_VAR, COD_ON_OFF)
VALUES ('PRD', 998, 'XPRD_INTERNAL_FLAG', '');
Searchable But Not Visible
COD_ON_OFF = "R"
Meaning:
- ❌ Not visible in list views
- ❌ Not visible in detail views
- ❌ Cannot be set directly
- ❌ Cannot be modified directly
- ✅ Can be used in searches
Use Cases:
- Foreign key IDs (use $expand to show related dimension)
- Technical identifiers for filtering
- Search-only lookup fields
Example:
-- Category ID - searchable but show category name via $expand
INSERT INTO TB_COST (COD_DIM, NUM_COST, COD_VAR, COD_ON_OFF)
VALUES ('PRD', 5, 'XPRD_CATEGORY_ID', 'R');
Validation Rules
Creation (POST)
Rule: Field can only be included in POST body if COD_ON_OFF contains 'N' flag
Validation:
// CoreWrite validation
function validateCreateFields(data, configs) {
const errors = [];
for (const [field, value] of Object.entries(data)) {
const config = configs.find(c => c.COD_VAR === field);
if (!config) {
errors.push(`Unknown field: ${field}`);
} else if (!config.COD_ON_OFF.includes('N')) {
errors.push(`Field ${field} cannot be set on creation (missing 'N' flag)`);
}
}
return errors;
}
Example:
# ❌ ERROR - XPRD03 has COD_ON_OFF="LDR" (no 'N' flag)
POST /api/v4/core/PRD
{
"data": {
"XPRD01": "Product",
"XPRD03": "SKU-001" # Error: cannot set on creation
}
}
Update (PUT/PATCH)
Rule: Field can only be included in PUT/PATCH body if COD_ON_OFF contains 'M' flag
Validation:
// CoreWrite validation
function validateUpdateFields(data, configs) {
const errors = [];
for (const [field, value] of Object.entries(data)) {
const config = configs.find(c => c.COD_VAR === field);
if (!config) {
errors.push(`Unknown field: ${field}`);
} else if (!config.COD_ON_OFF.includes('M')) {
errors.push(`Field ${field} cannot be modified (missing 'M' flag)`);
}
}
return errors;
}
Example:
# ❌ ERROR - XPRD03 has COD_ON_OFF="LDRN" (no 'M' flag = immutable)
PATCH /api/v4/core/PRD/123
{
"data": {
"XPRD03": "NEW-SKU" # Error: field is immutable
}
}
Filter (Search)
Rule: Field can only be used in ?filter[field]=value if COD_ON_OFF contains 'R' flag
Validation:
// CoreQuery validation
function validateFilterFields(filters, configs) {
const errors = [];
for (const field of Object.keys(filters)) {
const config = configs.find(c => c.COD_VAR === field);
if (!config) {
errors.push(`Unknown field: ${field}`);
} else if (!config.COD_ON_OFF.includes('R')) {
errors.push(`Field ${field} cannot be used in filters (missing 'R' flag)`);
}
}
return errors;
}
Example:
# ❌ ERROR - XPRD99 has COD_ON_OFF="DN" (no 'R' flag = not searchable)
GET /api/v4/core/PRD?filter[XPRD99]=notes
Response Filtering
List View (GET collection): Only include fields with 'L' flag
Detail View (GET single): Only include fields with 'D' flag
Implementation:
// CoreQuery response filtering
function filterResponseFields(record, configs, viewType) {
const flag = viewType === 'list' ? 'L' : 'D';
const filtered = {};
for (const [field, value] of Object.entries(record)) {
const config = configs.find(c => c.COD_VAR === field);
if (config && config.COD_ON_OFF.includes(flag)) {
filtered[field] = value;
}
}
return filtered;
}
Decision Matrix
| Want to... | Flag Required | Example COD_ON_OFF |
|---|---|---|
| Show in list view | L | "LDRNM", "L", "LDR" |
| Show in detail view | D | "LDRNM", "D", "DNM" |
| Set on creation | N | "LDRNM", "N", "LDRN" |
| Modify after creation | M | "LDRNM", "M", "LDRM" |
| Use in search filters | R | "LDRNM", "R", "LDR" |
| Make field read-only | No N or M | "LDR", "DR", "L" |
| Make field immutable | N but no M | "LDRN", "LN", "LDRN" |
| Hide from list, show in detail | D but no L | "DNMR", "D", "DNM" |
| Hide completely | Empty string | "" |
| Allow search only | R alone | "R" |
Common Mistakes
❌ Mistake 1: Wrong Flags for Immutable Fields
-- ❌ BAD - Has 'M' flag, so it can be modified
INSERT INTO TB_COST (COD_DIM, NUM_COST, COD_VAR, COD_ON_OFF)
VALUES ('PRD', 3, 'XPRD03', 'LDRNM'); -- Can be modified!
-- ✅ CORRECT - No 'M' flag, immutable after creation
INSERT INTO TB_COST (COD_DIM, NUM_COST, COD_VAR, COD_ON_OFF)
VALUES ('PRD', 3, 'XPRD03', 'LDRN'); -- Immutable
❌ Mistake 2: System Fields With Write Flags
-- ❌ BAD - Timestamp should be system-managed
INSERT INTO TB_COST (COD_DIM, NUM_COST, COD_VAR, COD_ON_OFF, VALUE_TEMP)
VALUES ('PRD', 99, 'CREATED_AT', 'LDRNM', '{timestamp}'); -- User can override!
-- ✅ CORRECT - Read-only, system-managed
INSERT INTO TB_COST (COD_DIM, NUM_COST, COD_VAR, COD_ON_OFF, VALUE_TEMP)
VALUES ('PRD', 99, 'CREATED_AT', 'LDR', '{timestamp}'); -- System-only
❌ Mistake 3: Missing 'R' Flag for Searchable Fields
-- ❌ BAD - Can't filter by category
INSERT INTO TB_COST (COD_DIM, NUM_COST, COD_VAR, COD_ON_OFF)
VALUES ('PRD', 5, 'XPRD05', 'LDNM'); -- No 'R' flag
-- ✅ CORRECT - Searchable
INSERT INTO TB_COST (COD_DIM, NUM_COST, COD_VAR, COD_ON_OFF)
VALUES ('PRD', 5, 'XPRD05', 'LDRNM'); -- Has 'R' flag
❌ Mistake 4: Detail-Only Fields Missing 'D' Flag
-- ❌ BAD - Not visible anywhere
INSERT INTO TB_COST (COD_DIM, NUM_COST, COD_VAR, COD_ON_OFF)
VALUES ('PRD', 99, 'XPRD99', 'NMR'); -- No 'L' or 'D' = invisible
-- ✅ CORRECT - Visible in detail view
INSERT INTO TB_COST (COD_DIM, NUM_COST, COD_VAR, COD_ON_OFF)
VALUES ('PRD', 99, 'XPRD99', 'DNMR'); -- Detail-only
Summary
- ✅ COD_ON_OFF controls field visibility across five contexts (L/D/N/M/R)
- ✅ L = List view, D = Detail view, N = New (create), M = Modify (update), R = Search
- ✅ Most common patterns:
"LDRNM"(full access),"LDR"(read-only),"LDRN"(immutable) - ✅ Validation enforced by CoreWrite (create/update) and CoreQuery (search)
- ✅ Fields without required flags are rejected with clear error messages
Key Takeaways:
- Check COD_ON_OFF before attempting operations
- Read-only fields: exclude 'N' and 'M' flags
- Immutable fields: include 'N' but exclude 'M'
- Detail-only fields: include 'D' but exclude 'L'
- Hidden fields: empty string
""
Best Practice: Always query TB_COST to check COD_ON_OFF before rendering forms or building queries.
Related Concepts
- Field Visibility - COD_ON_OFF concept explained
- Metadata Tables - TB_COST schema
- Validation - How COD_ON_OFF is enforced
- API Operations - Where flags apply