How to stop adding new SOLines in Sales Orders Screen according to a condition in Acumatica - customization

I want to stop adding new lines to a sales order based on a condition in Acumatica. How can I do this.?
I tried adding the following. But It did not worked.
protected void SOLine_RowInserting(PXCache cache, PXRowInsertingEventArgs e)
{
var row = (SOLine)e.Row;
if (row == null) return;
//Condition
if(Condition == true)
{
Base.Transaction.Delete(row);
}
}

Set AllowInsert cache property to false from the context of RowSelected event.
void _(Events.RowSelected<SOLine> e, PXRowSelected baseMethod)
{
baseMethod(e.Cache, e.Args);
bool canInsertCondition = false;
Base.Transaction.Cache.AllowInsert = canInsertCondition;
}

Related

Count bool true/false change inside game update loop

What would be the best way of counting how many times a bool flag was changed from false to true inside a game update loop? For example if I have this simple example below, where if you hold button "A" pressed the Input class sets the enable bool of the Game class to true and if you release it sets it to false and a counter inside the Game class that counts how many times enable was changed from true to false. For example if you press "A" and release twice counter should update to 2. Having Game::Update() updating at 60fps the counter would be wrong with the current approach. To fix it I moved the check and the counter inside SetEnable instead of the Update loop.
// Input class
// Waits for input
void Input::HandleKeyDown()
{
// Checks if key A is pressed down
if (key == KEY_A)
game.SetEnable(true);
}
void Input::HandleKeyUp()
{
// Checks if key A is released
if (key == KEY_A)
game.SetEnable(false);
}
// Game class
void Game::SetEnable(bool enable)
{
if(enable == enable_)
return;
enable_ = enable;
//Will increment the counter as many times A was pressed
if(enable)
counter_ += 1;
}
void Game::Update()
{
// Updates with 60fps
// Will increment the counter as long as A is pressed
/*
if(enable_ == true)
counter_ += 1;
*/
}
void Game::Update()
{
if (key == KEY_A && ! enable_)
{
enable_ = true;
++counter_;
}
else if (key == KEY_B)
enable_ = false;
}
If I get you right, you want to count how many times enable_ changes. Your code has a small flaw, imagine this example:
enable_ = false
counter = 0
update gets called, key is A -> enable_ = true, counter = 1
update gets called, key is B -> enable_ = false, counter remains 1
Function that might fix this can look, for example, like this:
void Game::Update() {
if (key == KEY_A && !enable_) { // key is A and previous state is false
++counter;
enable_ = true;
}
if (key == KEY_B && enable_) { // key is B and previous state is true
++counter;
enable_ = false;
}
}

Tab to next visible column in QTableView

I have a custom QTableView and QAbstractTableModel. My QTableView hides some of the columns from the QAbstractTableModel as they aren't needed.
When I hit Tab, I would like to select the next available (editable) column. My current implementation is to grab the next index from the QAbstractTableModel, but this index includes columns that are hidden. (So when hitting Tab it may be a couple presses before you see the "next" column selected.)
How can I tell Tab to jump to the next visible column?
The language is C++. Below is the code within my QTableView:
void keyPressEvent(QKeyEvent* event)
{
if((event->modifiers() == Qt::KeyboardModifier::NoModifier) && (event->key() == Qt::Key::Key_Tab))
{
this->moveToNextCell();
}
else
{
this->QTableView::keyPressEvent(event);
}
}
void moveToNextCell()
{
const QModelIndex index = this->currentIndex();
int nextColumn = index.column() + 1;
if(index.column() <= lastEditableCol)
{
this->setCurrentIndex(model->index(index.row(), nextColumn));
}
}
It's not elegant, but I've solved the problem by using isColumnHidden() from QTableView. I just iterate through the columns until I find one that isn't hidden.
for(int i = nextColumn; i <= numOfColumns && nextColumn <= numOfColumns; i++)
{
if(this->isColumnHidden(nextColumn) == true)
{
nextColumn += 1;
}
else
{
i = numOfCol + 1;
}
}

