Advantage Concepts
In order to keep this example simple, we are just going to make our AEP add a new record to the orders table and return. A real-world AEP would likely perform actions such as updating the accounts receivable table, modifying the inventory, and updating the sales representative’s quota numbers.
Cut/paste the following helper function into the body of your AEP, directly above MyProcedure:
{* Helper function for returning output parameters. *}
procedure ReturnParameter( tblOutput : TAdsTable; strVar : string; vValue : variant );
begin
with tblOutput do
begin
open;
{* If we've already set up a parameter to return then we'll already have a
* row in this table, so don't add one. *}
if eof then
insert
else
edit;
FieldByName( strVar ).Value := vValue;
post;
close;
end;
end;
function MyProcedure( ulConnectionID: UNSIGNED32;
hConnection: ADSHANDLE;
pulNumRowsAffected: PUNSIGNED32 ): UNSIGNED32;
{$IFDEF WIN32}stdcall;{$ENDIF}{$IFDEF LINUX}cdecl;{$ENDIF} // Do not change prototype
var
strManufacturer : string;
strProduct : string;
iQuantity : integer;
iNewOrderNum : integer;
ItemPrice : currency;
DM1 : TDM1;
begin
Result := AE_SUCCESS;
{* Get this connection's data module from the session manager. *}
DM1 := TDM1( AEPSessionMgr.GetDM( ulConnectionID ) );
try
with DM1 do
begin
{* MyProcedure is called with the following input parameters:
* manufacturer
* product id
* quantity
*}
tblInput.open;
strManufacturer := tblInput.FieldByName( 'mfr' ).Value;
strProduct := tblInput.FieldByName( 'product' ).Value;
iQuantity := tblInput.FieldByName( 'quantity' ).Value;
tblInput.close;
{* Now we have our input parameters, so let's get to work. *}
tblProducts.Locate( 'mfr_id;product_id', VarArrayOf( [strManufacturer, strProduct] ) , [] );
{* Save the item price. *}
ItemPrice := tblProducts.FieldByName( 'price' ).Value;
{* Reduce the number on hand. *}
tblProducts.Edit;
tblProducts.FieldByName( 'qty_on_hand' ).Value := tblProducts.FieldByName( 'qty_on_hand' ).Value - iQuantity;
tblProducts.Post;
{* Add a new record to the orders table.
* NOTE : This is no where near multi-user safe (not checking for a
* lock failure). For the purpose of this example we will just use
* an order number one larger than the last order. *}
with tblOrders do
begin
Last;
Edit; {* this will lock the record. *}
iNewOrderNum := FieldByName( 'order_num' ).AsInteger + 1;
Append;
FieldByName( 'order_num' ).Value := iNewOrderNum;
FieldByName( 'order_date' ).Value := Date;
FieldByName( 'mfr' ).Value := strManufacturer;
FieldByName( 'product' ).Value := strProduct;
FieldByName( 'qty' ).Value := iQuantity;
FieldByName( 'amount' ).Value := iQuantity * ItemPrice;
Post;
end;
{* MyProcedure returns the following output parameters:
* order number
* total price
*}
ReturnParameter( tblOutput, 'order_num', iNewOrderNum );
ReturnParameter( tblOutput, 'total_price', iQuantity * ItemPrice );
end; {* with DM1 *}
except
on E : EADSDatabaseError do
{* ADS-specific error, use ACE error code *}
DM1.DataConn.Execute( 'INSERT INTO __error VALUES ( ' + IntToStr( E.ACEErrorCode ) + ', ' + QuotedStr( E.Message ) + ' )' );
on E : Exception do
{* other error *}
DM1.DataConn.Execute( 'INSERT INTO __error VALUES ( 1, ' + QuotedStr( E.Message ) + ' )' );
end;
end;
If using Delphi 6 or greater, add "Variants" to the uses clause.
Select Build from the Project menu.
You should now have a file called MyFirstAEP.aep in your working directory.