UNPKG

bc-code-intelligence-mcp

Version:

BC Code Intelligence MCP Server - Complete Specialist Bundle with AI-driven expert consultation, seamless handoffs, and context-preserving workflows

256 lines (213 loc) 9.81 kB
# FieldError Method Syntax - AL Code Sample ## Basic FieldError Syntax ```al // Basic FieldError syntax with automatic message table 50100 "Sales Document" { fields { field(1; "Document Type"; Enum "Sales Document Type") { } field(2; "Document No."; Code[20]) { } field(3; "Sell-to Customer No."; Code[20]) { } field(10; "Currency Code"; Code[10]) { } field(20; "Amount"; Decimal) { } } trigger OnInsert() begin // Validate required fields before insert ValidateRequiredFields(); end; local procedure ValidateRequiredFields() begin // FieldError assumes validation already failed - no testing performed if "Sell-to Customer No." = '' then FieldError("Sell-to Customer No."); // Generates: "Sell-to Customer No. must have a value in Sales Document Document Type='Order', Document No.='SO001'." if Amount <= 0 then FieldError(Amount); // Generates: "Amount must not be 0 in Sales Document..." end; } ``` ## FieldError vs TestField Comparison ```al codeunit 50100 "Validation Examples" { procedure DemonstrateFieldErrorVsTestField() var SalesHeader: Record "Sales Header"; Customer: Record Customer; begin SalesHeader.Get(SalesHeader."Document Type"::Order, 'SO001'); // TestField approach - tests condition AND throws error if failed SalesHeader.TestField("Sell-to Customer No."); // Tests if empty, then errors SalesHeader.TestField(Amount); // Tests if zero, then errors // FieldError approach - assumes you already validated the condition if SalesHeader."Sell-to Customer No." = '' then SalesHeader.FieldError("Sell-to Customer No."); // Only errors, no testing if SalesHeader.Amount <= 0 then SalesHeader.FieldError(Amount, 'must be positive'); // Custom message // Practical usage: FieldError for complex validation logic if not Customer.Get(SalesHeader."Sell-to Customer No.") then SalesHeader.FieldError("Sell-to Customer No.", 'customer does not exist'); if Customer.Blocked <> Customer.Blocked::" " then SalesHeader.FieldError("Sell-to Customer No.", StrSubstNo('customer is blocked (%1)', Customer.Blocked)); end; } ``` ## Custom Message Examples ```al table 50101 "Purchase Document" { fields { field(1; "Document Type"; Enum "Purchase Document Type") { } field(2; "Document No."; Code[20]) { } field(3; "Buy-from Vendor No."; Code[20]) { } field(10; "Expected Receipt Date"; Date) { } field(20; "Amount Including VAT"; Decimal) { } } procedure ValidateBusinessRules() var Vendor: Record Vendor; begin // Custom message examples - note lowercase first word convention if "Expected Receipt Date" < WorkDate() then FieldError("Expected Receipt Date", 'cannot be in the past'); if "Amount Including VAT" > 10000 then FieldError("Amount Including VAT", 'exceeds approval limit'); // Complex validation with detailed custom message if Vendor.Get("Buy-from Vendor No.") then begin if Vendor.Blocked <> Vendor.Blocked::" " then FieldError("Buy-from Vendor No.", StrSubstNo('vendor is blocked for %1', Vendor.Blocked)); if (Vendor."Payment Terms Code" = '') and ("Amount Including VAT" > 1000) then FieldError("Buy-from Vendor No.", 'requires payment terms for amounts over 1000'); end else FieldError("Buy-from Vendor No.", 'vendor does not exist'); end; } ``` ## Real-World Posting Codeunit Pattern ```al codeunit 50102 "Sales Document Validation" { // Pattern used in standard BC posting codeunits (12, 80, 90) procedure ValidateSalesDocument(var SalesHeader: Record "Sales Header") begin // Comprehensive validation before posting with SalesHeader do begin // Required field validation if "Sell-to Customer No." = '' then FieldError("Sell-to Customer No."); if "Document Date" = 0D then FieldError("Document Date"); // Business logic validation with custom messages if "Posting Date" < "Document Date" then FieldError("Posting Date", 'cannot be before document date'); if Status <> Status::Released then FieldError(Status, 'must be Released before posting'); // Complex validation scenarios ValidateCustomerCredit(SalesHeader); ValidateDimensions(SalesHeader); end; end; local procedure ValidateCustomerCredit(var SalesHeader: Record "Sales Header") var Customer: Record Customer; CustLedgerEntry: Record "Cust. Ledger Entry"; RemainingAmount: Decimal; begin Customer.Get(SalesHeader."Sell-to Customer No."); // Calculate customer's remaining credit CustLedgerEntry.SetRange("Customer No.", Customer."No."); CustLedgerEntry.SetRange(Open, true); CustLedgerEntry.CalcSums("Remaining Amt. (LCY)"); RemainingAmount := CustLedgerEntry."Remaining Amt. (LCY)"; // Validate credit limit if (Customer."Credit Limit (LCY)" > 0) and (RemainingAmount + SalesHeader."Amount Including VAT" > Customer."Credit Limit (LCY)") then SalesHeader.FieldError("Sell-to Customer No.", StrSubstNo('credit limit exceeded. Available credit: %1', Customer."Credit Limit (LCY)" - RemainingAmount)); end; local procedure ValidateDimensions(var SalesHeader: Record "Sales Header") var DimMgt: Codeunit DimensionManagement; DimSetID: Integer; begin DimSetID := SalesHeader."Dimension Set ID"; // Validate required dimensions if not DimMgt.CheckDimIDComb(DimSetID) then SalesHeader.FieldError("Dimension Set ID", 'invalid dimension combination'); // Validate dimension values against posting rules if not DimMgt.CheckDimValuePosting(DimSetID, DATABASE::"Sales Header", SalesHeader."No.") then SalesHeader.FieldError("Dimension Set ID", 'dimension values not allowed for posting'); end; } ``` ## Advanced FieldError Patterns ```al codeunit 50103 "Advanced Validation Patterns" { // Pattern: Conditional validation with detailed context procedure ValidateItemAvailability(var SalesLine: Record "Sales Line") var Item: Record Item; AvailableQty: Decimal; begin if SalesLine.Type <> SalesLine.Type::Item then exit; // Only validate items Item.Get(SalesLine."No."); Item.CalcFields(Inventory, "Reserved Qty. on Inventory"); AvailableQty := Item.Inventory - Item."Reserved Qty. on Inventory"; if SalesLine.Quantity > AvailableQty then SalesLine.FieldError(Quantity, StrSubstNo('exceeds available inventory (%1 available)', AvailableQty)); end; // Pattern: Multi-field validation with specific field error procedure ValidatePriceAndDiscount(var SalesLine: Record "Sales Line") begin // Validate that discount doesn't exceed unit price if (SalesLine."Unit Price" > 0) and (SalesLine."Line Discount Amount" > SalesLine."Unit Price" * SalesLine.Quantity) then SalesLine.FieldError("Line Discount Amount", 'cannot exceed line amount'); // Validate price against minimum price rules if SalesLine."Unit Price" < GetMinimumPrice(SalesLine) then SalesLine.FieldError("Unit Price", StrSubstNo('cannot be below minimum price (%1)', GetMinimumPrice(SalesLine))); end; local procedure GetMinimumPrice(SalesLine: Record "Sales Line"): Decimal var Item: Record Item; begin if Item.Get(SalesLine."No.") then exit(Item."Unit Cost" * 1.1) // 10% markup minimum else exit(0); end; } ``` ## Error Context and Message Output Examples ```al // When this validation fails: procedure ExampleValidationScenarios() var SalesHeader: Record "Sales Header"; begin SalesHeader."Document Type" := SalesHeader."Document Type"::Order; SalesHeader."No." := 'SO001'; SalesHeader."Sell-to Customer No." := ''; // Empty value // This will generate message: // "Sell-to Customer No. must have a value in Sales Header Document Type='Order', No.='SO001'." SalesHeader.FieldError("Sell-to Customer No."); // With custom message: // "Sell-to Customer No. is required for orders in Sales Header Document Type='Order', No.='SO001'." SalesHeader.FieldError("Sell-to Customer No.", 'is required for orders'); // For non-empty field with custom message: SalesHeader."Sell-to Customer No." := 'INVALID'; // "Sell-to Customer No. customer does not exist in Sales Header Document Type='Order', No.='SO001'." SalesHeader.FieldError("Sell-to Customer No.", 'customer does not exist'); end; ```