AddNewRecord XamDataGrid

After entering a value in the AddNewRecord row, and clicking anywhere outside the row on the XamDataGrid seems to add the row to the collection.
How do I prevent mouse click from adding a new row to the collection.
Kindly any help
Clicking outside of the AddNewRecord ends edit mode on the record and if there were changes they are committed at that time which means the new record is added. If you were looking to only allow the record to be commmited when pressing the enter key and not by clicking another record in the grid, then you could use the following logic to set the mouse left button down as handled:
private bool editingAddNewRecord = false;
void XamDataGrid1_EditModeEnded(object sender, Infragistics.Windows.DataPresenter.Events.EditModeEndedEventArgs e)
{
this.editingAddNewRecord = false;
}
void XamDataGrid1_EditModeStarted(object sender, Infragistics.Windows.DataPresenter.Events.EditModeStartedEventArgs e)
{
this.editingAddNewRecord = e.Cell.Record.IsAddRecord;
}
void XamDataGrid1_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (editingAddNewRecord)
{
DataRecordPresenter drp = Infragistics.Windows.Utilities.GetAncestorFromType(e.OriginalSource as DependencyObject, typeof(DataRecordPresenter), true) as DataRecordPresenter;
if (!(drp != null && drp.IsAddRecord))
{
e.Handled = true;
}
}
}
Thanks for the answer #alhalama!
I noticed though that you don't handle the right mouse button down, and even when we do your solution doesn't work to support it. Also, with your solution I wasn't able to edit any other cells until I had hit Enter or Escape on the Add New Row record (which might be what some people want, but not me). Here is my modified solution that undoes changes to the Add New Record row's cell when the user clicks out of it, which also handles all mouse clicks (left, right, middle, etc.).
// Used to record when the user is editing a value in the Mass Edit row.
private DataRecord _addRecordCellBeingEdited = null;
private void XamDataGrid1_EditModeStarted(object sender, Infragistics.Windows.DataPresenter.Events.EditModeStartedEventArgs e)
{
if (e.Cell.Record.IsAddRecord)
_addRecordCellBeingEdited = e.Cell.Record;
}
private void XamDataGrid1_EditModeEnded(object sender, Infragistics.Windows.DataPresenter.Events.EditModeEndedEventArgs e)
{
_addRecordCellBeingEdited = null;
}
private void XamDataGrid1_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
if (_addRecordCellBeingEdited != null)
{
DataRecordPresenter drp = Infragistics.Windows.Utilities.GetAncestorFromType(e.OriginalSource as DependencyObject, typeof(DataRecordPresenter), true) as DataRecordPresenter;
if (!(drp != null && drp.IsAddRecord))
{
_addRecordCellBeingEdited.CancelUpdate();
}
}
}

Adding Row Specific context menu to an UltraWinGrid

I'm a newbie using Infragistics. I'm trying to add context menu to a specific row/column in UltraWinGrid, which I'm not able to. Looks like adding context menu to the grid is simple but adding it to a specific row/column is not straight forward. Can you please tell me how to do this?
You could add a context menu to the form or control your grid will reside in and only display it in when they right click in the grid over the rows/cells that need that menu.
Here's an example, though it's not pretty.
private void UltraGrid_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
ContextMenu.Hide();
Point point = new System.Drawing.Point(e.X, e.Y);
UIElement uiElement = ((UltraGridBase) sender).DisplayLayout.UIElement.ElementFromPoint(point);
UltraGridCell cell = (UltraGridCell) uiElement.GetContext(typeof (UltraGridCell));
if (cell != null && UseThisContextMenu(cell))
{
ContextMenu.Show();
}
}
}
MouseDown does not work. Please use MouseUp.
private void UltraGrid1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
Point point = new System.Drawing.Point(e.X, e.Y);
UIElement uiElement = ((UltraGridBase)sender).DisplayLayout.UIElement.ElementFromPoint(point);
UltraGridCell cell = (UltraGridCell)uiElement.GetContext(typeof(UltraGridCell));
if (cell.Band.Index == 0)
{
if (cell.Column.Key.Equals("ColumnToShow"))
{
contextMenuStrip.Show();
}
else
{
contextMenuStrip.Hide();
}
}
}
}
}

