PXAccumulatorAttribute in Acumatica

Few notes about PXAccumulatorAttribute

  1. If to inherit from PXAccumulatorAttribute, you'll have access to member _SingleRecord. If to set in constructor to true, you'll configure single record update mode.
  2. There is PrepareInsert method. This method intended for updating policy for the data fields.
  3. PrepareInsert is invoked within Persist method, before Acumatica framework generates SQL commands for inserted data records.
  4. Among paramethers of PrepareInsert method there is PXAccumulatorCollection, which has method Update. In this method it's possible to configure fields which will be updated during PrepareInsert
  5. Method Update has following policies: PXDataFieldAssign.AssignBehavior.Initialize ( new value is inserted into the database column only if value is null ), PXDataFieldAssign.AssignBehavior.Replace ( new value replces old value ), PXDataFieldAssign.AssignBehavior.Summarize ( new value is added to the value stored in the database ), PXDataFieldAssign.AssignBehavior.Maximize ( maximum of the new value and the value from the database is saved in the database ), PXDataFieldAssign.AssignBehavior.Minimize ( minimum of the new value and the value form database is saved in the database )

So, in order to implement Accumulator attribute, following steps are needed:

1. Inherit class from PXAccumulatorAttribute

2. Implement PrepareInsert method

3. Implement PersistInserted method.

Sources of trading ideas

Hello everybody,

For now I read book "Quantitative Trading: How to Build Your Own Algorithmic Trading Business"

and would like to note sources of trading ideas, which mentioned there:

 

Type URL
Business schools’ finance professors’ web sites www.hbs.edu/research/research.html
 Social Science Research Network www.ssrn.com
 National Bureau of Economic Research www.nber.org
Business schools’ quantitative finance seminars www.ieor.columbia.edu/seminars/ financialengineering
Mark Hulbert’s column in theNew York Times’ Sunday business section www.nytimes.com
Buttonwood column in the Economist magazine’s finance section www.economist.com
 Yahoo! Finance finance.yahoo.com
 TradingMarkets www.TradingMarkets.com
 Seeking Alpha www.SeekingAlpha.com
 TheStreet.com www.TheStreet.com
 The Kirk Repor www.TheKirkReport.com
 Alea Blog www.aleablog.com
 Abnormal Returns www.AbnormalReturns.com
 Brett Steenbarger Trading Psychology www.brettsteenbarger.com
 Ernest Chan epchan.blogspot.com
 Elite Trader www.Elitetrader.com
 Wealth-Lab www.wealth-lab.com
 Stocks, Futures and Options magazine www.sfomag.com

For my surprise Ernest claims that it's possible to find interesting strategies, which can work after some modifications

How to disable callback from Checkboxes in Acumatica

Hello everybody.

Today I want to share some details about inner kitchen of Checkboxes in grid of Acumatica.

If to look inside of generated grid of Acumatica with FireFox Dom and style inspector, you can see following structure:

Item with checkbox is implemented as td, which has div, and has another div. The first level div has data for internal ( Acumatica presentation ),

and second div, or internal div has data for user display.

Once I had task to disable callback from checkbox. You may wonder why somebody can have such task. The reason each tick at checkbox made 

roundtrip to server, called number of delegates, which significantly slowed down perfomance. By the way,  CommitChanges="false" didn't work. 

I mean after setting CommitChanges="false" roundtrip still was made, which made life of client little bit more nervous.

So in order to fix CommitChanges="false" this I wrote the following javascript code:

 

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js">
</script>
<script type="text/javascript">
  function checkDOMChange() {
    disableGridCheck();
    setTimeout(checkDOMChange, 100);
  }
  
  $(function () {
    checkDOMChange();
  }
   );
  
  function disableGridCheck() {
    $("[icon='GridUncheck']").on("click", function (elem) {
      $(this).attr("check", "1");
      $(this).attr("icon", "GridCheck");
      $($(this).children()[0]).attr("class", "control-icon-img control-GridCheck");
      return false;
    }
                                );
    $("[icon='GridCheck']").on("click", function (elem) {
      $(this).attr("check", "0");
      $(this).attr("icon", "GridUncheck");
      $($(this).children()[0]).attr("class", "control-icon-img control-GridUncheck");
      return false;
    }
                              );
  }
</script>

1. Function checkDOMChange is executed each 100 miliseconds, or 10 times per second. I don't know why, but jquery function document.read with junction with .on doesn't track newly created elements.

