Different types of manufactorings which Acumatica supports

Hi,

today I want to leave a short note of these types of manufactorings:

Make to stock

Make to order

Configure to order

Engineer to order

Job shop

Repetitive

Batch process

1. Make to stock - a manufacturing strategy in which production planning and production scheduling are based on forecasted product demand.

2. Make to order - a business production strategy that typically allows consumers to purchase products that are customized to their specifications. It is a manufacturing process in which the production of an item begins only after a confirmed customer order is received.

3. Configure to order - (CTO) is the manufacturing process of assembling and configuring products according to customer requirements.

4. Engineer to order - (ETO) is a type of manufacturing where a product is engineered and produced after an order has been received. Using the ETO method, a manufacturer can meet the exact specifications of their customer.

5. Job shop - are typically small manufacturing systems that handle job production, that is, custom/bespoke or semi-custom/bespoke manufacturing processes such as small to medium-size customer orders or batch jobs. Job shops typically move on to different jobs (possibly with different customers) when each job is completed. 

6. Repetitive - Repetitive manufacturing (REM) is the production of goods in rapid succession. Goods that are created through repetitive manufacturing follow the same production sequences. Repetitive manufacturing often goes hand-in-hand with automated assembly processes.

7. Batch process - Batch production is a method of manufacturing where the products are made as specified groups or amounts, within a time frame.

How to add button to existing Acumatica screen

Hi,

In order to add button to existing Acumatica screen, you need following:

1. Understand what is main graph. In order to find out, just press on your keyboard Ctrl + Alt + click anywhere on the form. You'll see following picture:

2. Then in C# code, you may write something like this:

public class SOOrderEntryExt : PXGraphExtension<SOOrderEntry>
{
    public static bool IsActive() => true;
 
    public PXAction<SOOrder> TestSomeStaff;
    [PXButton]
    [PXUIField(DisplayName = "Test some staff")]
    protected virtual IEnumerable testSomeStaff(PXAdapter adapter)
    {
        // Some of your logic
 
 
        return adapter.Get();
    }
}

 And here you go, yo'ull have button ready for you. Just don't forget to add your logic

 

 

Acumatica requirements for development

Hi everybody,

today I want to leave a short note regarding of what is needed, in order to be able to develop for Acumatica ERP.

REQUIREMENTS FOR DEV MACHINE

Display resolution: Minimum 1024 × 768, Typical 1920×1080

Adobe Reader: (to open Acumatica ERP PDF documents) 2019 or later

Microsoft Office: (to view documents exported from Acumatica ERP)

  • MS Office 2019
  • MS Office 2016
  • MS Office 2013
  • MS Office 2010
  • MS Office 2007
  • MS Office 2003 with the Microsoft Office 2007 compatibility pack

IIS

Web Browsers:

  • Microsoft Edge 44 or later
  • Mozilla Firefox 82 or later
  • Apple Safari 12 or later
  • Google Chrome 87 or later

As of June 15, 2022, Microsoft Internet Explorer is no longer supported by any version of Acumatica ERP as the browser has been retired by Microsoft who now recommends Microsoft Edge.

DATABASE REQUIREMENTS

Microsoft SQL Server: 2019, 2017, or 2016

MySQL Community Edition Server: 5.7 and 8.0 64-bit edition

MariaDB: Version 10

Memory: 8 GB RAM

CPU: 2 cores; 2 GHz

Hard Disk Space: For each database, 1 GB available hard disk space. Depending on the number of transactions, additional hard disk space may be required to store large numbers of transactions.

CODE AUTHORING ENVIRONMENTS

To create stand-alone applications with Acumatica ERP or develop customizations and add-on solutions on top of Acumatica ERP, you need one of the integrated development environments (IDEs) listed below.

Operating System

  • Windows 10
  • Windows Server 2019
  • Windows Server 2022

