Skip to main content
Solved

DAC Extension


Forum|alt.badge.img

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,

Best answer by Fernando Amadoz

@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

View original
Did this topic help you find an answer to your question?

17 replies

Forum|alt.badge.img+5
  • Captain II
  • 460 replies
  • August 12, 2022

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?


Forum|alt.badge.img
  • Author
  • Jr Varsity III
  • 21 replies
  • August 12, 2022

Hi,

That’s correct. 

 

Thanks,

 


Forum|alt.badge.img+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.


Forum|alt.badge.img
  • Author
  • Jr Varsity III
  • 21 replies
  • August 12, 2022
Brian Stevens wrote:

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,


Forum|alt.badge.img+4

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


Shawn Burt
Jr Varsity I
Forum|alt.badge.img+1
  • Jr Varsity I
  • 109 replies
  • August 12, 2022

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


Forum|alt.badge.img
  • Author
  • Jr Varsity III
  • 21 replies
  • August 12, 2022

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;
        }

    }


Shawn Burt
Jr Varsity I
Forum|alt.badge.img+1
  • Jr Varsity I
  • 109 replies
  • August 12, 2022

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


Forum|alt.badge.img+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.


Forum|alt.badge.img
  • Author
  • Jr Varsity III
  • 21 replies
  • August 12, 2022
Shawn Burt wrote:

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


Shawn Burt
Jr Varsity I
Forum|alt.badge.img+1
  • Jr Varsity I
  • 109 replies
  • August 12, 2022

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


Forum|alt.badge.img
  • Author
  • Jr Varsity III
  • 21 replies
  • August 12, 2022
Shawn Burt wrote:

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,


Shawn Burt
Jr Varsity I
Forum|alt.badge.img+1
  • Jr Varsity I
  • 109 replies
  • August 12, 2022

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


Fernando Amadoz
Jr Varsity I
Forum|alt.badge.img+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


Forum|alt.badge.img+5
  • Semi-Pro III
  • 293 replies
  • August 14, 2022

@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.


Forum|alt.badge.img
  • Author
  • Jr Varsity III
  • 21 replies
  • August 14, 2022
rosenjon wrote:

@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


Forum|alt.badge.img+5
  • Semi-Pro III
  • 293 replies
  • August 14, 2022

@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


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings