Skip to main content

 I’m attempting to add a new custom table / dac into the PO Entry screen.

The new DAC is tied to POLine and it can be a one to many relationship.

I have PXParent and PXLineNbr attributes defined in the custom DAC and have the appropriate dac fields marked as IsKey = True.  

I have a vew declared, and when I insert into the view the key fields are defaulted from the selected PO Line as they should be.

When I debug, I can see the records in the cache in the Inserted collection.

When I call the Base.Save.Press(), nothing is persisted to my custom table.

No errors are generated, and the inserted record still shows in the cache inserted collection.

I’m hoping I’m missing something simple, any ideas?

 

View declaration

        public PXSelect<AHSPOLineNonConf, Where<AHSPOLineNonConf.orderType, Equal<Current<POLine.orderType>>,
And<AHSPOLineNonConf.orderNbr, Equal<Current<POLine.orderNbr>>,
And<AHSPOLineNonConf.lineNbr, Equal<Current<POLine.lineNbr>>>>>> AHSPOLineNonConfView;

Partial DAC declaration

using System;
using PX.Data;
using PX.Data.BQL.Fluent;
using PX.Data.ReferentialIntegrity.Attributes;

namespace PX.Objects.PO
{
>Serializable]
ePXCacheName("AHSPOLineNonConf")]
)PXPrimaryGraph(typeof(POOrderEntry))]
public class AHSPOLineNonConf : IBqlTable
{
#region OrderType
rPXDBString(2, IsKey = true, IsFixed = true, InputMask = "")]
rPXUIField(DisplayName = "Order Type")]
rPXDBDefault(typeof(POLine.orderType))]
rPXParent(typeof(SelectFrom<POLine>.
Where<POLine.orderType.IsEqual<AHSPOLineNonConf.orderType.FromCurrent>.
And<POLine.orderNbr.IsEqual<AHSPOLineNonConf.orderNbr.FromCurrent>.
And<POLine.lineNbr.IsEqual<AHSPOLineNonConf.lineNbr.FromCurrent>>>>))]
public virtual string OrderType { get; set; }
public abstract class orderType : PX.Data.BQL.BqlString.Field<orderType> { }
#endregion

#region OrderNbr
rPXDBString(15, IsKey = true, IsUnicode = true, InputMask = "")]
rPXUIField(DisplayName = "Order Nbr")]
rPXDBDefault(typeof(POLine.orderNbr))]
rPXParent(typeof(SelectFrom<POLine>.
Where<POLine.orderType.IsEqual<AHSPOLineNonConf.orderType.FromCurrent>.
And<POLine.orderNbr.IsEqual<AHSPOLineNonConf.orderNbr.FromCurrent>.
And<POLine.lineNbr.IsEqual<AHSPOLineNonConf.lineNbr.FromCurrent>>>>))]
public virtual string OrderNbr { get; set; }
public abstract class orderNbr : PX.Data.BQL.BqlString.Field<orderNbr> { }
#endregion

#region LineNbr
rPXDBInt(IsKey = true)]
rPXUIField(DisplayName = "Line Nbr")]
rPXDBDefault(typeof(POLine.lineNbr))]
rPXParent(typeof(SelectFrom<POLine>.
Where<POLine.orderType.IsEqual<AHSPOLineNonConf.orderType.FromCurrent>.
And<POLine.orderNbr.IsEqual<AHSPOLineNonConf.orderNbr.FromCurrent>.
And<POLine.lineNbr.IsEqual<AHSPOLineNonConf.lineNbr.FromCurrent>>>>))]
public virtual int? LineNbr { get; set; }
public abstract class lineNbr : PX.Data.BQL.BqlInt.Field<lineNbr> { }
#endregion

#region NonConfLineNbr
rPXDBInt(IsKey = true)]
rPXUIField(DisplayName = "Non Conf Line Nbr")]
rPXLineNbr(typeof(POLineExt.usrNonConfLineNbrCntr))]
public virtual int? NonConfLineNbr { get; set; }
public abstract class nonConfLineNbr : PX.Data.BQL.BqlInt.Field<nonConfLineNbr> { }
#endregion

