I tried to create a Screen in acumatica/lexbizz, which should display all entries for my newly created DAC in a simple grid view. The graph looks like this:
using PX.Data;
using PX.Data.BQL.Fluent;
using PX.LotSertialNbrAttribute.Ext;
namespace Maut1
{
public class TestMaint : PXGraph<TestMaint>
{
public SelectFrom<M1InventoryLotSerialContainer>.View InventoryLotSerialContainers;
}
}
and the used DAC M1InventoryLotSerialContainer contains two Date fields declared like this:
#region ValidFrom
[PXDBDate()]
[PXUIField(DisplayName = "Valid from")]
public virtual DateTime? ValidFrom { get; set; }
public abstract class validFrom : PX.Data.BQL.BqlDateTime.Field<validFrom> { }
#endregion
#region ValidTo
[PXDBDate()]
[PXUIField(DisplayName = "Valid to")]
public virtual DateTime? ValidTo { get; set; }
public abstract class validTo : PX.Data.BQL.BqlDateTime.Field<validTo> { }
#endregion
and I created both fields in the SQL table as nullable and of type [datetime]. I can manage to create new entries in the table by using an already existing screen, but when I try to access my newly created GridView I get the following exception and there are no entries displayed:
5/12/2021 3:42:27 PM Error:
Error: An error occurred during processing of the field Valid to: Specified cast is not valid..
System.InvalidCastException: Specified cast is not valid.
at System.Data.SqlClient.SqlBuffer.get_DateTime()
at System.Data.SqlClient.SqlDataReader.GetDateTime(Int32 i)
at PX.Data.PXDataRecord.GetDateTime(Int32 i) in C:\Users\svc-builder\AppData\Local\Temp\~PX.Data.0\PX.Data.dll.il:line 769081
at PX.Data.PXDBDateAttribute.RowSelecting(PXCache sender, PXRowSelectingEventArgs e) in C:\Users\svc-builder\AppData\Local\Temp\~PX.Data.0\PX.Data.dll.il:line 856111
at PX.Data.PXCache.OnRowSelecting(Object item, PXDataRecord record, Int32& position, Boolean isReadOnly) in C:\Users\svc-builder\AppData\Local\Temp\~PX.Data.0\PX.Data.dll.il:line 666901
at PX.Data.PXCache.OnRowSelecting(Object item, PXDataRecord record, Int32& position, Boolean isReadOnly) in C:\Users\svc-builder\AppData\Local\Temp\~PX.Data.0\PX.Data.dll.il:line 666757
at PX.Data.PXCache`1.Select(PXDataRecord record, Int32& position, Boolean isReadOnly, Boolean& wasUpdated) in C:\Users\svc-builder\AppData\Local\Temp\~PX.Data.0\PX.Data.dll.il:line 644916
at PX.Data.PXView.CreateItem(PXCache cache, PXDataRecord record, Int32& position, Boolean isReadOnly, Boolean& wasUpdated) in C:\Users\svc-builder\AppData\Local\Temp\~PX.Data.0\PX.Data.dll.il:line 685666
at PX.Data.PXView.CreateResult(PXCache[] caches, PXDataRecord rec, Boolean hascount, Boolean& overrideSort, Boolean& extFilter) in C:\Users\svc-builder\AppData\Local\Temp\~PX.Data.0\PX.Data.dll.il:line 685586
at PX.Data.PXView.GetResult(Object[] parameters, PXFilterRow[] filters, Boolean reverseOrder, Int32 topCount, PXSearchColumn[] sorts, Boolean& overrideSort, Boolean& extFilter) in C:\Users\svc-builder\AppData\Local\Temp\~PX.Data.0\PX.Data.dll.il:line 685520
at PX.Data.PXView.Select(Object[] currents, Object[] parameters, Object[] searches, String[] sortcolumns, Boolean[] descendings, PXFilterRow[] filters, Int32& startRow, Int32 maximumRows, Int32& totalRows) in C:\Users\svc-builder\AppData\Local\Temp\~PX.Data.0\PX.Data.dll.il:line 690963
at PX.Data.PXGraph.ExecuteSelect(String viewName, Object[] currents, Object[] parameters, Object[] searches, String[] sortcolumns, Boolean[] descendings, PXFilterRow[] filters, Int32& startRow, Int32 maximumRows, Int32& totalRows) in C:\Users\svc-builder\AppData\Local\Temp\~PX.Data.0\PX.Data.dll.il:line 981069
As far as I can understand acumatica is not able to cast the field Valid to as a [datetime]. I already tried to use the type [datetime2] in my SQL table, but nothing changed. So I'm not quite sure if either the field is declared wrongfully in the DAC or if I have to use a different type in the SQL table.
BTW this is my first question posted on stackoverflow, so Feedback is appreciated on how to improve on questions in the future
I would check your customization page definition, my guess is that you created the wrong kind of control to present your date field. Go into 'Customization Project Editor', click on your screen under the 'Screens' header, Click on your grid, click on the 'Add Data Fields' column on the right. Check for your 'Valid To' field and make sure it's not listed with a Selector Control or something other than DateTimeEdit. If it is, you can delete, change the control, and re-add.
I solved the problem by generating the DAC in the Customization Editor from the SQL table. After that I could apply all changes I needed inside the DAC while checking if the view is still correct every few fields. Quite a tedious process. This way I could narrow the problem down to a different field that was defined like this:
#region CustomerID
[CustomerActive(DisplayName = "Customer ID", DescriptionField = typeof(Customer.acctName))]
[PXUIField(DisplayName = "Customer ", Enabled = false)]
[PXDBInt]
public virtual int? CustomerID { get; set; }
public abstract class customerID : PX.Data.BQL.BqlInt.Field<customerID> { }
#endregion
The Attribute [PXDBInt] is already included when [CustomerActive] is used. By deleting [PXDBInt] from the CustomerID field the duplicate is removed and the DAC can be correctly used on my screen. I'm still not completely sure why acumatica mentioned the field ValidTo in the exception, because for this field there are no changes necessary. For the future I will be more aware of the Exception messages, apparantly they can be a little confusing and lead in a wrong direction.
Related
I have a custom screen with a custom Graph, and my graph has a View delegate that calls another method in the same graph. Doesn't seem that crazy, but an exception is thrown by Acumatica:
Unable to cast object of type '<GetVersions>d__25' to type 'System.Collections.IDictionary'.
My delegate method is simply this:
protected virtual IEnumerable reportVersions()
{
yield return GetVersions();
}
public virtual IEnumerable GetVersions()
{
yield return null;
}
Yet, when I take out the call:
protected virtual IEnumerable reportVersions()
{
yield return null;
}
there is no error. The call stack is long, but seems to be happening when the grid referencing the view is being rendered on the page and binding to this as a data source. Here's the top of the call stack:
[InvalidCastException: Unable to cast object of type '<GetVersions>d__25' to type 'System.Collections.IDictionary'.]
PX.Data.PXCache`1.GetValueInt(Object data, String fieldName, Boolean forceState, Boolean externalCall) +807
PX.Data.PXCache`1.GetValueExt(Object data, String fieldName) +123
PX.Data.PXGraph.GetValueExt(String viewName, Object data, String fieldName) +126
PX.Web.UI.PXBaseDataSource.GetValueExt(String viewName, Object data, String fieldName) +151
PX.Web.UI.PXDataSourceView.GetValue(Object data, String fieldName) +42
PX.Web.UI.PXFormDataProvider.GetFieldValue(String field, DataSourceView view)
...
It appears to be trying to retrieve a field value. Any thoughts?
Change the reportVersions() method by this
protected virtual IEnumerable reportVersions()
{
return GetVersions();
}
or
protected virtual IEnumerable reportVersions()
{
foreach (var item in GetVersions())
{
yield return item;
}
}
I'm upgrading an older version (6.1) to 2019 R1 (19.100.0022) and an old section of code is giving me an error that I cannot understand. Here's the relevant code - which is an attribute:
[ActiveProjectTask(typeof(EPExpenseClaimSummary.projectID), BatchModule.EP, DisplayName = "Project Task")]
[PXDefault]
public virtual int? TaskID
{
The problem is that there seems to be something wrong with the 'BatchModule.EP' parameter. Here's the error I get:
ProjectTaskAttribute does not support the given module.
Parameter name: Module
Actual value was EP.
The stack trace is as follows:
[ArgumentOutOfRangeException: ProjectTaskAttribute does not support the given module.
Parameter name: Module
Actual value was EP.]
PX.Data.PXGraph.CreateInstance(Type graphType, String prefix) +1017
PX.Web.UI.PXBaseDataSource.f(Type A_0) +560
PX.Web.UI.PXBaseDataSource.g(Type A_0) +195
PX.Web.UI.PXBaseDataSource.get_DataGraph() +396
User_PageTitle.InitAuditMenu() +591
User_PageTitle.Page_InitComplete(Object sender, EventArgs e) +71
System.EventHandler.Invoke(Object sender, EventArgs e) +0
System.Web.UI.Page.OnInitComplete(EventArgs e) +141
System.Web.UI.Page.ProcessRequestMain(Boolean
includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2203
Does anyone know what's happening here?
I couldn't locate the relevant release note but I'm almost certain this is a breaking change introduced by newer versions. Only BatchModule.EA will be allowed in that context, for all practical purpose it seems to have replaced BatchModule.EP.
More concerning is EPExpenseClaimSummary which was removed so I think some refactoring will be necessary here because the module was re-implemented. You can get inspiration from the new DAC EPExpenseClaim (summary) and EPExpenseClaimDetails (details). I think the ActiveProjectTask attribute should be replaced by EPExpenseAllowProjectTask attribute (exemple in source code below).
The TaskID field has been moved from Summary to Details so you can't re-use your current logic. This means task are now assigned per detail records instead of being assigned to a single header record changing the relationship from 1-1 to 1-x. Also project was renamed to contract. The most relevant fields for you would be EPExpenseClaimDetails.ContractID and EPExpenseClaimDetails.TaskID:
#region ContractID
public abstract class contractID : PX.Data.IBqlField
{
}
/// <summary>
/// The <see cref = "Contract.ContractID"/> project or contract</see>, which should be specified if the
/// employee incurred the expenses while working on a particular project or contract.
/// You can select a project or contract only if the Project Management or Contract Management feature,
/// respectively, is enabled on the Enable/Disable Features (CS100000) form.
/// </summary>
[PXDBInt]
[PXUIField(DisplayName = "Project/Contract")]
[PXDimensionSelector(ContractAttribute.DimensionName,
typeof(Search2<Contract.contractID,
LeftJoin<EPEmployeeContract,
On<EPEmployeeContract.contractID, Equal<Contract.contractID>,
And<EPEmployeeContract.employeeID, Equal<Current2<employeeID>>>>>,
Where<Contract.isActive, Equal<True>,
And<Contract.isCompleted, Equal<False>,
And<Where<Contract.nonProject, Equal<True>,
Or2<Where<Contract.baseType, Equal<CTPRType.contract>,
And<FeatureInstalled<FeaturesSet.contractManagement>>>,
Or<Contract.baseType, Equal<CTPRType.project>,
And2<Where<Contract.visibleInEA, Equal<True>>,
And2<FeatureInstalled<FeaturesSet.projectModule>,
And2<Match<Current<AccessInfo.userName>>,
And<Where<Contract.restrictToEmployeeList, Equal<False>,
Or<EPEmployeeContract.employeeID, IsNotNull>>>>>>>>>>>>,
OrderBy<Desc<Contract.contractCD>>>),
typeof(Contract.contractCD),
typeof(Contract.contractCD),
typeof(Contract.description),
typeof(Contract.customerID),
typeof(Contract.status),
Filterable = true,
ValidComboRequired = true,
CacheGlobal = true,
DescriptionField = typeof(Contract.description))]
[ProjectDefault(BatchModule.EA, AccountType = typeof(expenseAccountID))]
public virtual int? ContractID
{
get;
set;
}
#endregion
#region TaskID
public abstract class taskID : PX.Data.IBqlField
{
}
/// <summary>
/// The <see cref="PMTask">project task</see> to which the expenses are related.
/// This box is available only if the Project Management feature is enabled on the Enable/Disable Features (CS100000) form.
/// </summary>
///
[PXDefault(typeof(Search<PMTask.taskID, Where<PMTask.projectID, Equal<Current<contractID>>, And<PMTask.isDefault, Equal<True>>>>), PersistingCheck = PXPersistingCheck.Nothing)]
[EPExpenseAllowProjectTaskAttribute(typeof(EPExpenseClaimDetails.contractID), BatchModule.EA, DisplayName = "Project Task")]
[PXUIEnabled(typeof(Where<contractID, IsNotNull, And<Selector<contractID, Contract.baseType>, Equal<CTPRType.project>>>))]
[PXFormula(typeof(Switch<Case<Where<contractID, IsNull, Or<Selector<contractID, Contract.baseType>, NotEqual<CTPRType.project>>>, Null>, taskID>))]
[PXForeignReference(typeof(Field<taskID>.IsRelatedTo<PMTask.taskID>))]
public virtual int? TaskID
{
get;
set;
}
#endregion
I'm trying to process return orders in Acumatica, for which I will have to create a Sales Order of type RC, invoke the Create Receipt Action on the sales order which creates a shipment of type Receipt and then invoke Confirm Shipment on the shipment. However in the list of Actions defined on the Sales Order, I do not find an action corresponding to Create Receipt. Can anyone guide me on how to invoke the Create Receipt action programatically as we do through the screen?
For e.g. this is how I invoke Confirm Shipment on a shipment and looking for something similar to Create Receipt:
var adapter = new PXAdapter(graph.CurrentDocument);
adapter.Arguments.Add("actionID", SOShipmentEntryActionsAttribute.ConfirmShipment);
PXLongOperation.StartOperation(graph, delegate ()
{
foreach (SOShipment soShipment in graph.action.Press(adapter)) ;
});
This is a solution previously provided by Acumatica, I tried this method in few screens and it was working. In the following code try to change the graph to your SOOrderEntry and Command to "Create Receipt"
docgraph.Document.Current = docgraph.Document.Search<SOShipment.shipmentNbr>("mYsHIPMENTnUMBER");
docgraph.Cancel.Press();
foreach (var action in (docgraph.action.GetState(null) as PXButtonState).Menus)
{
if (action.Command == "Confirm Shipment")
{
PXAdapter adapter2 = new PXAdapter(new DummyView(docgraph, docgraph.Document.View.BqlSelect, new List<object> { docgraph.Document.Current }));
adapter2.Menu = action.Command;
docgraph.action.PressButton(adapter2);
}
}
internal class DummyView : PXView
{
List<object> _Records;
internal DummyView(PXGraph graph, BqlCommand command, List<object> records)
: base(graph, true, command)
{
_Records = records;
}
public override List<object> Select(object[] currents, object[] parameters, object[] searches, string[] sortcolumns, bool[] descendings, PXFilterRow[] filters, ref int startRow, int maximumRows, ref int totalRows)
{
return _Records;
}
}
I am trying to insert a new record into a custom table in the database. This is being performed through a graph extension onto the SO graph. The code is as follows:
public PXAction<PX.Objects.SO.SOOrder> addToDatabase;
[PXButton(CommitChanges = true)]
[PXUIField(DisplayName = "Send to Manufacturing")]
protected void AddToDatabase()
{
try
{
Flow2 graphWO = PXGraph.CreateInstance<Flow2>();
EMPWorkOrder wo = null;
foreach (PXResult<SOLine, InventoryItem> line in PXSelectJoin<SOLine, LeftJoinSingleTable<InventoryItem, On<InventoryItem.inventoryID, Equal<SOLine.inventoryID>>>,
Where<SOLine.orderNbr, Equal<Current<SOOrder.orderNbr>>>>.Select(Base, Base.Document.Current.OrderNbr))
{
PXCache sender = Base.Transactions.Cache;
SOLine soLine = (SOLine)line;
InventoryItem item = (InventoryItem)line;
SOLineExt lineExt = sender.GetExtension<SOLineExt>(soLine);
if (lineExt.UsrisSentToManufacturing != true)
{
wo = new EMPWorkOrder();
wo.Soid = Base.Document.Current.OrderNbr;
wo.ItemCD = item.InventoryCD;
wo.LineNbr = soLine.LineNbr;
wo.QtyReceived = 0;
wo.DateReceived = null;
wo.QtyComplete = 0;
wo.QtySentToInventory = 0;
wo.RouteId = "0";
wo.KitId = -1;
wo.IsStarted = false;
wo.NoteID = Guid.NewGuid();
graphWO.Document.Insert(wo);
graphWO.Actions.PressSave();
graphWO.Clear();
}
}
throw new PXException("Successfully moved to Manufacturing");
}
}
When executing the code, the error I receive is the following:
Error#14: Inserting 'EMPWorkOrder' record raised one or more errors. Please review.
When I go into the trace, this is the information it gives me:
12/16/2016 1:44:23 PM Error:
Error #14: Inserting 'EMPWorkOrder' record raised one or more errors. Please review.
at PX.Objects.SO.SOOrderEntry_Extension.AddToDatabase()
at PX.Data.PXAction`1.<>c__DisplayClass3_0.<.ctor>b__0(PXAdapter adapter)
at PX.Data.PXAction`1.a(PXAdapter A_0)
at PX.Data.PXAction`1.d__31.MoveNext()
at PX.Data.PXAction`1.d__31.MoveNext()
at PX.Web.UI.PXBaseDataSource.tryExecutePendingCommand(String viewName, >String[] sortcolumns, Boolean[] descendings, Object[] searches, Object[] >parameters, PXFilterRow[] filters, DataSourceSelectArguments arguments, >Boolean& closeWindowRequired, Int32& adapterStartRow, Int32& adapterTotalRows)
at PX.Web.UI.PXBaseDataSource.ExecuteSelect(String viewName, DataSourceSelectArguments arguments, PXDSSelectArguments pxarguments)
Is there any reason that my record wouldn't be inserting into the custom table I made? If you need any other information to develop a resolution to this issue, please feel free to ask.
Eric, you most likely get this error because of some empty field or fields (with no value or null value assigned) decorated with the PXDefaultAttribute. While running the code under debugger, you should get access to a more detailed exception through the InnerException property of the originally thrown exception.
On a side note, let me also advise you to add SOLine.orderType field in Where clause of your BQL query in the beginning of action delegate, as there are 2 key fields defined for the SOOrder DAC has: OrderType and OrderNbr
I've updated our test environment to the latest version of Acumatica 5.10.0752. After updating our sync process has started to fail when inserting an item into a sales order. Note that no code changes were implemented to the sync process and the only change was to apply the latest update to Acumatica. I've been struggling with this and can't seem to solve adequately and could use a bit of help..
Here is the stack trace:
System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> PX.Data.PXException: Error #112: An error occurred while processing the field InventoryID : Object reference not set to an instance of an object.. ---> System.NullReferenceException: Object reference not set to an instance of an object. at PX.Objects.SO.SOOrderEntry.SOLine_CuryUnitCost_FieldDefaulting(PXCache sender, PXFieldDefaultingEventArgs e) at PX.Data.PXCache.OnFieldDefaulting(String name, Object row, Object& newValue) at PX.Data.PXCache1.SetDefaultExt(Object data, String fieldName) at PX.Objects.SO.SOOrderEntry.SOLine_UOM_FieldUpdated(PXCache sender, PXFieldUpdatedEventArgs e) at PX.Data.PXFieldUpdated.Invoke(PXCache sender, PXFieldUpdatedEventArgs args) at PX.Data.PXCache.OnFieldUpdated(String name, Object row, Object oldValue, Boolean externalCall) at PX.Data.PXCache1.SetDefaultExt(Object data, String fieldName) at PX.Objects.SO.SOOrderEntry.SOLine_InventoryID_FieldUpdated(PXCache sender, PXFieldUpdatedEventArgs e) at PX.Data.PXFieldUpdated.Invoke(PXCache sender, PXFieldUpdatedEventArgs args) at PX.Data.PXCache.OnFieldUpdated(String name, Object row, Object oldValue, Boolean externalCall) at PX.Data.PXCache1.a(TNode A_0, TNode A_1, IDictionary A_2, PXCacheOperation A_3, Boolean A_4) --- End of inner exception stack trace --- at PX.Data.PXCache1.a(TNode A_0, TNode A_1, IDictionary A_2, PXCacheOperation A_3, Boolean A_4) at PX.Data.PXCache1.a(TNode A_0, TNode A_1, IDictionary A_2, PXCacheOperation A_3) at PX.Data.PXCache1.Insert(IDictionary values) at PX.Data.PXCache1.Update(IDictionary keys, IDictionary values) at PX.Data.PXGraph.ExecuteUpdate(String viewName, IDictionary keys, IDictionary values, Object[] parameters) at PX.Data.PXGraph.CopyPasteCommitChanges(String viewName, OrderedDictionary keys, OrderedDictionary vals) at PX.Api.SyImportProcessor.SyStep.CommitChanges(Object itemToBypass, PXFilterRow[] targetConditions) at PX.Api.SyImportProcessor.ExportTableHelper.ExportTable() at PX.Api.ScreenUtils.Submit(String screenId, Command[] commands, SchemaMode schemaMode, PXGraph& graph, String& redirectContainerView, String& redirectScreen, Boolean mobile) at PX.Api.Services.ScreenService.Submit(String id, IEnumerable1 commands, SchemaMode schemaMode, Boolean mobile, PXGraph& forceGraph, String& redirectContainerView, String& redirectScreen) at PX.Api.Services.ScreenService.Submit(String id, IEnumerable`1 commands, SchemaMode schemaMode) at PX.Api.Soap.Screen.ScreenGate.Submit(Command[] commands) --- End of inner exception stack trace ---
Here is a code snippet that worked fine before the update:
cmds.Add( SO301000.DocumentDetails.ServiceCommands.NewRow );
cmds.Add( new AcumaticaApiWS.Value { Value = item.InventoryId, LinkedCommand = SO301000.DocumentDetails.InventoryID } );
cmds.Add( new AcumaticaApiWS.Value { Value = item.Quantity, LinkedCommand = SO301000.DocumentDetails.Quantity } );
cmds.Add( new AcumaticaApiWS.Value { Value = item.UnitPrice, LinkedCommand = SO301000.DocumentDetails.UnitPrice } );
cmds.Add( new AcumaticaApiWS.Value { Value = item.WebCode, LinkedCommand = SO301000.DocumentDetails.WebCode } );
cmds.Add( new AcumaticaApiWS.Value { Value = item.ExtPrice, LinkedCommand = SO301000.DocumentDetails.ExtPrice} );
cmds.Add( new AcumaticaApiWS.Value { Value = item.ReasonCode, LinkedCommand = SO301000.DocumentDetails.ReasonCode } );
cmds.Add( new AcumaticaApiWS.Value { Value = item.LineDescription, LinkedCommand = SO301000.DocumentDetails.LineDescription } );
cmds.Add( SO301000.Actions.Save );
try
{
this.context.SO301000Submit( cmds.ToArray() );
}
catch( Exception ex )
{
...
}
It seems to be related to UOM but I'm not sure what the issue is. Thinking that there might be a some configuration somewhere that needs to be setup. But not seeing what it could be.
If I add this line of code right after the new row command, it works fine.
cmds.Add( new AcumaticaApiWS.Value { Value = "EA", LinkedCommand = SO301000.DocumentDetails.UOM } );
However, I would prefer it to get the UOM from the item's inventory default as it was before the update.
Any help would be greatly appreciated.
** Another thought we had was that when we skipped updates by installing just the latest version without installing each of the versions in between we inadvertently caused this issue. - Could that cause weird behavior - skipping updates to just install the latest? Tx
Regarding stack trace you need to set UOM