This post is about creating a New CreateSalesLine form which is just going to work like SalesCreateOrder form except that this out of box form creates SO and the new one create SalesLine.
Let's start with the reasons why we may need this form - In out of box SalesTable form
1. whenever user clicks on the new button from toolbar all the user filters and sort expressions are lost and the active line item that user wants to refer will loose the focus, this is all because the datasource query re-executes. I tried to persist the user filters using my earlier post technique, but it didn't work for me in the case of new button.
2. since it is about referring an existing lineItem we can always use out of box "Copy from lines" function, but the issue with this one is - it doesn't allow user to change the ItemId of the line ( my user wants to use the values from existing lineItem for a new lineItem with different ItemId). i tried to solve this one by making ItemId field editable in the Salestable form, but it was causing chain of other errors - let me know if you have any luck with this.
So i came up with this approach where i provide a new button named "New LineItem" in the salesLine section of SalesTable form(Fig 1), on click i will pop-up the new form that i call CreateSalesLine (Fig 2)
Fig 1 Fig 2:
this form will create a new line item record and pre-populates it with values from the active lineItem record in Parent form(SalesTable). User can change the item number if needed and once OK button is clicked the newly created lineItem record is commited to DB , child form closes and the SalesLine grid in the parent form refreshes with the focus on newly Created LineItem.
Here are the things i did to achieve this :
Let's start with the reasons why we may need this form - In out of box SalesTable form
1. whenever user clicks on the new button from toolbar all the user filters and sort expressions are lost and the active line item that user wants to refer will loose the focus, this is all because the datasource query re-executes. I tried to persist the user filters using my earlier post technique, but it didn't work for me in the case of new button.
2. since it is about referring an existing lineItem we can always use out of box "Copy from lines" function, but the issue with this one is - it doesn't allow user to change the ItemId of the line ( my user wants to use the values from existing lineItem for a new lineItem with different ItemId). i tried to solve this one by making ItemId field editable in the Salestable form, but it was causing chain of other errors - let me know if you have any luck with this.
So i came up with this approach where i provide a new button named "New LineItem" in the salesLine section of SalesTable form(Fig 1), on click i will pop-up the new form that i call CreateSalesLine (Fig 2)
Fig 1 Fig 2:
SalesLine section in SalesTable form (Parent) |
New form - CreateSalesLine (Child) |
Here are the things i did to achieve this :
1. To simplify i have created this simple data flow diagram
2. within the new button's click event , i added :
CreateSalesLineClass obj;
;
obj = new CreateSalesLineClass();
obj.init(salesTable, salesTableForm, inventDim, salesLine); // passing current records info
4. CreateSalesLine form:
a) Add SalesLine datasource , add simple design tab control with some salesLine fields (Fig 2) and add Command buttons - OK and Cancel
b) CreateSalesLine form class declaration:
CreateSalesLineClass CreateSalesLineClass;
SalesTable salesTable;
SalesTableForm salesTableForm;
InventDim copyFromInventDim , inventDim;
SalesLine copyFromSalesLine, newlyCreatedSalesLine ;
c) init method:
Comments, questions are always welcome, happy DAXing :)
2. within the new button's click event , i added :
CreateSalesLineClass obj;
;
obj = new CreateSalesLineClass();
obj.init(salesTable, salesTableForm, inventDim, salesLine); // passing current records info
obj.create(); // we will discuss this method in subsequent steps
SalesTable_ds.research(true);
SalesLine_ds.research(true);
SalesLine_ds.findRecord(obj.newSalesLineRec()); // to focus the newly created record
super();
3. CreateSalesLineClass:
a) variables declared at class level scope:
SalesTable salesTable;
SalesTableForm salesTableForm;
InventDim inventDim;
SalesLine copyFromSalesLine;
Int64 newLineRecId;
SalesLine newSalesLineRec;
b) init method:
void init(SalesTable _currRec, SalesTableForm _salesTableForm, InventDim _inventDim, SalesLine _copyFromSalesLine)
{
;
salesTable = _currRec;
salesTableForm = _salesTableForm;
inventDim = _inventDim;
copyFromSalesLine = _copyFromSalesLine;
}
c) Create method:
boolean create()
{
Args args = new Args();
FormRun CreateSalesLine;
SalesLine salesLine;
boolean result = false;
SalesTable localSalesTable;
;
args.name(formStr(CreateSalesLine) );
args.caller(this);
CreateSalesLine = classFactory.formRunClass(args);
CreateSalesLine.init();
CreateSalesLine.run();
if(!CreateSalesLine.closed())
CreateSalesLine.wait();
if(CreateSalesLine.closedOk())
result = true;
else
result = false;
return result; // indicating if the new record is created or not
}
4. CreateSalesLine form:
a) Add SalesLine datasource , add simple design tab control with some salesLine fields (Fig 2) and add Command buttons - OK and Cancel
b) CreateSalesLine form class declaration:
CreateSalesLineClass CreateSalesLineClass;
SalesTable salesTable;
SalesTableForm salesTableForm;
InventDim copyFromInventDim , inventDim;
SalesLine copyFromSalesLine, newlyCreatedSalesLine ;
c) init method:
public void init()
{
super();
if (!element.args().caller()) // throw error if called directly
throw error("@SYS22539");
CreateSalesLineClass = element.args().caller();
salesTable = CreateSalesLineClass.getSalesTable();
salesTableForm = CreateSalesLineClass.getSalesTableForm();
copyFromInventDim = CreateSalesLineClass.getInventDim();
copyFromSalesLine = CreateSalesLineClass.getCopyFromSalesLine();
}
d) run method:
public void run()
{
super();
SalesLine_ds.create();
CreateSalesLineClass.newSalesLineRec(SalesLine); // pass the newly created salesline ref to caller
}
e) SalesLine_DS -> Create method:
public void create(boolean _append = false)
{
super(_append);
newlyCreatedSalesLine.data(SalesLine); // back up the newly created record
newlyCreatedInventDim.data(inventDim); // back up the newly created record
// we can use both the back-up buffers later if User changes the ItemId
// set the basic Line info
SalesLine.SalesId = salesTable.SalesId;
SalesLine.ItemId = copyFromSalesLine.ItemId;
inventDim.InventColorId = copyFromInventdim.InventColorId;
inventDim.InventLocationId = copyFromInventDim.InventLocationId;
inventDim = InventDim::findOrCreate(inventDim); // create new inventDim rec
SalesLine.InventDimId = inventDim.inventDimId;
SalesLine.CustAccount = salestable.CustAccount;
SalesLine.CurrencyCode = salesTable.CurrencyCode;
SalesLine.CustGroup = salesTable.CustGroup;
SalesLine.SalesType = salesTable.SalesType;
// copy data from active salesLine record in parent form, i just copied the data that my client needs
SalesLine.ReceiptDateRequested = copyFromSalesLine.ReceiptDateRequested;
SalesLine.ShippingDateRequested = copyFromSalesLine.ShippingDateRequested;
salesLine.SalesQty = copyFromSalesLine.SalesQty;
salesLine.SalesUnit = copyFromSalesLine.SalesUnit;
salesLine.QtyOrdered = copyFromSalesLine.QtyOrdered;
salesLine.SalesPrice = copyFromSalesLine.SalesPrice;
salesLine.PriceUnit = copyFromSalesLine.PriceUnit;
salesLine.LinePercent = copyFromSalesLine.LinePercent;
salesLine.LineDisc = copyFromSalesLine.LineDisc;
salesLine.MultiLnDisc = copyFromSalesLine.MultiLnDisc;
salesLine.MultiLnPercent = copyFromSalesLine.MultiLnPercent;
salesLine.SalesMarkup = copyFromSalesLine.SalesMarkup;
salesLine.LineAmount = copyFromSalesLine.LineAmount;
// you can copy more data as per your need , refer class SalesLineType.initFromSalesLine() - used by out of box copy line functionality
}
f) Override form's salesLine datasource's Write method:
public void write()
{
;
if (!element.closedOk())
return;
SalesLine.createLine(NoYes::Yes, NoYes::No, NoYes::No, NoYes::No);
super();
}
so far whatever i coded is good as long as User doesn't want to change the ItemId in the new form, my user like the ability to change the ItemId so i coded the following...
g) override the modified method for ItemId field of SalesLine datasource:
public void modified()
{
ItemId itemId;
;
super();
//info(strFmt('Old ItemId - %1', copyFromSalesLine.ItemId ));
//info(strFmt('New ItemId - %1', SalesLine.ItemId ));
itemId = SalesLine.ItemId;
SalesLine.data(newlyCreatedSalesLine); // restore from the back-up buffer
inventDim.data(newlyCreatedInventDim);
SalesLine.ItemId = itemId;
SalesLine_ds.refresh(); // refresh form data from the cache
info(strFmt('Old ItemId - %1', copyFromSalesLine.ItemId ));
inventDim = InventDim::findOrCreate(inventDim);//inventDim.data(InventDim::find(salesLine.InventDimId));
salesLine.modifyItemDim(inventDim, fieldnum(InventDim,InventLocationId), InventTable::find(salesLine.ItemId).DimGroupId);
InventMovement::bufferSetTransQtyUnit(salesLine);
salesLine.setDeliveryDateControlType(InventDim::findOrCreate(inventDim).InventDimId);
SalesLine::modifySalesQty(salesLine,inventDim);
SalesLine_ds.refresh();
//info( strFmt('AfterChange Invent Color and Location: %1 and %2', inventDim.InventColorId, inventDim.InventLocationId) );
// copying back
SalesLine.SalesId = salesTable.SalesId;
SalesLine.CustAccount = salestable.CustAccount;
SalesLine.CurrencyCode = salesTable.CurrencyCode;
SalesLine.CustGroup = salesTable.CustGroup;
SalesLine.SalesType = salesTable.SalesType;
SalesLine.ReceiptDateRequested = copyFromSalesLine.ReceiptDateRequested;
SalesLine.ShippingDateRequested = copyFromSalesLine.ShippingDateRequested;
salesLine.SalesQty = copyFromSalesLine.SalesQty;
salesLine.SalesUnit = copyFromSalesLine.SalesUnit;
salesLine.QtyOrdered = copyFromSalesLine.QtyOrdered;
SalesLine_ds.refresh();
}
No comments:
Post a Comment