Microsoft Visual Studio with Microsoft Web Developer Tools:

  • 20xx: Community, Professional, and Enterprise editions ( xx stands for version numbers, 09, ..., 19, 22 )
  • (OR) Rider 

Summary

If to sum upp, if you want to develop Acumatica, you'll need Windows, IIS, Database and Visual Studio or Rider

How to remove validation of the Lot/Serial Class field on the Stock Items page

Today I want to share with you the article "How to remove the validation of the Lot/Serial Class field on the Stock Items page".

Recently I had a case where I wanted to change Lot/Serial Class at any time regardless of its use, but out of the box, Acumatica doesn't give this possibility and show an error or warning "Lot/serial class cannot be changed when its tracking method as it is not compatible with the previous class and the item is in use" as it is demonstrated in the image below.

There is a possibility of this warning

The red error comes from validation on FieldVerifying, but the yellow comes from the rule in INItemPlan.inventoryID.InventoryLotSerClassIDRule. Although looks like a warning, it reverts your change so it doesn't let you to change it.

The solution of the Lot/serial class can be changed as it is not a complicated process but can be quite time-consuming.

First of all we need to create a GraphExtension where by overriding the Initialize we provide ability to change the Lot/Serial class.

And we also need to override the FieldVerifiyng event and not call the base method so that this field is not validated.

The full code is here:

[PXCacheName(InventoryItemMaintExtCacheName)]
public class InventoryItemMaintExt : PXGraphExtension<InventoryItemMaint>
{
	private const string InventoryItemMaintExtCacheName = "InventoryItemMaintExt";
	public static bool IsActive() => true;
 
	public override void Initialize()
	{
		base.Initialize();
		Base.MakeRuleWeakeningScopeFor<InventoryItem.lotSerClassID>(RuleWeakenLevel.AllowEdit);
	}
 
	protected virtual void _(Events.FieldVerifying<InventoryItem,
	InventoryItem.lotSerClassID> e, PXFieldVerifying baseMethod)
	{
		//baseMethod?.Invoke(sender, e); 
		//skip the baseMethod so Messages.ItemLotSerClassVerifying is not thrown
	}
}

 And final word, use with caution. Because you may influence plenty of other pages in Acumatica.

 

 

 

How to customize PXDefault attribute of Acumatica

Sometimes you can get request from BA or client to add new field like this: “On the Customers (AR.30.30.00) screen add a checkbox field called Membership. It is a required field and the default value is False. The Membership field should be already there.”

How we usually develop it:

public class PACustomerExt : PXCacheExtension<Customer>
{
	public static bool IsActive() => true;
 
	#region UsrMembership
	[PXDBBool]
	[PXUIField(DisplayName = "Membership", Required = true)]
	[PXDefault(false)]
	public virtual bool? UsrMembership { getset; }
	public abstract class usrMembership : PX.Data.BQL.BqlBool.Field<usrMembership> { }
	#endregion
}

 

And as you know, this logic will work correct for new records in DB, but when you will change existing records in DB, than you will get nullable Exception because of this custom field and PXDefault attribute. “PersistingCheck = PXPersistingCkeck.Nothing” do not help, it excludes the required status of the custom field.

So we can fix this issue and develop custom Default attribute, and we do not need create graph extension and develop additional logic in events.

Here is example of correct logic according the request:

public class PACustomerExt : PXCacheExtension<Customer>
{
	public static bool IsActive() => true;
 
	#region UsrMembership
	[PXDBBool]
	[PXUIField(DisplayName = "Membership", Required = true)]
	[PXDefaultCustom(false)]
	public virtual bool? UsrMembership { getset; }
	public abstract class usrMembership : PX.Data.BQL.BqlBool.Field<usrMembership> { }
	#endregion
}
 
 
[PXAttributeFamily(typeof(PXDefaultAttribute))]
public class PXDefaultCustomAttribute : PXDefaultAttribute
{
	public PXDefaultCustomAttribute(object value) : base(value) { }
 
 
	public override void RowPersisting(PXCache sender, PXRowPersistingEventArgs e)
	{
		var fieldValue = sender.GetValue(e.Row, base.FieldName);
 
		if (fieldValue == null)
			sender.SetValue(e.Row, base.FieldName, false);
	}
}

 

