I have the following custom api that I’m attempting to use to create Ship-to Addresses but I don’t want to store the customer Id as well as the customer No. in my system. So I was hoping to just make the API lookup the correct customer No. based on the customer ID that I pass in and then store that number in the table.
I can’t seem to get this to work as it always wants me to a customer No along. I get the error
Customer No. must have a value in Ship-to Address: Customer No.=, Code=. It cannot be zero or empty.
It also appears like the Code is required. So do I have to make up a code and try to pass that in or can I have the system create a unique one?
What part of my AL code below is not allowing the customerNo to get looked up and set correctly based on the customerId?
I tried as is and with the commented out code instead. Neither seems to work. Thanks.
page 83704 "SF_APIV-ShipToAddresses"
{
PageType = API;
ChangeTrackingAllowed = true;
DelayedInsert = true;
EntityName = 'sf_shiptoaddress';
EntitySetName = 'sf_shiptoaddresses';
Extensible = false;
SourceTable = "Ship-to Address";
ODataKeyFields = SystemId;
layout
{
area(content)
{
repeater(Group)
{
field(id; Rec.SystemId)
{
Editable = false;
}
field(customerNo; Rec."Customer No.")
{
Editable = false; // Keep readonly to avoid conflict
}
// Our new input field for Customer SystemId
field(customerId; CustomerId) { }
field(code; Rec.Code) { }
field(name; Rec.Name) { }
}
}
}
actions
{
}
// Variables
var
CustomerId: Guid;
trigger OnInsertRecord(BelowxRec: Boolean): Boolean
var
CustomerRec: Record Customer;
begin
if CustomerRec.GetBySystemId(CustomerId) then begin
Rec."Customer No." := CustomerRec."No.";
// if not IsNullGuid(CustomerId) then begin
// if not CustomerRec.GetBySystemId(CustomerID) then
// Error('Customer with given ID not found.');
// Rec.Validate("Customer No.", CustomerRec."No.");
end;
end;
}
Customer No is the key in Ship to address, for each customers you go and define multiple ship to addresses, so that’s why you have to have this.
You are using Ship to Address as the source table so you need to mention for which customer you are doing the insertion. Have a look in BC Customer → Ship to Address and the table schema.
I think a good starting point is to look at how BC addresses this in its standard API… I’ve searched, and the “itemVariables” API page might be a good option:
namespace Microsoft.API.V2;
using Microsoft.Inventory.Item;
page 30052 "APIV2 - Item Variants"
{
APIVersion = 'v2.0';
EntityCaption = 'Item Variant';
EntitySetCaption = 'Item Variants';
DelayedInsert = true;
EntityName = 'itemVariant';
EntitySetName = 'itemVariants';
ODataKeyFields = SystemId;
PageType = API;
SourceTable = "Item Variant";
Extensible = false;
layout
{
area(Content)
{
repeater(Group)
{
field(id; Rec.SystemId)
{
Caption = 'Id';
Editable = false;
}
field(itemId; Rec."Item Id")
{
Caption = 'Item Id';
trigger OnValidate()
begin
if not IsNullGuid(Item.SystemId) then
if Item.SystemId <> Rec."Item Id" then
Error(ItemValuesDontMatchErr);
if Rec.GetFilter("Item Id") <> '' then
if Rec."Item Id" <> Rec.GetFilter("Item Id") then
Error(ItemValuesDontMatchErr);
if Rec."Item Id" = BlankGuid then
Rec."Item No." := ''
else
if not Item.GetBySystemId(Rec."Item Id") then
Error(ItemIdDoesNotMatchAnEmployeeErr);
end;
}
field(itemNumber; Rec."Item No.")
{
Caption = 'Item No.';
trigger OnValidate()
begin
if Rec."Item No." = '' then
Rec."Item Id" := BlankGuid
else
if not Item.Get(Rec."Item No.") then
Error(ItemNumberDoesNotMatchAnEmployeeErr);
if Rec.GetFilter("Item Id") <> '' then
if Item.SystemId <> Rec.GetFilter("Item Id") then
Error(ItemValuesDontMatchErr);
end;
}
field("code"; Rec.Code)
{
Caption = 'Code';
}
field(description; Rec.Description)
{
Caption = 'Description';
}
field(lastModifiedDateTime; Rec.SystemModifiedAt)
{
Caption = 'Last Modified Date';
Editable = false;
}
}
}
}
actions
{
}
trigger OnInsertRecord(BelowxRec: Boolean): Boolean
begin
if Rec.HasFilter() then
Rec.Validate("Item Id", Rec.GetFilter("Item Id"));
end;
trigger OnModifyRecord(): Boolean
var
ItemVariant: Record "Item Variant";
begin
ItemVariant.GetBySystemId(Rec.SystemId);
if Rec."Item No." = ItemVariant."Item No." then
Rec.Modify(true)
else begin
ItemVariant.TransferFields(Rec, false);
ItemVariant.Rename(Rec."Item No.", Rec."Code");
Rec.TransferFields(ItemVariant, true);
end;
exit(false);
end;
var
Item: Record Item;
ItemIdDoesNotMatchAnEmployeeErr: Label 'The "itemId" does not match to an Item.', Comment = 'itemId is a field name and should not be translated.';
ItemNumberDoesNotMatchAnEmployeeErr: Label 'The "itemNumber" does not match to an Item.', Comment = 'itemNumber is a field name and should not be translated.';
ItemValuesDontMatchErr: Label 'The item values do not match to a specific Item.';
BlankGuid: Guid;
}
Consider “itemId” and “itemNumber” as “customerId” and “customerNumber”.
The itemvariants table has both item id and item no. In the ship-to address table there is only customer no. so no customer id. So I don’t know how to make a api which accepts customer id and maps that to customer no. I don’t see anywhere that your example would do that on insert. It appears like it must just be doing that automatically when on insert validating or something like that.
Thanks for the help but I’m not thinking this code will work.