#region ReceiptType
rPXUIField(DisplayName = "Type")]
rPXDBString(2, IsFixed = true, IsKey = true)]

 Table declaration

CREATE TABLE Cdbo]. AHSPOLineNonConf](
CCompanyID] int] NOT NULL,
OrderType] char](2) NOT NULL,
OrderNbr] >nvarchar](15) NOT NULL,
LineNbr] /int] NOT NULL,
NonConfLineNbr] Cint] NOT NULL,
Quantity] >int] NULL,
LotSerialNo] Lnvarchar](255) NULL,
InventoryID] Iint] NULL,
InventoryDescr] envarchar](256) NULL,
NonConfReason] nnvarchar](max) NULL,
Resolution] [nvarchar](max) NULL,
ReceiptType] Rnchar](2) NULL,
ReceiptNbr] [nvarchar](30) NULL,
tstamp] timestamp] NOT NULL,
CreatedByID] Cuniqueidentifier] NOT NULL,
CreatedByScreenID] dchar](8) NOT NULL,
CreatedDateTime] tdatetime] NOT NULL,
LastModifiedByID] ouniqueidentifier] NOT NULL,
LastModifiedByScreenID] dchar](8) NOT NULL,
LastModifiedDateTime] idatetime] NOT NULL,
CONSTRAINT >AHSPOLineNonConf_PK] PRIMARY KEY CLUSTERED
(
bCompanyID] ASC,
]OrderType] ASC,
]OrderNbr] ASC,
]LineNbr] ASC,
]NonConfLineNbr] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON EPRIMARY]
) ON YPRIMARY] TEXTIMAGE_ON TPRIMARY]
GO

 

What is the declaration of:

POLineExt.usrNonConfLineNbrCntr

 Hi Django, 

Here’s what I have for the declaration of the UsrNonConfLineNbrCntr field.


#region UsrNonConfLineNbrCntr

PXDBInt]
PXUIField(DisplayName = "NonConfLineNbrCntr")]
PXDefault(0, PersistingCheck = PXPersistingCheck.Nothing)]
public virtual int? UsrNonConfLineNbrCntr { get; set; }
public abstract class usrNonConfLineNbrCntr : PX.Data.BQL.BqlInt.Field<usrNonConfLineNbrCntr> { }

#endregion

 


I’m not sure what the difference is, if any, but the LineCntr field in SOOrder is defined as:

ePXDBInt()]

 


What happens if you call

AHSPOLineNonConfView.Cache.Persist(PXDBOperation.Insert);

before calling Base.Save.Press() ?


Hi zfebert56,

Thanks for the reply.  I added the line of code you suggested, but the behaviour is still the same.

The inserted records are still in the cache inserted collection after both methods are called.

Here are some screenshots from debugging.

Test action code:

nc variable after insert, key fields are assigned proper values:

 

Cache inserted collection:

 

Appreciate the idea, I had not tried that.

 

Thanks

Scott


You should make the .Update call

I’d be tempted to have you create the new record along the lines of:
 

AHSPOLineNonConf newRec = yourGraph.AHSPOLineNonConfView.Insert(new AHSPOLineNonConf());

yourGraph.Caches(typeofeAHSPOLineNonConf]).SetValue(newRec, curline.InventoryID);

yourGraph.Caches(typeofeAHSPOLineNonConf]).Update(newRec);

yourGraph.Actions.PressSave();