Also you can customize PXDefault attribute with any logic that you need, one more example:

[PXAttributeFamily(typeof(PXDefaultAttribute))]
public class PXDefaultCustomAttribute : PXDefaultAttribute
{
	public PXDefaultCustomAttribute(object value) : base(value) { }
 
	public override void FieldDefaulting(PXCache sender, PXFieldDefaultingEventArgs e)
	{
		base.FieldDefaulting(sender, e); // you can raise base event and logic 
 
		e.NewValue = base._Constant;  // you can setup or check constant value of default attribute
 
		// develop needed logic
	}
 
	public override void RowPersisting(PXCache sender, PXRowPersistingEventArgs e)
	{
		// develop needed logic before value will be persisted to DB
 
		var fieldValue = sender.GetValue(e.Row, base.FieldName);
 
		if (fieldValue == null)
			sender.SetValue(e.Row, base.FieldName, false);
 
		// base.RowPersisting(sender, e);  - you can raise base event if you need, also you can set up PXPersistingCheck on you custom attribute
	}
}

 

How to use LoadOnDemand in PXSmartPanel

First of all I want to say that if you do not use "PXTabItem" in your "PXSmartPanel" you should not set LoadOnDemand(by default this attribute has "False" value).

In our example I will show you the difference between using this attribute for "PXSmartPanel" with "True" or "False" values. For that I prepared a short example:

We will use two TabItems (Stock Items for the first and Non-Stock Items for the second).

Let's create them in GraphExt.

public SelectFrom<InventoryItem>.Where<InventoryItem.stkItem.IsEqual<True>>.View StockItemView;
public SelectFrom<InventoryItem>.Where<InventoryItem.stkItem.IsEqual<False>>.View NonStockItemView;

 Let's add button to GraphExt and to the View. For this example we will use the Sales Orders page and add PXSmartPanel to the View.

public sealed class SoOrderEntryExt : PXGraphExtension<SOOrderEntry>
{
    public static bool IsActive() => true;
 
    public PXSelect<SOLine> MyPanelView;
 
    public PXAction<SOOrder> noteAction;
    [PXUIField(DisplayName = "TestNoteButton", MapViewRights = PXCacheRights.Select, MapEnableRights = PXCacheRights.Update)]
    [PXButton(ImageKey = PX.Web.UI.Sprite.Main.DataEntryF)]
    protected IEnumerable NoteAction(PXAdapter adapter)
    {
        if (Base.Transactions.Current != null &&
            MyPanelView.AskExt() == WebDialogResult.OK)
        {
            //extra stuff here if needed when OK is pushed
        }
 
        return adapter.Get();
    }
 
    public SelectFrom<InventoryItem>.Where<InventoryItem.stkItem.IsEqual<True>>.View StockItemView;
    public SelectFrom<InventoryItem>.Where<InventoryItem.stkItem.IsEqual<False>>.View NonStockItemView;
}

 

ASPX. PXSmartPanel:

<px:PXSmartPanel runat="server" ID="PXSmartPanelNote" DesignView="Hidden" LoadOnDemand="false" CreateOnDemand="false" 
                     CaptionVisible="true" Caption="Order Notes" Key="MyPanelView">
        <px:PXTab ID="PXTab123" runat="server" Height="540px" Style="z-index100;" Width="100%">
            <Items>
                <px:PXTabItem Text="NonStockItem" >
                    <Template>
                        <px:PXGrid runat="server" ID="CstPXGrid4" Width="100%" DataSourceID="ds" SyncPosition="True">
                            <Levels>
                                <px:PXGridLevel DataMember="NonStockItemView">
                                    <Columns>
                                        <px:PXGridColumn DataField="StkItem" Width="60" />
                                        <px:PXGridColumn DataField="InventoryCD" Width="70" />
                                    </Columns>
                                </px:PXGridLevel>
                            </Levels>
                        </px:PXGrid>
                    </Template>
                </px:PXTabItem>
                <px:PXTabItem Text="StockItem">
                    <Template>
                        <px:PXGrid runat="server" ID="CstPXGrid5" Width="100%" SyncPosition="True" DataSourceID="ds">
                            <Levels>
                                <px:PXGridLevel DataMember="StockItemView">
                                    <Columns>
                                        <px:PXGridColumn DataField="StkItem" Width="60" />
                                        <px:PXGridColumn DataField="InventoryCD" Width="70" />
                                    </Columns>
                                </px:PXGridLevel>
                            </Levels>
                        </px:PXGrid>
                    </Template>
                </px:PXTabItem>
            </Items>
        </px:PXTab>
        <px:PXPanel runat="server" ID="PXPanel12" SkinID="Buttons">
            <px:PXButton runat="server" ID="btnMyNoteOk" Text="OK" DialogResult="OK" />
        </px:PXPanel>
    </px:PXSmartPanel>

 ASPX.  Callback:

<CallbackCommands>
    <px:PXDSCallbackCommand CommitChanges="true" Name="NoteAction" Visible="False" DependOnGrid="grid" />
</CallbackCommands> 

ASPX. Action Bar:

<px:PXToolBarButton Text="TestNoteButton" DependOnGrid="grid">
    <AutoCallBack Command="NoteAction" Target="ds" />
</px:PXToolBarButton>

 

 

 

 

 

How to publish customization with custom dll

Hi everybody,

today I want to share with you how to publish Acumatica customization with dll, which gives you errors during publish. For example, recently I've added Accord net library, and during publish got following errors:

Accord.Math.dll Failed to resolve method reference: System.Numerics.Complex& System.Numerics.Complex[0...,0...]::Address(System.Int32,System.Int32) declared in System.Numerics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Accord.Math.dll Failed to resolve method reference: System.Void System.Numerics.Complex[0...,0...]::Set(System.Int32,System.Int32,System.Numerics.Complex) declared in System.Numerics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Accord.Math.dll Failed to resolve method reference: System.Numerics.Complex System.Numerics.Complex[0...,0...]::Get(System.Int32,System.Int32) declared in System.Numerics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

Steps to deal with that are following:

1. Copy into clipboard error messages.

2. Create file cstValidationIgnore.txt

3. Paste content in the step 1 into file cstValidationIgnore.txt in the folder App_Data

4. Include that file into customization:

 

5. Publish.

 

After these steps I was able to get needed features of Accord.Net into Acumatica.

 

LSSelect view in Acumatica

Hi all. Today I want to told you about how to override Split Lines on Acumatica screens:

This pop-up used on different screens like SO302000 or S0301000…

Overriding the view in 21 R1 and older versions look like this:

Imagine situation that you want to control this functionality or make automatic allocation on some action. The problem I encountered was that I could not fully override lsselect.

 More precisely, I overloaded but I could not disable the execution of basic logic.

For a sample my task was to make an automatic allocation when user click on save the order and control qty’s on the grid.

After several overloads, I could not control this grid. So I decided to adjust to the basic logic.

Here is a piece of code that I use:

