Field Maps in Nama ERP - Complete Guide (AI-Generated by Claude.ai)
Overview
Field maps are a powerful feature in Nama ERP that allow automatic copying and transformation of data between different entities (records). This system is primarily used in Entity Flows to generate new documents from existing ones (e.g., creating a Credit Note from a Sales Invoice).
Basic Concept
A field map is a set of instructions that tells the system:
- What data to copy (source field)
- Where to copy it (target field)
- How to transform it (optional functions)
The basic syntax is:
targetField=sourceField
Simple Field Mapping
Direct Field Copy
The simplest form copies a value from one field to another:
code=code # Copy code from source to target
description=description # Copy description from source to target
customer=customer # Copy customer reference from source to target
Setting Fixed Values
You can set fields to specific values:
status="Active" # Set status to the text "Active"
priority=1 # Set priority to number 1
isApproved=true # Set boolean value
discount=null # Clear the field
Special References
ref5=$this # Set ref5 to reference the source entity itself
fromDocument=$this # Create a link back to the source document
Working with Collections (Detail Lines)
Copying Entire Tables
When documents have detail lines (like invoice items), you can:
details=[lines] # Create same number of lines as source
details=[5] # Create exactly 5 empty lines
details=[clear] # Remove all existing lines
Adding Lines
details=[addLines(5)] # Add 5 new empty lines
details=[addLines(lines)] # Add same number as source lines
details1=[addLines(details2)] # Add lines based on another collection
Copying Field Values to All Lines
details.warehouse=warehouse # Copy header warehouse to all detail lines
details.project=project # Copy header project to all detail lines
Line-by-Line Copying
details.quantity=lines.quantity # Copy quantity from each source line
details.price=lines.unitPrice # Copy price from corresponding lines
details.item=lines.item # Copy item references
Advanced Functions
Text Manipulation
Masking
Format text according to a pattern:
altCode=mask(code,XXX-XXX-XXX) # ABC123456 becomes ABC-123-456
phoneDisplay=mask(phone,XXXX XXX XXXX) # 0501234567 becomes 0501 234 567
X
represents a character from the original value- Any other character (like
-
,.
,) is inserted as-is
Text Extraction
firstFive=description.$left_5 # Get first 5 characters
lastTwo=code.$right_2 # Get last 2 characters
middle=ref1.$mid_3_4 # Get 4 characters starting at position 3
Mathematical Functions
Totaling Values
Calculate sum of values in detail lines:
totalAmount=totalize(details,details.price)
netTotal=totalize(lines,lines.netAmount)
Conditional Totaling
Sum values only when a condition is met:
serviceTotal=totalizeif(details,details.price,select case when {details.item.item.itemType} = 'Service' then 1 else 0 end)
SQL-Based Calculations
weightedTotal=totalizesql(select {details.quantity} * {details.unitPrice} * {details.discount} / 100)
Database Queries
Simple SQL Queries
customerBalance=sql(select balance from Customer where id = {customer.id})
lastInvoiceDate=sql(select max(valueDate) from SalesInvoice where customer_id = {customer.id})
Multi-line SQL
complexValue=mlsql(
select case
when {totalAmount} > 1000 then 'High'
when {totalAmount} > 500 then 'Medium'
else 'Low'
end
)endmlsql
Conditional Value Selection
First Not Empty
Returns the first value that is not empty:
details.ref1=firstNotEmpty(details.ref1,ref1,customer.ref1)
contactPhone=firstNotEmpty(customer.mobile,customer.phone,customer.contact.phone)
First Not Null
Returns the first value that is not null:
details.project=firstNotNull(details.project,project,customer.defaultProject)
Reference Creation
Create references to other entities:
# Fixed reference
relatedInvoice=ref("SalesInvoice","SIV150160")
# Dynamic reference based on SQL
parentDoc=ref(ref2.entityType,sql(select id from SalesInvoice where code = {ref1}))
Advanced Line Matching
Match Lines By Fields
Match source and target lines based on specific fields:
matchLinesBy=details.item.item=lines.ref1,details.warehouse=lines.warehouse(
details.quantity=lines.quantity
details.price=lines.unitPrice
details.discount=lines.discount
)endMatchLinesBy
This will:
- Match lines where item and warehouse are the same
- Only copy data between matched lines
- Ignore unmatched lines
Filter Lines
Process only specific lines based on conditions:
filterLinesBy=(
filterSourceDetail=details
filterSourceBy=sql(select case when {details.quantity} > 0 then 1 else 0 end)
filterTargetDetail=lines
filterTargetBy=sql(select case when {lines.item.item.isActive} = 1 then 1 else 0 end)
# Copy only between filtered lines
lines.quantity=details.quantity
)endFilterLinesBy
You can filter source only, target only, or both
Special Operations
Switch Target/Source
Temporarily change what entity you're copying to:
switchTarget=relatedDocument(
# Now copying TO each related document
status="Processed"
processedBy=currentUser
processedDate=sql(select getdate())
)endSwitchTarget
switchSource=customer.ref1(
totalPurchases=n5 #n5 here will come from customer.ref1
)endSwitchSource
Working with Newly Added Lines
details=[addLines(5)]
details=addedLinesOnly(
details.item=defaultItem
details.quantity=1
details.price=defaultPrice
)
Line Selection
selectLine="details(0)" # Select first line (0-based index)
$line.quantity=10 # Set quantity of selected line
selectLine="details(2)" # Select third line
$line.price=sql(select {$line.quantity} * {$line.unitPrice}) # Calculate price
selectLine="details(last)" # Select last line
$line.isLast=true
Entity Commands
runCommand="edit" # Start editing mode
runCommand="save" # Save the entity
runCommand="recommit" # Re-save/recommit the entity
runCommand="forcestable" # Force update without validation
runCommand="unforcestable" # Cancel force update mode
runCommand="flush" # Flush database changes
runCommand="guessPeriod" # Auto-detect accounting period (DocumentFile only)
runCommand="makeValueDateToday" # Set value date to today (DocumentFile only)
runCommand="systemUpdateCalculatedFields" # Update all calculated fields
runCommand="regenledger" # Regenerate ledger entries (if applicable)
runCommand="runManualEntityFlow(EF005)" # Run specific entity flow by code
runCommand="encryptPassword" # Encrypt password field (NaMaUser only)
runCommand="doNotCheckQty" # Skip quantity checks (InvoiceWithStockEffect only)
runCommand="collectStockDocsIfEmpty" # Collect stock documents (InvoiceWithStockEffect only)
Updating Related Entities
# Update item from within invoice line
details.item.item.runCommand="edit"
details.item.item.lastSaleDate=valueDate
details.item.item.lastSalePrice=details.price
details.item.item.runCommand="save"
Security Features
Encryption/Decryption
# Encrypt sensitive data
encryptedCode=code.$encrypt1
encryptedSSN=customer.ssn.$encrypt2
# Decrypt when needed
originalCode=encryptedCode.$decrypt1
originalSSN=encryptedSSN.$decrypt2
OTP Generation
# Numeric OTP
otp4Digit=$createNumericOTP4 # e.g., 1234
otp6Digit=$createNumericOTP6 # e.g., 123456
# Alphanumeric OTP
otpCode=$createOTP4 # e.g., A1B2
otpLong=$createOTP8 # e.g., A1B2C3D4
Best Practices
1. Order Matters
Fields are processed in order, so dependent fields should come after their dependencies:
# Correct
subtotal=totalize(details,details.price)
tax=sql(select {subtotal} * 0.15)
total=sql(select {subtotal} + {tax})
# Incorrect (total calculated before tax)
total=sql(select {subtotal} + {tax})
subtotal=totalize(details,details.price)
tax=sql(select {subtotal} * 0.15)
2. Handle Empty Values
# Ensure a value is always set
warehouse=firstNotEmpty(details.warehouse,defaultWarehouse,"WH001")
3. Test Conditions
When using SQL conditions, test with simple cases first:
# Start simple
includeInTotal=sql(select 1)
# Then add complexity
includeInTotal=sql(select case when {item.itemType} = 'Service' then 1 else 0 end)
Troubleshooting
Common Errors
- "Field not found" - Check field spelling and entity structure
- "Type mismatch" - Ensure compatible data types (use ref() for references)
- "Empty result" - Check SQL queries return data
- "Index out of bounds" - Verify line numbers exist
Debugging Tips
- Start with simple direct copies
- Test SQL queries separately
- Use fixed values to isolate issues
- Check entity relationships are correct
- Verify user permissions for all operations
This documentation was generated by Claude.ai based on analysis of the Nama ERP source code and system functionality.