Sitecore Workflow and Pipelines

I'm trying to implement a basic Javascript confirmation box on a workflow command (e.g. "are you sure you want to edit this?"). Depending on whether a users clicks yes or no, I want to move to a different state in the workflow. Here is the code I currently have (some logic is taken out):
[Serializable]
public class ConfirmAction
{
public void Process(WorkflowPipelineArgs args)
{
Item currentItem = args.DataItem;
ClientPipelineArgs clientArgs = new ClientPipelineArgs();
Sitecore.Context.ClientPage.Start(this, "DialogProcessor", clientArgs);
}
protected void DialogProcessor(ClientPipelineArgs args)
{
if (args.IsPostBack)
{
if (args.Result != "yes")
{
args.AbortPipeline();
return;
}
}
else
{
Sitecore.Context.ClientPage.ClientResponse.Confirm("Are you sure you want to edit this?");
args.WaitForPostBack();
}
}
}
I'm new to the Pipeline model, especially in relation to Sitecore, so I'm somewhat grasping at straws. The problem that I'm having, I believe, is that I don't have a way of getting the result back to the Workflow Pipeline, from the ClientResponse pipeline, to tell it what to do.
Thank you.
EDIT:
Using Yan's information, I eventually came up with the following solution:
public void Process(WorkflowPipelineArgs args)
{
Item currentItem = args.DataItem;
ClientPipelineArgs clientArgs = new ClientPipelineArgs();
clientArgs.Parameters.Add("itemID", currentItem.ID.ToString());
clientArgs.Parameters.Add("stateID", currentItem.Fields["__Workflow state"].Value);
Sitecore.Context.ClientPage.Start(this, "DialogProcessor", clientArgs);
}
protected void DialogProcessor(ClientPipelineArgs args)
{
if (args.IsPostBack)
{
if (args.Result != "yes")
{
Item currentItem = Sitecore.Configuration.Factory.GetDatabase("master").GetItem(args.Parameters["itemID"]);
currentItem.Editing.BeginEdit();
currentItem.Fields["__Workflow state"].Value = args.Parameters["stateID"];
currentItem.Editing.EndEdit();
return;
}
SheerResponse.Eval("window.location.reload();");
}
else
{
Sitecore.Context.ClientPage.ClientResponse.YesNoCancel("Are you sure you want to edit this?", "200", "200");
args.WaitForPostBack();
}
}
Well, I think this is where you can take advantage from ClientPipelineArgs. Let's say you add the current item ID to the parameters to pass:
public void Process(WorkflowPipelineArgs args)
{
Item currentItem = args.DataItem;
ClientPipelineArgs clientArgs = new ClientPipelineArgs();
clientArgs.Parameters.Add("id", currentItem.ID.ToString());
Sitecore.Context.ClientPage.Start(this, "DialogProcessor", clientArgs);
}
and later on when you get positive result you get it back and move to the target workflow state (explained in comments):
protected void DialogProcessor(ClientPipelineArgs args)
{
if (args.IsPostBack)
{
if (args.Result == "yes")
{
// 1. take item ID from args.Parameters["id"];
// 2. get item by this ID
// 3. move item to target workflow state
}
}
else
{
Sitecore.Context.ClientPage.ClientResponse.Confirm("Are you sure you want to edit this?");
args.WaitForPostBack();
}
}
This might require some minor changes (I didn't run it myself before posting), but hope you get the idea.