2.  $(function () { this code makes initial execution of tracking newly added elements at page.

3. Inside of code disableGridCheck we deal with two cases: when checkbox is changed. Due to fact, that checkbox implemented as td>div>div, I made code, which modifies two internal conditions.

How to enable disable menu item in Acumatica

Hello everybody,

Today I want to share short glimps how to Enable/Disable menu item. Let's some menu. For example it looks like this:

Suppose, we added menu action Activate in the following way:

public PXAction<EPEmployee> Activate;

[PXButton]
[PXUIField(DisplayName = "Activate")]
protected virtual IEnumerable activate(PXAdapter adapter)
{
   
}
// menu action was added like this:
public override void Initialize()
{
     Actions.AddMenuAction(Activate);
}

Let's say we want to disable menu item Activate. It can be achieved with usage of RowSelected event and SetEnabled function.  In my case I used the following construction:

protected virtual void EPEmployee_RowSelected(PXCache sender, PXRowSelectedEventArgs e)
{
      Actions.SetEnabled("activate", false);//this code will disable menu item activate
}

Take note, that we declared PXAction, which is repsonsible for menu. Then in action Initialize ( this is code from extension class ) we added menu item. And then we can manipulate with enabling/disabling it through Actions.SetEnabled

Make PXDefault as not required for input

Hello everybody,

Imagine following situation, you added to your DAC field some default value. For example like this:

[PXDBDate]
[PXDefault(typeof(AccessInfo.businessDate))]
public virtual DateTime? FromDate

And now you have default value as current date. But what, if you don't like to make it required for input. How to achieve this goal? The answer is quite simple, you just need to add PersistingCheck = PXPersistingCheck.Nothing into pxdefault attribute. Like this:

[PXDBDate]
[PXDefault(typeof(AccessInfo.businessDate), PersistingCheck = PXPersistingCheck.Nothing)]
public virtual DateTime? FromDate

With such changes you can init your values at form, and make it not required for input

Select all rows in Acumatica

Hello everybody,

today I want to share one simple trick. Sometime in grid you have chekcboxes, and you can have a need to make all of them selected. Here is sample of code which helps with this task:

<px:PXGridColumn AllowCheckAll="True" AllowNull="False" DataField="Selected" TextAlign="Center" Type="CheckBox" Width="30px" />

PXFilteredProcessing in Acumatica

Hello everybody,

few day ago I was digging in code of CT502000, and found interesting part of code:

public PXFilteredProcessing<ContractsList, ExpiringContractFilter> Items;

As usually in my code I use PXFilter, and discovery of PXFilteredProcessing was confusting for me. 

The first think that I as usually do, if I see something new, it is watching with reflector in declaration of new type. Here it what reflector shows:

public class PXFilteredProcessing<Table, FilterTable> : PXProcessing<Table> 
where Table: class, IBqlTable, new() where FilterTable: class, IBqlTable, new()

This means, that we can pass into PXFilteredProcessing two tables. T200 manual gives an answer why: Provides data records for processing with filtering. This data type takes two DACs as type parameters, where the second DAC specifies the filter DAC. You can use the

Where<>and OrderBy<>clauses in this data view type. It means, that items in Table will be filtered according to FilterTable. 

Save DAC class in acumatica to DB

Hello everybody,

today I want to note interesting gotcha. Let's say you want to save object to db in Acumatica. You in your code created some DAC item and want to save it to db. And you call Actions.PressSave() method. And you get error. You can get suspection, that maybe you put some wrong data in your DAC class or something like this. 

But the real reason is different, According to T200 Acumatica manual: " You should not invoke the Persist()method on the current graph instance. You can do it only for a graph instance created in a background operation."  It means that you should create instance of Graph, and in that instance call method Persist. 

Here is fragment, which I extracted with the help of reflector:

          ContractMaint instance = PXGraph.CreateInstance<ContractMaint>();
          instance.Clear();
          if (!redirect && !PXAutonumberingInfo.IsDimensionAutonumbered(
(PXGraph)Base, "CONTRACT"))
throw new PXException("Cannot automatically
renew contract when Auto Numbering is off. Please use Renew Contract action on Customer Contracts screen."
); this.RenewExpiring(instance); instance.Save.Press();

Another way to insert some record in db is to use PXDataBase.Insert. Example of usage is the following:

PXDatabase.Insert<APTran>(
                        new PXDataFieldAssign("TranType", PXDbType.NVarChar, apTran.TranType),
                        new PXDataFieldAssign("RefNbr", apTran.RefNbr),
                        new PXDataFieldAssign("ManualPrice", apTran.ManualPrice),
                        new PXDataFieldAssign("LineNbr", apTran.LineNbr));

The first option gives you opportunity to use logic of graph, while second gives you good perfomance.

PXSmartPanel in Acumatica

Hello everybody,

today I want to write few words how to work with PXSmartPanel.

One of my clients asked following:

1. Press at button.

2. Pop up should appear with two buttons ( "OK" , "Cancel")

3. At pop up should be also selector of contracts and datetime.

4. Existing screen should be modified.

In order to do this, following actions were implemented:

1. Existing screen was CT301000.

2. If to look in screen source code, following line says about graph:

<px:PXDataSource ID="ds" runat="server" Visible="True" Width="100%" TypeName="PX.Objects.CT.ContractMaint"
        PrimaryView="Contracts" BorderStyle="NotSet">

3. It means, that we need to create extension class for ContractMaint.

4. For example like this:

public class ContractMaintExt : PXGraphExtension<ContractMaint>
{

        [PXCopyPasteHiddenView]
        public PXFilter<SubstituteSettingsFilter> SubstituteSettings;
        public PXAction<Contract> Substitute;
        [PXButton(CommitChanges = true)]
        [PXUIField(DisplayName = "Substitute")]
        protected void substitute()
        {
            if (this.SubstituteSettings.AskExt(new PX.Data.PXView.InitializePanel(this.fillFilter)) ==
                WebDialogResult.OK)
            {
                var subsFilter = (SubstituteSettingsFilter)this.SubstituteSettings.Cache.Current;
                CopyOpenPMTaskHistory(Base.Contracts.Current.ContractID, subsFilter.ContractID, subsFilter.TransitionDate);
            }
        }
}

5. In the line 4 we declared to Acumatica, that we want to extend ContractMaint, and we want to create some data input, which is related to SubstituteSettingsFilter. Take note of Substitute and substitute: both of them are needed in order to make processing of inputted values.

6. Take a look at SubstituteSettingsFilter class itself:

 [Serializable]
        public class SubstituteSettingsFilter  : IBqlTable
        {
            #region contractID

            public abstract class contractID : IBqlField, IBqlOperand
            {
            }

            protected int? _ContractID;
            [PXDefault]
            [PXDBInt]
            [PXDimensionSelector("CONTRACT", typeof(Search2<Contract.contractID, 
                InnerJoin<ContractBillingSchedule, On<Contract.contractID, Equal<ContractBillingSchedule.contractID>>, 
                LeftJoin<Customer, On<Customer.bAccountID, Equal<Contract.customerID>>>>, 
                Where<Contract.isTemplate, Equal<boolFalse>,
                And<Contract.baseType, Equal<Contract.ContractBaseType>>>>), 
                typeof(Contract.contractCD), 
                new System.Type[] { typeof(Contract.contractCD), typeof(Contract.customerID), typeof(Customer.acctName), 
                    typeof(Contract.locationID), typeof(Contract.description), typeof(Contract.status), typeof(Contract.expireDate), 
                    typeof(ContractBillingSchedule.lastDate), typeof(ContractBillingSchedule.nextDate) },
                    DescriptionField = typeof(Contract.description), Filterable = true)]
            [PXUIField(DisplayName = "Contract ID", Visibility = PXUIVisibility.SelectorVisible)]
            [PXFieldDescription]
            
            public virtual int? ContractID
            {
                get { return this._ContractID; }
                set { this._ContractID = value; }

            }

            #endregion contractID

            #region TransitionDate
            public abstract class transitionDate : PX.Data.IBqlField
            {
            }
            protected DateTime? _TransitionDate;
            [PXDBDate()]
            [PXDefault]
            [PXUIField(DisplayName = "Transition Date")]
            public virtual DateTime? TransitionDate
            {
                get
                {
                    return this._TransitionDate;
                }
                set
                {
                    this._TransitionDate = value;
                }
            }
            #endregion TransitionDate
         }

7. We described two properties: contractID and TransitionDate.

8. Now goes time of aspx page at <px:PXFormView> section I described the following:

<px:PXSmartPanel ID="pnlSubstitute" runat="server" AcceptButtonID="PXButtonOK" AutoReload="true" CancelButtonID="PXButtonCancel"
        Caption="Substitute" CaptionVisible="True" DesignView="Content" HideAfterAction="false" Key="SubstituteSettings"
        LoadOnDemand="true" Height="190px" Width="360px" DefaultControlID="edContract">
        <px:PXFormView ID="PXFormView6" runat="server" CaptionVisible="False" DataMember="SubstituteSettings" Width="100%"
            DefaultControlID="edActivationDate" DataSourceID="ds" TabIndex="1400">
            <ContentStyle BackColor="Transparent" BorderStyle="None">
            </ContentStyle>
            <Template>
                <px:PXLayoutRule runat="server" StartColumn="True" LabelsWidth="SM" ControlSize="M" />
                <px:PXSelector runat="server" ID="edContract" DataField="ContractID" CommitChanges="True" Width="130px" />
                <px:PXDateTimeEdit CommitChanges="True" ID="edTransitionDate" runat="server" DataField="TransitionDate" Width="130px" />
                <px:PXLayoutRule runat="server" StartRow="True" />
                <px:PXPanel ID="PXPanel1" runat="server" SkinID="Buttons">
                    <px:PXButton ID="OK" runat="server" DialogResult="OK" Text="OK" />
                    <px:PXButton ID="Cancel" runat="server" DialogResult="Cancel" Text="Cancel" />
                </px:PXPanel>
            </Template>
        </px:PXFormView>
</px:PXSmartPanel>

Few words. AcceptButtonID speak about who plays role of OK button, Caption means title, CaptionVisible means that title will be visible, HideAfterAction means hide or not after action, Key means name of member in extension or graph, DefaultControlID means which control is active by default. Another important detail is DataMember property, which equals to Key.  Then goes layout rules, which I ommit. Then in Template goes selector, and datetime input. 

9. Here how control look like:

Here it is. If you have any comments, wishes, etc, you are welcome to post them