Solved

DAC Extension


Userlevel 2
Badge

Hi,

I created a dac extension in the POLine, I add the field the grid and when save the document , the records is inserted in the db. Bu when retrieve the PO the new field is empty. 

 

How I can populate the new field?

 

Thanks,

icon

Best answer by Fernando Amadoz 13 August 2022, 10:34

View original

17 replies

Userlevel 7
Badge +5

Just to confirm - you see the new field on the screen and you’re able to enter a value it in.  You save the PO and see that the value is in the database.  But when you load the PO on the screen again, you cannot see the value in the field.  Is that correct?

Userlevel 2
Badge

Hi,

That’s correct. 

 

Thanks,

 

Userlevel 6
Badge +4

If the field is on the screen and you can enter, but it does not save… check that you defined it as a PXDB… type rather than a PX… type.  Here’s an example of one of mine on POOrder.

namespace PX.Objects.PO
{
    public sealed class POOrderExt : PXCacheExtension<PX.Objects.PO.POOrder>
    {
        public static bool IsActive() =>
            SSCSAccess.FeatureInstalled<SSCSFeaturesSet.main>();
        
        #region UsrSSMyField
        //[PXDBBool()]
        [PXBool()]
        [PXDefault(false, PersistingCheck = PXPersistingCheck.Nothing)]
        public bool? UsrSSMyField{ get; set; }
        public abstract class usrSSMyField: PX.Data.BQL.BqlBool.Field<usrSSMyField> { }
        #endregion
    }
}

 

Notice the commented out PXDBBool attribute.  The uncommented attribute is just PXBool.  PXDBBool tells Acumatica to interact with the database, while the PXBool attribute tells Acumatica that this is an unbound field, and therefore, not saved to the database.

Also, when using PXDB… attributes, be sure the field has been added to the database as well, or it will give database errors to the browser.

Userlevel 2
Badge

If the field is on the screen and you can enter, but it does not save… check that you defined it as a PXDB… type rather than a PX… type.  Here’s an example of one of mine on POOrder.

namespace PX.Objects.PO
{
    public sealed class POOrderExt : PXCacheExtension<PX.Objects.PO.POOrder>
    {
        public static bool IsActive() =>
            SSCSAccess.FeatureInstalled<SSCSFeaturesSet.main>();
        
        #region UsrSSMyField
        //[PXDBBool()]
        [PXBool()]
        [PXDefault(false, PersistingCheck = PXPersistingCheck.Nothing)]
        public bool? UsrSSMyField{ get; set; }
        public abstract class usrSSMyField: PX.Data.BQL.BqlBool.Field<usrSSMyField> { }
        #endregion
    }
}

 

Notice the commented out PXDBBool attribute.  The uncommented attribute is just PXBool.  PXDBBool tells Acumatica to interact with the database, while the PXBool attribute tells Acumatica that this is an unbound field, and therefore, not saved to the database.

 

Hi, The record is in the db. Right now I'm having problems displaying the value and in the updating.

 

Thanks,

Userlevel 6
Badge +4

Your custom field that you added is in the record and has a value?

Userlevel 5
Badge +1

Steven is correct, your issue is in the DAC Definition

you need:
[PXDBBool()]

Not:

[PXBool()]

 

 

 

 

[PXBool()] is for unbound DAC Extensions and is not persisted into the DB

Userlevel 2
Badge

Hi,

This is the PO.

This is my Dac Extension table. 

 

This is my dac extension class. The field that I want to display is QtyCases.

