Codeunits - Business Logic
This document describes the codeunits that implement the core business logic for Texas Star Nuts operations.
Overview
The extension includes 9 codeunits organized by functional area:
- TSN Event Subscriber (50004) - Primary event handler
- TSN Functions (50007) - Utility and tracking functions
- TSN Warehouse Functions (50008) - Warehouse-specific utilities
- TSN WMS Extension (50000) - Warehouse Insight integration
- TSN Shelf Life Management (50002) - Expiration validation
- TSN Planning Management (50005) - Inventory planning
- TSN Item Application Management (50003) - Item ledger management
- TSN Miracle Functions (50001) - Miracle ERP integration
- TSN Report Helper Functions (50006) - Reporting utilities
1. TSN Event Subscriber (Codeunit 50004)
Location: src/codeunits/TSNEventSubscriber.Codeunit.al
Purpose
Primary event handler that intercepts standard Business Central processes to inject custom logic. This is the core integration point for most custom functionality.
Key Responsibilities
A. Warehouse Shipment Processing
- Bill of Lading Synchronization: Maps BOL number to TrueCommerce EDI fields
- EDI Field Mapping: Synchronizes warehouse data to TRC* fields
- ASN Type Determination: Automatically sets Pick & Pack vs. Pallet Pick & Pack
- Shipment Data Updates: Syncs trailer, seal, and shipping agent information
B. Sales Order Management
- Dimension Source Management: Handles dimension sources for sales orders
- Shipment Information Sync: Updates sales headers with warehouse shipment data
C. Purchase Order Processing
- Field Copying: Copies custom fields during purchase line processing
- Item Creation: Handles custom fields when items are created from purchase orders
D. Item Tracking
- Lot Validation: Validates lot tracking specifications
- Pick Synchronization: Syncs registered picks with item tracking
- Tracking Specification: Ensures lot numbers are properly tracked
E. Production Order Management
- Status Transitions: Manages production order status changes
- Field Preservation: Preserves custom fields during status updates
Key Event Subscribers
Trigger: When warehouse shipment is created from warehouse request
Action:
- Initializes Bill of Lading number from number series
- Sets up initial EDI field mappings
// Pseudo-code example
OnAfterCreateWhseShipmentHeaderFromWhseRequest(WarehouseShipmentHeader)
begin
// Generate BOL number
WarehouseShipmentHeader."Bill of Lading No." := GetNextBOLNumber();
// Initialize TrueCommerce fields
WarehouseShipmentHeader.TRCBillofLading := WarehouseShipmentHeader."Bill of Lading No.";
WarehouseShipmentHeader.TRCUDF2 := WarehouseShipmentHeader."Bill of Lading No.";
end;
Trigger: Before warehouse shipment header is modified
Action:
- Syncs Seal No. to TRCUDF3
- Syncs Trailer Reference to TRCTrailerNumber and TRCCarrierPro
- Updates shipping agent code to TRCUDF5
// Pseudo-code example
OnBeforeWhseShptHeaderModify(WarehouseShipmentHeader)
begin
// Sync seal number
if WarehouseShipmentHeader."Seal No." <> '' then
WarehouseShipmentHeader.TRCUDF3 := WarehouseShipmentHeader."Seal No.";
// Sync trailer reference
if WarehouseShipmentHeader."Trailer Reference" <> '' then begin
WarehouseShipmentHeader.TRCTrailerNumber := WarehouseShipmentHeader."Trailer Reference";
WarehouseShipmentHeader.TRCCarrierPro := WarehouseShipmentHeader."Trailer Reference";
end;
// Sync shipping agent code
if WarehouseShipmentHeader."Shipping Agent Code" <> '' then
WarehouseShipmentHeader.TRCUDF5 := WarehouseShipmentHeader."Shipping Agent Code";
end;
Event: OnAfterWhseShipmentLineInsert
Trigger: After warehouse shipment line is inserted
Action:
- Calculates and sets ASN type based on total quantity
- Updates sales header with ASN type
// Pseudo-code example
OnAfterWhseShipmentLineInsert(WarehouseShipmentLine)
begin
if SalesHeader.Get(SalesHeader."Document Type"::Order, WarehouseShipmentLine."Source No.") then begin
SalesHeader.CalcFields("TSN Total Quantity");
// Determine ASN Type based on quantity
if SalesHeader."TSN Total Quantity" > 25 then
SalesHeader.TRCASNType := SalesHeader.TRCASNType::"Pallet Pick and Pack"
else
SalesHeader.TRCASNType := SalesHeader.TRCASNType::"Pick and Pack";
SalesHeader.Modify();
end;
end;
Event: OnBeforePostWhseShipment
Trigger: Before warehouse shipment is posted
Action:
- Final validation of EDI fields
- Ensures all required shipment data is present
- Performs final BOL number synchronization
Event: OnAfterRegisterPick
Trigger: After pick is registered
Action:
- Syncs registered pick quantities with item tracking
- Ensures lot/serial numbers are properly assigned
Event: OnBeforeProductionOrderStatusChange
Trigger: Before production order status changes
Action:
- Preserves custom field values during status transitions
- Validates status change is allowed
- Warehouse Shipment Header/Lines - Primary data source
- Sales Header/Lines - Order data sync
- Purchase Header/Lines - Purchase order processing
- Production Order - Manufacturing order management
- Item Tracking - Lot/serial number management
2. TSN Functions (Codeunit 50007)
Location: src/codeunits/TSNFunctions.Codeunit.al
Purpose
General-purpose utility functions for lot tracking, barcode generation, and data access control.
Key Functions
A. Item Tracking Functions
SyncRegisteredPicksWithTracking()
Purpose: Synchronizes registered pick quantities with item tracking specifications
Parameters:
- RegisteredWhseActivityLine: Registered pick line
Logic:
- Retrieves item tracking for the pick
- Updates tracking specification with actual picked quantities
- Ensures lot/serial numbers match physical picks
SuggestLotNoByLocation()
Purpose: Suggests lot numbers for picking based on location and FEFO logic
Parameters:
- ItemNo: Item number
- VariantCode: Item variant
- LocationCode: Warehouse location
- BinCode: Specific bin (optional)
Returns: Suggested lot number
Logic:
- Filters warehouse entries by location
- Applies FEFO (First Expiry, First Out) logic
- Considers available quantity
- Returns optimal lot number for picking
GetItemTracking()
Purpose: Retrieves item tracking information for a document line
Parameters:
- SourceType: Document type (Sales, Purchase, Transfer, etc.)
- SourceSubtype: Document subtype
- SourceID: Document number
- SourceRefNo: Line number
Returns: Item tracking specifications
Logic:
- Queries Item Tracking Specification table
- Filters by source document
- Returns lot/serial numbers assigned to the line
B. Financial Data Access Control
CanViewFinancialData()
Purpose: Determines if current user can view financial information
Returns: Boolean
Logic:
- Checks user setup for financial data access flag
- Returns true if user has permission
- Used to control visibility of cost/pricing fields
C. Global Group Management
GetGlobalGroupCaption()
Purpose: Retrieves the custom caption for a global group
Parameters:
- GroupNo: Global group number (1-5)
Returns: Caption text
Logic:
- Reads Inventory Setup for group captions
- Returns configured caption (e.g., “Product Category”)
- Defaults to “Global Group X” if not configured
ValidateGlobalGroupValue()
Purpose: Validates a global group value exists
Parameters:
- GroupCode: Global group code
- ValueCode: Value code to validate
Returns: Boolean
Logic:
- Checks TSN Global Group Value table
- Returns true if value exists
- Used during data entry validation
D. Barcode Generation
GenerateBarcode()
Purpose: Generates barcodes for labels and documents
Parameters:
- BarcodeText: Text to encode
- BarcodeType: Format (Data Matrix, QR Code, Code 39)
Returns: Barcode image as TempBlob
Logic:
- Uses Barcode Generator extension
- Encodes text in specified format
- Returns image ready for printing
Supported formats:
- Data Matrix: 2D barcode for high-density encoding
- QR Code: 2D barcode for general use
- Code 39: Linear barcode for simple applications
Usage Examples
Example 1: Suggest Lot for Picking
// Suggest best lot for item at location MAIN
LotNo := TSNFunctions.SuggestLotNoByLocation('NUT-ALMOND-1000', '', 'MAIN', '');
// Returns lot with earliest expiration (FEFO)
Example 2: Check Financial Data Access
// Hide cost fields if user doesn't have access
if not TSNFunctions.CanViewFinancialData() then
CurrPage.UnitCost.Visible := false;
Example 3: Get Global Group Caption
// Get caption for Global Group 1
GroupCaption := TSNFunctions.GetGlobalGroupCaption(1);
// Returns "Product Category" (if configured) or "Global Group 1"
- Warehouse Entry - Lot tracking data
- Item Tracking Specification - Tracking assignments
- User Setup - Access control
- Inventory Setup - Global group configuration
- Barcode Generator - External barcode library
3. TSN Warehouse Functions (Codeunit 50008)
Location: src/codeunits/TSNWarehouseFunctions.Codeunit.al
Purpose
Specialized functions for warehouse operations.
Key Functions
GetNextBOLNumber()
Purpose: Generates next Bill of Lading number from number series
Returns: Next BOL number
Logic:
- Reads BOL number series from Warehouse Setup
- Uses NoSeriesManagement to get next number
- Returns formatted BOL number
Usage:
BOLNo := TSNWarehouseFunctions.GetNextBOLNumber();
WarehouseShipmentHeader."Bill of Lading No." := BOLNo;
ValidateBOLNumber()
Purpose: Validates BOL number format and uniqueness
Parameters:
- BOLNo: BOL number to validate
Returns: Boolean
CalculateShipmentWeight()
Purpose: Calculates total weight for warehouse shipment
Parameters:
- WarehouseShipmentNo: Shipment document number
Returns: Total weight (decimal)
CalculateShipmentVolume()
Purpose: Calculates total volume/cubage for warehouse shipment
Parameters:
- WarehouseShipmentNo: Shipment document number
Returns: Total volume (decimal)
- Warehouse Setup - BOL number series configuration
- Warehouse Shipment Header/Lines - Shipment data
- No. Series Management - Number generation
4. TSN WMS Extension (Codeunit 50000)
Location: src/codeunits/TSNWMSExtension.Codeunit.al
Purpose
Integration layer for Warehouse Insight (IWorks) Advanced WMS system.
Key Responsibilities
- Handles warehouse receipt line updates during manual item receipt
- Manages alternate lot number tracking
- Tracks country of origin for received items
- License plate template integration
Key Event Subscribers
Event: OnAfterManualItemReceiptLineCreate
Trigger: After manual warehouse receipt line is created in Warehouse Insight
Action:
- Copies alternate lot number from purchase order line
- Populates country of origin from purchase line
- Sets up item tracking for the receipt
// Pseudo-code example
OnAfterManualItemReceiptLineCreate(WarehouseReceiptLine, PurchaseLine)
begin
// Copy alternate lot number
if PurchaseLine."Alternate Lot No." <> '' then
WarehouseReceiptLine."Alternate Lot No." := PurchaseLine."Alternate Lot No.";
// Copy country of origin
if PurchaseLine."Country of Origin" <> '' then
WarehouseReceiptLine."Country of Origin" := PurchaseLine."Country of Origin";
end;
Event: OnBeforeLicensePlateCreate
Trigger: Before license plate is created in WMS
Action:
- Determines if template should create package-level license plates
- Controls pallet vs. package license plate creation
Integration Points
- Warehouse Insight WMS - Advanced warehouse management
- Purchase Order Lines - Source data for receiving
- License Plate System - Pallet/package tracking
- IWX License Plate Template - License plate configuration
- Warehouse Receipt Header/Lines - Receiving documents
- Purchase Line - Purchase order data
5. TSN Shelf Life Management (Codeunit 50002)
Location: src/codeunits/TSNShelfLifeManagement.Codeunit.al
Purpose
Enforces customer-specific shelf life requirements during picking operations. Prevents shipping products that don’t meet minimum shelf life requirements.
Key Functions
ValidateShelfLife()
Purpose: Validates lot meets customer shelf life requirement
Parameters:
- CustomerNo: Customer account number
- ItemNo: Item number
- LotNo: Lot number to validate
- ShipmentDate: Planned shipment date
Returns: Boolean (true if meets requirement)
Logic:
- Retrieves customer shelf life requirement (e.g., 60 days)
- Gets lot expiration date
- Calculates remaining shelf life at shipment date
- Returns true if remaining shelf life >= requirement
- Returns false if insufficient shelf life
Event: OnBeforeCreatePick
Trigger: Before pick is created for warehouse shipment
Action:
- Validates each lot against customer shelf life requirement
- Filters out lots with insufficient shelf life
- Ensures only compliant lots are picked
// Pseudo-code example
OnBeforeCreatePick(WarehouseShipmentLine, var TempBinContent)
begin
CustomerNo := GetCustomerNo(WarehouseShipmentLine);
ShipmentDate := WarehouseShipmentLine."Shipment Date";
// Filter bin content to only include lots meeting shelf life
TempBinContent.SetFilter("Lot No.", '<>%1', '');
if TempBinContent.FindSet() then
repeat
if not ValidateShelfLife(CustomerNo, TempBinContent."Item No.",
TempBinContent."Lot No.", ShipmentDate) then
TempBinContent.Delete();
until TempBinContent.Next() = 0;
end;
GetCustomerShelfLifeRequirement()
Purpose: Retrieves shelf life requirement for customer
Parameters:
- CustomerNo: Customer account number
- ItemNo: Item number (optional, for item-specific requirements)
Returns: Shelf life requirement in days
Logic:
- Reads customer master data
- Returns shelf life days required
- May vary by item category
CalculateRemainingShelfLife()
Purpose: Calculates remaining shelf life for a lot
Parameters:
- LotNo: Lot number
- ReferenceDate: Date to calculate from
Returns: Days of shelf life remaining
Logic:
- Gets lot expiration date
- Calculates days between reference date and expiration
- Returns days remaining
Business Impact
- Compliance: Ensures customer requirements are met
- Quality Assurance: Prevents shipping near-expiry products
- FEFO Integration: Works with First Expiry, First Out logic
- Customer Satisfaction: Delivers products with adequate shelf life
- Customer Table Extension - Shelf life requirements
- Lot No. Information - Expiration dates
- Warehouse Activity Lines - Pick validation
- FEFO Logic - First Expiry, First Out integration
6. TSN Planning Management (Codeunit 50005)
Location: src/codeunits/TSNPlanningManagement.Codeunit.al
Purpose
Adjusts inventory planning calculations to exclude quantities in bins marked as “Exclude from Planning.”
Key Functions
Event: OnAfterCalcAvailableQty
Trigger: After available quantity is calculated for planning
Action:
- Subtracts quantities in “Exclude from Planning” bins
- Adjusts projected available balance
// Pseudo-code example
OnAfterCalcAvailableQty(ItemNo, LocationCode, var AvailableQty)
begin
// Get quantity in excluded bins
ExcludedQty := CalculateExcludedBinQty(ItemNo, LocationCode);
// Adjust available quantity
AvailableQty := AvailableQty - ExcludedQty;
end;
CalculateExcludedBinQty()
Purpose: Calculates quantity in bins excluded from planning
Parameters:
- ItemNo: Item number
- LocationCode: Location code
Returns: Excluded quantity
Logic:
- Queries bin content where “Exclude from Planning” = true
- Sums quantity for the item/location
- Returns total excluded quantity
Use Cases
1. Quarantine Bins
Bins holding quarantined or hold inventory should not be included in available supply.
2. Samples and Testing
Bins with samples or items reserved for testing shouldn’t be planned.
3. Customer-Consigned Inventory
Bins with customer-owned consignment inventory excluded from planning.
- Bin Table Extension - Exclude from Planning flag
- Bin Content - Inventory by bin
- Planning Worksheet - Planning calculations
- Requisition Line - Planning recommendations
7. TSN Item Application Management (Codeunit 50003)
Location: src/codeunits/TSNItemApplicationManagement.Codeunit.al
Purpose
Manages item application and ledger entry relationships.
Key Responsibilities
- Handles custom item application logic
- Manages item ledger entry relationships
- Supports custom costing scenarios
8. TSN Miracle Functions (Codeunit 50001)
Location: src/codeunits/TSNMiracleFunctions.Codeunit.al
Purpose
Integration functions for Miracle ERP system.
Key Functions
- Miracle-specific data transformations
- System integration utilities
- Custom Miracle ERP workflow support
9. TSN Report Helper Functions (Codeunit 50006)
Location: src/codeunits/TSNReportHelperFunctions.Codeunit.al
Purpose
Utility functions for report generation and data formatting.
Key Functions
Purpose: Formats addresses for reports
Parameters:
- Address fields
Returns: Formatted address string
CalculateReportTotals()
Purpose: Calculates totals for report groupings
Parameters:
- Dataset records
Returns: Calculated totals
Purpose: Prepares barcode data for report printing
Parameters:
- Barcode text
- Format type
Returns: Formatted barcode data
- Custom Reports - Uses these helper functions
- Report Extensions - Formatting utilities
Codeunit Architecture
Event-Driven Design
Most codeunits use event subscriber pattern to integrate with standard BC processes without modifying core code.
Benefits:
- Upgrade Safety: Custom code preserved during BC upgrades
- Modularity: Changes isolated to specific functional areas
- Maintainability: Clear separation of concerns
- Testability: Individual units can be tested independently
Key Event Types:
- OnBefore: Pre-processing validation and modification
- OnAfter: Post-processing actions and synchronization
- OnValidate: Field-level validation logic
Summary
The codeunit architecture provides:
- Integration: Seamless connection with third-party systems (WMS, EDI)
- Automation: Automatic lot number generation, BOL numbering, field synchronization
- Validation: Shelf life compliance, planning exclusions, data validation
- Utilities: Barcode generation, financial access control, reporting helpers
- Flexibility: Event-driven design enables customization without core code changes
See Also: