In a previous article I showed how easy it is to write a blank operation to add a specific item to a retail transaction:

Application.RunOperation(PosisOperations.ItemSale, "0110");
  

It doesn’t get much simpler than that:  a single line of code.

Unfortunately there is a limitation to this method:  you can only add an item with a quantity of one with its default selling price.  I recently had a situation where I wanted to add a negative quantity (to simulate a return) and use a calculated price.

I originally thought that I could just run the ItemSale operation and then manipulate the transaction right after it:

Application.RunOperation(PosisOperations.ItemSale, "0112");

RetailTransaction retailTransaction = posTransaction as RetailTransaction;
int iLastLine = Decimal.ToInt32(retailTransaction.NoOfItemLines);
SaleLineItem sl = retailTransaction.GetItem(iLastLine);
sl.Quantity = -1;
sl.Price = 12.34M;
retailTransaction.CalcTotals();
  

Not so much. This doesn’t work because the posTransaction is still a copy of the transaction from before you added the item.  There is no visibility into the transaction from after the item was added.

I didn’t want to go back to the “old” way of adding an item by manipulating the posTransaction directly.  For one thing I would lose the simplicity of the single line of code.  In addition there is still a problem where posTransaction doesn’t get converted to a RetailTransaction until after the first item has been added to the transaction.  This is a problem if you want to run your blank operation at the very start of a transaction.

Calling a Blank Operation from a Blank Operation

On a whim I decided to see what would happen if I tried to run a second blank operation from the first blank operation.  I was hoping that the second blank operation would have access to the updated posTransaction with the new item… and it did!

When you run a blank operation from a button you can pass in two parameters:  OperationId and Parameter.  I was worried that this would cause a problem when using the RunOperation to execute the blank operation.  Luckily the ExtraInfo parameter works on the this PosisOperations.BlankOperation as well:  you can pass in the OperationId and Parameter separated with a semicolon:

Application.RunOperation(PosisOperations.BlankOperation, "101; myparam");
  

This is the equivalent of setting up your button with the same values:

image

With this in mind I broke up the previous code into two operations:  100 to add the item to the transaction, 101 to manipulate:

switch (operationInfo.OperationId)
{
    case "100":
        Application.RunOperation(PosisOperations.ItemSale, "0112");
        Application.RunOperation(PosisOperations.BlankOperation, "101");
        operationInfo.OperationHandled = true;
        break;
    case "101":
        RetailTransaction retailTransaction = posTransaction as RetailTransaction;
        int iLastLine = Decimal.ToInt32(retailTransaction.NoOfItemLines);
        SaleLineItem sl = retailTransaction.GetItem(iLastLine);
        sl.Quantity = -1;
        sl.Price = 12.34M;
        retailTransaction.CalcTotals();
        operationInfo.OperationHandled = true;
        break;
    default:
        break;
}
  

Testing was easy:  I just added a button to operation “100” and gave it a try.  As hoped, a return of item 0112 for $12.34 was added to my transaction:

image

A couple of notes on the code:

  • There is no error checking in the second operation.  If you try the code with an item number that doesn’t exist in your inventory you’ll see that it fails with an “Item Not Found” error and then an unhandled error on the second operation.  If you already had an item in the transaction it would override that item with a negative quantity and $12.34.  Not good!

  • Note the call to CalcTotals() which is a great way to make sure that the transaction runs through the price, discount, tax logic every time you manipulate anything in the transaction.

  • Also see the “NoOfItemLines” which I used in conjunction with “GetItem()” to manipulate the last item on the `transaction.  This may not work properly if you are aggregating items.

The practical application of this exercise was to be able to add a service line item to zero out a transaction without using discounts.  For instance, if the transaction had a balance of $2.00 I would create a return item of $2.00 to offset.  Likewise, a ($3.00) transaction could have the same SKU to create a $3.00 item to zero it out.

Hopefully you can find a good real-world use for this little trick as well.