[Serializable]
    [PXCacheName("PoCatchWeight")]
    [PXTable(typeof(POLine.orderNbr), typeof(POLine.orderType), typeof(POLine.lineNbr), IsOptional = true)]
    public class PoCatchWeight : PXCacheExtension<POLine>
    {
        public static bool IsActive()
        {
            return true;
        }
        #region QtyCases
        [PXDBDecimal()]
        [PXUIField(DisplayName = "Qty Cases")]
        public virtual Decimal? QtyCases { get; set; }
        public abstract class qtyCases : PX.Data.BQL.BqlDecimal.Field<qtyCases> { }
        #endregion

        #region QtyLbs
        [PXDBDecimal()]
        [PXUIField(DisplayName = "Qty Lbs")]
        public virtual Decimal? QtyLbs { get; set; }
        public abstract class qtyLbs : PX.Data.BQL.BqlDecimal.Field<qtyLbs> { }
        #endregion

        [PXNote(PopupTextEnabled = true)]
        public virtual Guid? NoteID { get; set; }
        public abstract class noteID : BqlType<IBqlGuid, Guid>.Field<noteID> { }

        public abstract class orderType : BqlType<IBqlString, string>.Field<orderType>
        {
        }

        public abstract class orderNbr : BqlType<IBqlString, string>.Field<orderNbr>
        {
        }

        public abstract class lineNbr : BqlType<IBqlInt, int>.Field<lineNbr>
        {
        }

        [PXDBString(2, IsKey = true, IsFixed = true)]
        [PXDBDefault(typeof(POOrder.orderType))]
        [PXUIField(DisplayName = "Order Type", Visibility = PXUIVisibility.Visible, Visible = false)]
        public virtual string OrderType
        {
            get; set;
        }

        [PXDBString(15, IsUnicode = true, IsKey = true, InputMask = "")]
        [PXDBDefault(typeof(POOrder.orderNbr))]
        [PXUIField(DisplayName = "Order Nbr.", Visibility = PXUIVisibility.Invisible, Visible = false)]
        public virtual string OrderNbr
        {
            get; set;
        }

        [PXDBInt(IsKey = true)]
        [PXUIField(DisplayName = "Line Nbr.", Visibility = PXUIVisibility.Visible, Visible = false)]
        [PXLineNbr(typeof(POOrder.lineCntr))]
        public virtual int? LineNbr
        {
            get; set;
        }

    }

Userlevel 5
Badge +1

shoud look more like this:

[Serializable]
public sealed class PoCatchWeight : PXCacheExtension<POLine>
{
public static bool IsActive()
{
return true;
}
#region UsrQtyCases
[PXDBDecimal()]
[PXUIField(DisplayName = "Qty Cases")]
public Decimal? UsrQtyCases { get; set; }
public abstract class usrQtyCases : PX.Data.BQL.BqlDecimal.Field<usrQtyCases> { }
#endregion

#region UsrQtyLbs
[PXDBDecimal()]
[PXUIField(DisplayName = "Qty Lbs")]
public Decimal? UsrQtyLbs { get; set; }
public abstract class usrQtyLbs : PX.Data.BQL.BqlDecimal.Field<usrQtyLbs> { }
#endregion

cachename and pxtable are for DAC’s not DACExtensions unless you doing something like PXProjection.

Also you don’t need to link in the keys as they will be automatically there.

lastly if you don’t prefix your custom fields with Usr they will be purged durin upgrades, e.g. 22R1 to 22R2

 

hope this helps

Userlevel 6
Badge +4

As a Cache Extension, your fields should start with UsrXX where XX is a prefix you use on all your custom code to keep from stepping on Acumatica changes with upgrades.  Typically, extending a DAC involves a naming convention like POLineExt to extend POLine.  This helps with readability for developers who come behind you.  In how you have used this, I am unfamiliar with…

[PXTable(typeof(POLine.orderNbr), typeof(POLine.orderType), typeof(POLine.lineNbr), IsOptional = true)]

 

So try commenting it out to see if that is interfering.  The comments on the attribute indicate that it is used to relate a DAC extension that is stored in a different table to the table you are extending, so it is unnecessary here and probably the source of your trouble.

Userlevel 2
Badge

shoud look more like this:

[Serializable]
public sealed class PoCatchWeight : PXCacheExtension<POLine>
{
public static bool IsActive()
{
return true;
}
#region UsrQtyCases
[PXDBDecimal()]
[PXUIField(DisplayName = "Qty Cases")]
public Decimal? UsrQtyCases { get; set; }
public abstract class usrQtyCases : PX.Data.BQL.BqlDecimal.Field<usrQtyCases> { }
#endregion

#region UsrQtyLbs
[PXDBDecimal()]
[PXUIField(DisplayName = "Qty Lbs")]
public Decimal? UsrQtyLbs { get; set; }
public abstract class usrQtyLbs : PX.Data.BQL.BqlDecimal.Field<usrQtyLbs> { }
#endregion

cachename and pxtable are for DAC’s not DACExtensions unless you doing something like PXProjection.

Also you don’t need to link in the keys as they will be automatically there.

lastly if you don’t prefix your custom fields with Usr they will be purged durin upgrades, e.g. 22R1 to 22R2

 

hope this helps

Hi,

“lastly if you don’t prefix your custom fields with Usr they will be purged durin upgrades, e.g. 22R1 to 22R2”

But this is a custom table. I’m not adding fields to Acumatica default tables. 

Thanks,

EV

Userlevel 5
Badge +1

that is not how you have it coded, you have this setup as a DAC Extension, which adds fields to POLine.

If you are doing a custom table, then you need to add a View to the Graph to use your table and you need to move your fields to their own form on the screeen

Userlevel 2
Badge

that is not how you have it coded, you have this setup as a DAC Extension, which adds fields to POLine.

If you are doing a custom table, then you need to add a View to the Graph to use your table and you need to move your fields to their own form on the screeen

Hi,

Can you please give me an example? I’m using this link to create it, https://www.acumatica.com/blog/creating-acumatica-dac-extension-tables/

 

Thanks,

Userlevel 5
Badge +1

I can’t say I have used this methodology, with any luck Patrick Chen will notice this thread and give some advice, sorry

Userlevel 5
Badge +2

@edsonvelez64

You are managing the extended DAC as a separate table instead of adding the fields to Acumatica’s POLine table.

This is a valid approach. And it is correct in these cases the use of the attribute [PXTable] in order to indicate Acumatica that it’s a “Joined” table.

However, you seem to be adding additional attributes that are not needed for a CacheExtension (e.g. [PXCacheName]) and you are redefining native fields that should not be added to the DAC extension (e.g. NoteID, OrderType, OrderNbr, etc)

 

Try a simplified approach adding only the extra fields: QtyCases and QtyLbs.
You are correct in adding CompanyID and the primary key in the DB table definition, but it is not needed in the DAC extension definition.

 

Please see this reference from a project we worked on a couple of years ago (you may have to add the IsActive() method)

using PX.Data;
using PX.Objects.AR;
using PX.Objects.CR;

namespace ProjectNameSpace
{
[PXTable(typeof(BAccountR.bAccountID), IsOptional = true)] //IsOptional ==> it's managed as a Left Join
public class CustomerExt : PXCacheExtension<Customer>
{
#region LCID
public abstract class lCID : PX.Data.IBqlField
{
}
[PXDBInt()]
[PXUIField(DisplayName = "Field Name")]
public virtual int? LCID { get; set; }
#endregion
}
}

Notice that the DAC extension only adds the LCID field.
However, my DB table also included CompanyID, BAccountID (primary key), and *DeletedDatabaseRecord

*Only needed if defined in the original table. POLine does not have it

Userlevel 6
Badge +5

@edsonvelez64 You will have to explain why you would want to have an entirely separate table when you are adding a field to an existing table that is already setup for display/user interaction in the system. A separate table will require a join to this POLine table, which under the hood is already joined to other tables (PO, POAllocation, etc). This makes your customization more complex than it needs to be, which will make it slower and more brittle if this field needs to be used in other places as well.

The correct, performant and simpler way to do this is to simply add the column to the existing table. While some ERP systems will not let you add to core tables, Acumatica encourages it and this is the default behavior when you create a usr field in code against an existing DAC (basically an abstraction of a table).

If you follow what @Shawn Burt is telling you, this will get you what you want. That field will then be available for addition to the POLine UI in the front end as well.

Userlevel 2
Badge

@edsonvelez64 You will have to explain why you would want to have an entirely separate table when you are adding a field to an existing table that is already setup for display/user interaction in the system. A separate table will require a join to this POLine table, which under the hood is already joined to other tables (PO, POAllocation, etc). This makes your customization more complex than it needs to be, which will make it slower and more brittle if this field needs to be used in other places as well.

The correct, performant and simpler way to do this is to simply add the column to the existing table. While some ERP systems will not let you add to core tables, Acumatica encourages it and this is the default behavior when you create a usr field in code against an existing DAC (basically an abstraction of a table).

If you follow what @Shawn Burt is telling you, this will get you what you want. That field will then be available for addition to the POLine UI in the front end as well.

Hi,

That’s works when I have a 1-1 relationship , but if I have a 1 - many relationship, what is the correct way to handle it?

 

Thanks,

EV

Userlevel 6
Badge +5

@edsonvelez64 Maybe you should describe what you’re trying to achieve first? It looks like you’re trying to add different UOMs to the POLine. In some cases this might not require storage in the database at all, as this info is derivative of the UOM feature.

However, it would help to have a description of your desired outcome first.

Reply


About Acumatica ERP system
Acumatica Cloud ERP provides the best business management solution for transforming your company to thrive in the new digital economy. Built on a future-proof platform with open architecture for rapid integrations, scalability, and ease of use, Acumatica delivers unparalleled value to small and midmarket organizations. Connected Business. Delivered.
© 2008 — 2024  Acumatica, Inc. All rights reserved