private void SetupAllocation(SOOrderEntry sooRderEntry, SOLine line)
{
 
    SOOrderExt currSoOrderExt = sooRderEntry.Document.Current
        .GetExtension<SOOrderExt>();
    Base.Transactions.Current = line;
 
    foreach (SOLineSplit split in Base.splits.Select())
    {
        // some conditions
        if (split.Completed == false && split.IsAllocated == false)
        {
            SOLineSplit oldLine = PXCache<SOLineSplit>.CreateCopy(split);
 
            decimaldiffQty = 0m;
 
            Base.splits.Cache.RaiseRowUpdated(split, oldLine);
            //qty that we want to allocate
            split.Qty = Base.Transactions.Current.OpenQty;
            split.IsAllocated = true;
            Base.splits.Cache.RaiseRowUpdated(split, oldLine);
            Base.splits.Update(split);
 
 
            // diffQty = //here you can set your value 
 
            Base.splits.Cache.RaiseRowUpdated(split, oldLine);
 
            split.Qty = //first value
                split.IsAllocated = true;
 
            Base.splits.Update(split);
            //if you want to insert new row into the grid     
            if (diffQty > 0)
            {
                SOLineSplit newsplit = new SOLineSplit();
 
                newsplit.LineNbr = split.LineNbr;
                newsplit.Qty = diffQty;
                newsplit.IsAllocated = false;
                Base.splits.Insert(newsplit);
            }
        }
    }
}

 I did something like that. And now I can control automatic or manual allocation also I can control how much qty allocate.

But in the 21R2 version Acumatica changed the code and now for overriding you should do like this:

And I am sure that now will be easier to override and control this panel. In the near future I will do more tests and share the result.

 

 

ABC-XYZ analysis for laymen

Hello everybody,

In this post, I’m going to explain ABC-XYZ analysis and why your company should bother about it. Also, I hope after reading this blog post you’ll understand why big companies, at least at some stage, use ABC-XYZ analysis.

So, first of all, ABC-XYZ analysis is a tool that allows you to classify your products into two main groups:

  1. ABC
  2. XYZ

ABC metrics tell you about the volume of sales. Where A – best sellers, B in between sellers, C – worst sellers

XYZ metrics tell you about the regularity of sales. Where X – stands for regular sellers, Y stands for more or less regular sellers, and Z are irregular sellers.

After I’ve read this explanation, I still was puzzled; and for me, it still wasn’t clear what ABC-XYZ is all about. But please bear with me for few more minutes, and I’ll explain ABC-XYZ via example, and hopefully, everything will be clear.

Imagine that you are an owner of a bakery. And your bakery produces three kinds of products:

  1. Bread

2. Biscuit

3. Wedding cake

And now the question is: what product will be sold in the highest quantities and regularities?

Most probably, you’ll agree that bread will be the winner in the category of quantity and regularity.

What product will be number two by regularity? Definitely a biscuit. And what will be the number three in quantity and regularity? Wedding cake.

If to look from the perspective of ABC-XYZ, the break will belong to A category by quantity and X category by regularity. Biscuit will belong to B category by quantity and Y category by regularity. And wedding cake will belong to C category by quantity and Z category by regularity.

So far, so good?

But imagine that your company sells not bread, but, for example, GPS trackers, toys, furniture, or something else. How can you figure out what bread of your company is? And what about biscuit and wedding cake? What if you have not three products, but let’s say 100. Which of these products belong to A, B, C. And which belong to X, Y, Z? How could you track/notice cases when bread from A becomes C. Or when wedding cake from Z moves to X by regularity? All of this may be accomplished with the help of our ABC-XYZ analysis and advanced ABC-XYZ profit margin analysis.

 

ConsentDate has been expirated in Acumatica

Today I will tell you how to fix the import error for CROpportunity "No consent date has been specified".

In order to import CROpportunity you need to create DataProvider and ImportScenario

Data Provider (SM206015)

Import Scenario (SM206025)

Now you have to go to the Import by Scenario (SM206036) screen and do the Import data.

After the successful import, you can see that a new Opportunity was created, but the Contact and Owner fields were not filled in.

This can easily be corrected by making changes to the Import scenario for

  • «Contact» - «ContactID!DisplayName»
  • «Owner» - «OwnerID!DisplayName»

Let's repeat the import on the page Import by Scenario (SM206036)

Import result as an example of one of the records

Good luck with your imports!

 

Good luck with your imports.