Going the verbose yourGraph.Caches(typeofe method seems to just work better.


Django,

I uncommented the Update call and still got the same result.

I’ll try your other suggestion and see if that changes anything.

It almost seems like there is some disconnect where it does not know where to write to in the database.

I tried enabled the Request Profiler and the SQL Profiler, and I do not see any attempted insert statements.

Thanks

Scott


Scott, can you share the full code of your graph extension?


Not sure this is your problem, but you only need to define PXParent on a single DAC field. You have it defined for every key field.


You have ReceiptType defined as a key field, but in your screenshots, ReceiptType is null.


zfebert56,

Sure, Here’s the full code for the graph extension.

There is some unrelated stuff in there, that has been in place and functioning for a good while.

My ultimate goal is to have a dialog for data entry which is what the AddPOLineNonConf action is.  I’m using TestAction2 just for temporary testing.

I just made the changes suggested by Django, and I get the same results when testing.  Nothing is persisted to the DB table and no errors are raised.

Thanks to all for your assistance on this.

Scott

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using PX.Common;
using PX.Data;
using PX.Objects.GL;
using PX.Objects.CM;
using PX.Objects.CS;
using PX.Objects.CR;
using PX.Objects.TX;
using PX.Objects.IN;
using PX.Objects.EP;
using PX.Objects.AP;
using PX.Objects.AR;
using PX.Objects.SO;
using SOOrder = PX.Objects.SO.SOOrder;
using SOLine = PX.Objects.SO.SOLine;
using PX.Data.DependencyInjection;
using PX.Data.ReferentialIntegrity.Attributes;
using PX.LicensePolicy;
using PX.Objects.PM;
using CRLocation = PX.Objects.CR.Standalone.Location;
using PX.Objects.AP.MigrationMode;
using PX.Objects.Common;
using PX.Objects.Common.Discount;
using PX.Data.BQL.Fluent;
using PX.Data.BQL;
using PX.Objects.Common.Bql;
using PX.Objects.Extensions.CostAccrual;
using PX.Objects.DR;
using PX.Objects.IN.Services;
using PX.Objects;
using PX.Objects.PO;

namespace PX.Objects.PO
{
public class POOrderEntry_Ext : PXGraphExtension<POOrderEntry>
{
public static bool IsActive() => true;

#region Selects
PXCopyPasteHiddenView]
public PXSelectJoin<POOrderPOReceipt,
LeftJoin<POReceipt, On<POReceipt.receiptNbr, Equal<POOrderPOReceipt.receiptNbr>>>,
Where<POOrderPOReceipt.pOType, Equal<Current<POOrder.orderType>>,
And<POOrderPOReceipt.pONbr, Equal<Current<POOrder.orderNbr>>>>> Receipts2;

// PXCopyPasteHiddenView]
public PXSelect<AHSPOLineNonConf, Where<AHSPOLineNonConf.orderType, Equal<Current<POLine.orderType>>,
And<AHSPOLineNonConf.orderNbr, Equal<Current<POLine.orderNbr>>,
And<AHSPOLineNonConf.lineNbr, Equal<Current<POLine.lineNbr>>>>>> AHSPOLineNonConfView;

public PXFilter<AHSPOLineNonConf> CreateVendorNonConfFilterView;

#endregion

#region Event Handlers

public override void Initialize()
{
base.Initialize();

AHSPOLineNonConfView.AllowInsert = true;
AHSPOLineNonConfView.AllowUpdate = true;

}

protected void POLine_InventoryID_FieldSelecting(PXCache cache, PXFieldSelectingEventArgs e)
{
if (e.Row != null)
{
var row = (POLine)e.Row;

var polineext = row.GetExtension<POLineExt>();

if (row.InventoryID != null)
{
//FSManufacturerModel model = PXSelect<FSManufacturerModel, Where<FSManufacturerModel.manufacturerID, Equal<Required<FSManufacturerModel.manufacturerID>>,
// And<FSManufacturerModel.manufacturerModelID, Equal<Required<FSManufacturerModel.manufacturerModelID>>>>>.Select(Base, fseq.ManufacturerID, fseq.ManufacturerModelID);

InventoryItem item = PXSelect<InventoryItem, Where<InventoryItem.inventoryID, Equal<Required<InventoryItem.inventoryID>>>>.Select(Base, row.InventoryID);

polineext.UsrIsSerialized = (item.LotSerClassID == "SERIAL");
}
}
}

#endregion

public PXAction<POOrder> TestAction2;

PXUIField(DisplayName = "Test NonConf 2", Enabled = true, Visible = true)]
// PXButton(CommitChanges = true, Category = "Other", DisplayOnMainToolbar = true)]
PXButton()]
protected virtual IEnumerable testAction2(PXAdapter adapter)
{


POLine curline = Base.Transactions.Current;

//CreateVendorNonConfFilterView.Current = nc;
//AHSPOLineNonConf nc = new AHSPOLineNonConf();

//nc = AHSPOLineNonConfView.Insert(nc);

AHSPOLineNonConf newRec = this.AHSPOLineNonConfView.Insert(new AHSPOLineNonConf());

Base.Cachesetypeof(AHSPOLineNonConf)].SetValue<AHSPOLineNonConf.inventoryID>(newRec, curline.InventoryID);

Base.Cachesetypeof(AHSPOLineNonConf)].SetValue<AHSPOLineNonConf.inventoryDescr>(newRec, curline.TranDesc);

Base.Cachesetypeof(AHSPOLineNonConf)].Update(newRec);

Base.Actions.PressSave();


// nc.OrderType = curline.OrderType;
// nc.OrderNbr = curline.OrderNbr;
// nc.LineNbr = curline.LineNbr;
// nc.NonConfLineNbr = 1;
// nc.InventoryID = curline.InventoryID;
// nc.InventoryDescr = curline.TranDesc;

//AHSPOLineNonConfView.Update(nc);

//AHSPOLineNonConfView.Cache.Persist(PXDBOperation.Insert);

// //Base.Persist();
// Base.Save.Press();

return adapter.Get();
}

public PXAction<AHSPOLineNonConf> AddPOLineNonConf;
PXUIField(DisplayName = "Add Non Conformance", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select)]
PXButton(CommitChanges = true, Category = "Other", DisplayOnMainToolbar = false)]
protected virtual IEnumerable addPOLineNonConf(PXAdapter adapter)
{
PXTrace.WriteInformation("Reached the AddPOLineNonConf action");

POLine curline = Base.Transactions.Current;

if (curline != null)
{
// pre fill non conf line
AHSPOLineNonConf nc = CreateVendorNonConfFilterView.Current;

nc.OrderType = curline.OrderType;
nc.OrderNbr = curline.OrderNbr;
nc.LineNbr = curline.LineNbr;
nc.NonConfLineNbr = 1;
nc.InventoryID = curline.InventoryID;
nc.InventoryDescr = curline.TranDesc;

CreateVendorNonConfFilterView.Update(nc);

//CreateVendorNonConfFilterView.Current = nc;

if (CreateVendorNonConfFilterView.AskExt() == WebDialogResult.OK)
{
// user selected ok to add new polinenonfrecord

//Base.Document.Ask("Add Non Conformance", "User Clicked the Add Non Conformance Action...", MessageButtons.OK);

if (nc != null)
{
// add new record
// valiation needed?

AHSPOLineNonConfView.Insert(nc);
Base.Save.Press();
}

}
}
return adapter.Get();
}
}
}

 


darylbowman,

Good call out on the receipttype that was an error I missed from a copy/paste.

 

I thought that may be the issue, but still not persisting after correcting that.  I’ll test with the PXParent, I thought you had have it defind for each keyfield.

Thanks

Scott


 I removed the multiple PXParent attributes and I found an additional field that incorrectly has IsKey = True and removed it.  Still not able to get any records for my custom table to persist.

Here’s the revised DAC 

using System;
using PX.Data;
using PX.Data.BQL.Fluent;
using PX.Data.ReferentialIntegrity.Attributes;

namespace PX.Objects.PO
{
>Serializable]
>PXCacheName("AHSPOLineNonConf")]
>PXPrimaryGraph(typeof(POOrderEntry))]
public class AHSPOLineNonConf : IBqlTable
{
#region OrderType
PXDBString(2, IsKey = true, IsFixed = true, InputMask = "")]
PXUIField(DisplayName = "Order Type")]
PXDBDefault(typeof(POLine.orderType))]
PXParent(typeof(SelectFrom<POLine>.
Where<POLine.orderType.IsEqual<AHSPOLineNonConf.orderType.FromCurrent>.
And<POLine.orderNbr.IsEqual<AHSPOLineNonConf.orderNbr.FromCurrent>.
And<POLine.lineNbr.IsEqual<AHSPOLineNonConf.lineNbr.FromCurrent>>>>))]
public virtual string OrderType { get; set; }
public abstract class orderType : PX.Data.BQL.BqlString.Field<orderType> { }
#endregion

#region OrderNbr
PXDBString(15, IsKey = true, IsUnicode = true, InputMask = "")]
PXUIField(DisplayName = "Order Nbr")]
PXDBDefault(typeof(POLine.orderNbr))]
// PXParent(typeof(SelectFrom<POLine>.
// Where<POLine.orderType.IsEqual<AHSPOLineNonConf.orderType.FromCurrent>.
// And<POLine.orderNbr.IsEqual<AHSPOLineNonConf.orderNbr.FromCurrent>.
// And<POLine.lineNbr.IsEqual<AHSPOLineNonConf.lineNbr.FromCurrent>>>>))]
public virtual string OrderNbr { get; set; }
public abstract class orderNbr : PX.Data.BQL.BqlString.Field<orderNbr> { }
#endregion

#region LineNbr
PXDBInt(IsKey = true)]
PXUIField(DisplayName = "Line Nbr")]
PXDBDefault(typeof(POLine.lineNbr))]
// PXParent(typeof(SelectFrom<POLine>.
// Where<POLine.orderType.IsEqual<AHSPOLineNonConf.orderType.FromCurrent>.
// And<POLine.orderNbr.IsEqual<AHSPOLineNonConf.orderNbr.FromCurrent>.
// And<POLine.lineNbr.IsEqual<AHSPOLineNonConf.lineNbr.FromCurrent>>>>))]
public virtual int? LineNbr { get; set; }
public abstract class lineNbr : PX.Data.BQL.BqlInt.Field<lineNbr> { }
#endregion

#region NonConfLineNbr
PXDBInt(IsKey = true)]
PXUIField(DisplayName = "Non Conf Line Nbr")]
PXLineNbr(typeof(POLineExt.usrNonConfLineNbrCntr))]
public virtual int? NonConfLineNbr { get; set; }
public abstract class nonConfLineNbr : PX.Data.BQL.BqlInt.Field<nonConfLineNbr> { }
#endregion

#region ReceiptType
PXUIField(DisplayName = "Type")]
PXDBString(2, IsFixed = true)]

public virtual string ReceiptType { get; set; }
public abstract class receiptType : PX.Data.BQL.BqlString.Field<receiptType> { }
#endregion

#region ReceiptNbr
PXDBString(15, IsUnicode = true, InputMask = "")]
PXUIField(DisplayName = "Receipt Nbr.")]
PXSelector(typeof(Search<POReceiptLine.receiptNbr, Where<POReceiptLine.pONbr, Equal<Current<POLine.pONbr>>, And<POReceiptLine.pOLineNbr,Equal<Current<POLine.pOLineNbr>>>>>))]
public virtual string ReceiptNbr { get; set; }
public abstract class receiptNbr : PX.Data.BQL.BqlString.Field<receiptNbr> { }
#endregion

#region Quantity
PXDBInt()]
PXUIField(DisplayName = "Quantity")]
public virtual int? Quantity { get; set; }
public abstract class quantity : PX.Data.BQL.BqlInt.Field<quantity> { }
#endregion

#region LotSerialNo
PXDBString(255, IsUnicode = true, InputMask = "")]
PXUIField(DisplayName = "Lot Serial No")]
public virtual string LotSerialNo { get; set; }
public abstract class lotSerialNo : PX.Data.BQL.BqlString.Field<lotSerialNo> { }
#endregion

#region InventoryID
// PXDBInt()]
PXUIField(DisplayName = "Inventory ID")]
POLineInventoryItem(Filterable = true)]

public virtual int? InventoryID { get; set; }
public abstract class inventoryID : PX.Data.BQL.BqlInt.Field<inventoryID> { }
#endregion

#region InventoryDescr
PXDBString(256, IsUnicode = true, InputMask = "")]
PXUIField(DisplayName = "Inventory Descr")]
public virtual string InventoryDescr { get; set; }
public abstract class inventoryDescr : PX.Data.BQL.BqlString.Field<inventoryDescr> { }
#endregion

#region NonConfReason
PXDBString(IsUnicode = true, InputMask = "")]
PXUIField(DisplayName = "Non Conf Reason")]
public virtual string NonConfReason { get; set; }
public abstract class nonConfReason : PX.Data.BQL.BqlString.Field<nonConfReason> { }
#endregion

#region Resolution
PXDBString(IsUnicode = true, InputMask = "")]
PXUIField(DisplayName = "Resolution")]
public virtual string Resolution { get; set; }
public abstract class resolution : PX.Data.BQL.BqlString.Field<resolution> { }
#endregion

#region Tstamp
PXDBTimestamp()]
PXUIField(DisplayName = "Tstamp")]
public virtual byte ] Tstamp { get; set; }
public abstract class tstamp : PX.Data.BQL.BqlByteArray.Field<tstamp> { }
#endregion

#region CreatedByID
PXDBCreatedByID()]
public virtual Guid? CreatedByID { get; set; }
public abstract class createdByID : PX.Data.BQL.BqlGuid.Field<createdByID> { }
#endregion

#region CreatedByScreenID
PXDBCreatedByScreenID()]
public virtual string CreatedByScreenID { get; set; }
public abstract class createdByScreenID : PX.Data.BQL.BqlString.Field<createdByScreenID> { }
#endregion

#region CreatedDateTime
PXDBCreatedDateTime()]
public virtual DateTime? CreatedDateTime { get; set; }
public abstract class createdDateTime : PX.Data.BQL.BqlDateTime.Field<createdDateTime> { }
#endregion

#region LastModifiedByID
PXDBLastModifiedByID()]
public virtual Guid? LastModifiedByID { get; set; }
public abstract class lastModifiedByID : PX.Data.BQL.BqlGuid.Field<lastModifiedByID> { }
#endregion

#region LastModifiedByScreenID
PXDBLastModifiedByScreenID()]
public virtual string LastModifiedByScreenID { get; set; }
public abstract class lastModifiedByScreenID : PX.Data.BQL.BqlString.Field<lastModifiedByScreenID> { }
#endregion

#region LastModifiedDateTime
PXDBLastModifiedDateTime()]
public virtual DateTime? LastModifiedDateTime { get; set; }
public abstract class lastModifiedDateTime : PX.Data.BQL.BqlDateTime.Field<lastModifiedDateTime> { }
#endregion
}
}

 


Scott, the problem is your filter view. Once I removed that the test record was saved to the database.

//public PXFilter<AHSPOLineNonConf> CreateVendorNonConfFilterView;

 


zfebert56,

Thank  you so much, that did resolve the issue.

I guess having 2 views declared for the same DAC confused the framework.

I’ve created a new “Filter” dac for that view.

Scott


 Another question regarding my custom field on the PO Line extension used to store the PXLineNbr.

This works on new records, but I get a null reference error on existing records.  If I manually update the field for a PO line to zero vs. null the error goes away.

Is there a recommended way to handle this this issue?

I know I could do a custom sql script to update all polines from null to 0, but I was not sure if there is way to handle it without the script.  

I did not see a way to specify a default value when adding the custom field to the database scripts section.

// PXLineNbr
#region NonConfLineNbr
PXDBInt(IsKey = true)]
PXUIField(DisplayName = "Non Conf Line Nbr")]
PXLineNbr(typeof(POLineExt.usrNonConfLineNbrCntr))]
public virtual int? NonConfLineNbr { get; set; }
public abstract class nonConfLineNbr : PX.Data.BQL.BqlInt.Field<nonConfLineNbr> { }
#endregion


// POLin Extension
#region UsrNonConfLineNbrCntr

PXDBInt()]
PXUIField(DisplayName = "NonConfLineNbrCntr")]
PXDefault(0, PersistingCheck = PXPersistingCheck.Nothing)]
public virtual int? UsrNonConfLineNbrCntr { get; set; }
public abstract class usrNonConfLineNbrCntr : PX.Data.BQL.BqlInt.Field<usrNonConfLineNbrCntr> { }

#endregion

 


I don’t know what is the best way to solve it. You can use SQL, and you can also try to default the value to zero in FieldDefaulting or RowSelecting events.


I think I’ll plan on the SQL script for now.

Thanks for the feedback, and the help resolving my original issue.  

 


Reply