According to the list of new/updated features in acumatica it mentions the following: "Specify multiple, non-continuous ranges in the data source for accounts, subaccounts,and branches in the general ledger engine."
However from what I'm seeing, this doesn't seem to apply to subaccounts.
For example in my situation, the first segment of the subaccount defines the "region".
When defining my Unit sets what I need to do is the following:
Central Region - (subacct segment AB and DE)
- Sub1 (AB)
- Sub2 (DE)
North Region (subacct segment BC)
In the Data Source, I can only specify a single "Start" and "End" subaccount which uses all in between.
Is it possible to have the "Central Region" be a summary of all the child nodes OR can I specify i want ONLY subaccts AB, DE for "Central Region"
In FRx you can do this where the "Folder" or "Parent" is a summary of the children items underneath it.
It is indeed possible, but by default the user interface will not allow you to enter the string in such a way, due to the segmented nature of the subaccount field. You can, however, customize the field so that it no longer behaves as a segmented editor. To do that, you need to create a PXCacheExtension on RMDataSourceGL which will override the StartSub/EndSub attributes. The class looks like that:
using System;
using PX.Data;
using PX.Objects.GL;
using PX.CS;
namespace PX.Objects.CS
{
[Serializable]
public partial class RMDataSourceGL : PXCacheExtension<RMDataSource>
{
[PXDBString(255, IsUnicode = true)]
[PXUIField(DisplayName = "Start Sub.")]
public virtual string StartSub { get; set; }
[PXDBString(255, IsUnicode = true)]
[PXUIField(DisplayName = "End Sub.")]
public virtual string EndSub { get; set; }
}
}
Once the customization is in place, you can put non-contiguous ranges in the StartSub/EndSub fields. Please note that the segmented key separator (usually it's '-') should not be part of the ranges. For example, assuming you want to include all subaccounts between US-00-00-00-000 and US-99-99-99-999 AND all the CA- accounts, you would put the following in the StartSub field: US?????????,CA?????????. You could also express it differently: US000000000-US999999999,CA000000000-CA999999999. The syntax is documented in the 5.0 release notes, and is the same for accounts.
As a secondary Comment for those who might be reading this, I also found that it is possible to make a Parent folder summarize the children. For Example:
CE - Central Region
AB - Sub1
DE - Sub2
Instead of specifying a Data Source for "CE", specify a Value of
=#AB+#DE
Related
I have a process that creates records in the Sales Orders screen's Details grid based on two Header user fields: SiteID (Warehouse) and LocationID.
When the 'Create Shipment' process is initiated, the shipment is created which contains the SiteID in the Sales Orders grid - but since there is no locationID in the grid, this 'Create Shipment' process uses some default(?) LocationID, where I'd like to use the Header User field's LocationID.
My question is, how would I intercept this process to set the LocationID to something other than what it's defaulting to?
Thanks...
Update:
Using the virtual method:
SetShipmentFieldsFromOrder(SOOrder order, SOShipment shipment, Nullable<Int32> siteID, Nullable<DateTime> shipDate, String operation, SOOrderTypeOperation orderOperation, Boolean newlyCreated, SetShipmentFieldsFromOrderDelegate baseMethod)
I don't see any way to set the grid value for LocationID (i.e., there is no SOShipLine record to set a value in the virtual method. How would I do this?
There's a virtual method on the SOShipmentEntry graph called SetShipmentFieldsFromOrder, you can override that to update the CustomerLocationID as needed. The create shipment action calls SOShipmentEntry.CreateShipment which inserts the shipment and then calls the SetShipmentFieldsFromOrder method.
The system should be pulling the SOShipment.CustomerLocationID from the SOOrder.CustomerLocationID field by default though.
I believe the question is about defaulting of warehouse locations into the shipment lines and allocations rather than customer locations
Currently, shipment line selects location(s) by the following way
Originally (SelectLocationStatus), it selects location based on their pick priority (smaller value means higher priority)
After this method, the ResortStockForShipmentByDefaultItemLocation is executed. This method puts the default issue location for the item-warehouse combination (InItemSite) at the top of this list regardless of its pick priority.
I believe you should override this method to put the needed location to the top of the list instead of (or ahead of) the default issue location. Here is the code of this method of the SOShipmentEntry class for reference:
protected virtual void ResortStockForShipmentByDefaultItemLocation(SOShipLine newline, List<PXResult> resultset)
if (INSite.PK.Find(this, newline.SiteID)?.UseItemDefaultLocationForPicking != true)
return;
var dfltShipLocationID = INItemSite.PK.Find(this, newline.InventoryID, newline.SiteID)?.DfltShipLocationID;
if (dfltShipLocationID == null)
return;
var listOrderedByDfltShipLocationID = resultset.OrderByDescending(
r => PXResult.Unwrap<INLocation>(r).LocationID == dfltShipLocationID).ToList();
resultset.Clear();
resultset.AddRange(listOrderedByDfltShipLocationID);
}
Important! If we are talking about 21R2 version, there is the "Project-Specific Inventory" (materialManagement) feature which has its own extension of the SOShipmentEntry where some of the shipment creation methods (including the SelectLocationStatus) are overridden. The ResortStockForShipmentByDefaultItemLocation is not overridden, but if the customer uses this feature, I suggest to extend this extension rather than base SOSHipmentEntry:
namespace PX.Objects.PM.MaterialManagement
{
public class SOShipmentEntryMaterialExt : PXGraphExtension<SOShipmentEntry>
For example, if I change the "Original Budgeted Quantity" field to 9.00 (see first image below), I would like that to also change in the Revenue tab (see second image) without having to change the same thing twice.
Is there a way I can achieve this?
Cost Tab
Revenue Tab
Here are the details of the two fields I have highlighted in the images above:
Cost Tab Field
Revenue Tab Field
Let me know if I need to clarify anything or provide more information :)
Unfortunately I'm not very familiar with the Project Entry screen, and after a quick glance I couldn't find an easy way to tie the records from the Cost Budget tab to the Revenue Budget tab.
If you are planning on tying these two records together you may need some additional customization work to create the link that you are looking for if it doesn't already exist.
As far as the update itself, that is pretty straightforward and can be accomplished with a simple event handler, as demonstrated below.
namespace MyCompany.MyCustomization
{
public class ProjectEntryExtMyCustomization : PXGraphExtension<ProjectEntry>
{
public static bool IsActive() => true;
#region Actions
#endregion
#region Events
protected virtual void _(Events.FieldUpdated<PMCostBudget, PMCostBudget.qty> eventHandler)
{
PMCostBudget row = eventHandler.Row;
if (row is null) return;
// Replace the stub below with your PMRevenueBudget lookup
// using the link that you have defined.
PMRevenueBudget revenueDetail = new PMRevenueBudget();
// Assigns the PMRevenueBudget Qty field to match the PMCostBudget new value.
revenueDetail.Qty = eventHandler.NewValue as decimal?;
// Updates the PMRevenueBudget record in the cache.
Base.RevenueBudget.Update(revenueDetail);
}
#endregion
}
}
Don't forget to replace the line where I create a new PMRevenueBudget with the logic that you need for looking up the linked PMRevenueBudget record that you need. Let me know if you have any questions.
The field in the DAC is defined like this.
#region NextMonthHours
[PXDBDecimal(2, MinValue = 0.0, MaxValue = 280.0)]
[PXUIField(DisplayName = "Next Month Hours")]
[PXDefault(TypeCode.Decimal, "0.0")]
public virtual Decimal? NextMonthHours { get; set; }
public abstract class nextMonthHours : PX.Data.BQL.BqlDecimal.Field<nextMonthHours> { }
#endregion
I change the display name of the field in RowSelected event.
PXUIFieldAttribute.SetDisplayName<EVEPPlannedHoursDetails.nextMonthHours>(sender, nextMonth+"Hours");
where nextMonth is "February".
I need to add this field to Acumatica Mobile Screen. When I go to web service schema the field name is "FebruaryHours"
<s:element minOccurs="0" maxOccurs="1" name="FebruaryHours" type="tns:Field"/>
I cannot use the name "FebruaryHours" because it changes every month but I also when I use field name NextMonthHours it is not added in the mobile screen.
Any idea how to solve this issue?
Thanks
There's quite a few ways to workaround this depending on the use case and whether the label value is static or dynamic.
If all you want to do is to change a static label in UI without having to change the display name property you can add a separate label and merge group.
Here's an example to change Billable in UI without changing DisplayName property using that technique.
Set SuppressLabel property to true to hide the original label bounded to DisplayName on UI.
Use ADD CONTROLS tab to add a Layout Rule with Merge property set to true.
Use ADD CONTROLS tab to add a label control in the merged group.
Put the original field in the merge group so they show up together on the same line in UI.
End result, label is now a UI control and wouldn't interfere with DisplayName property.
I would like to access the individual segments of a subaccount programmatically. Assuming I have a particular sub account set as ABC-123, I would like to be able to access ABC and 123 separately in code so that I can implement a particular business requirement.
I know that SubAccounts are saved in the Sub table as one string example ABC123. The sub account fields which link to this table would then link based on the ID (integer - PK of the Sub table). I can of course read from this table and then split accordingly (by taking the first 3 characters and the second 3 characters). However, I would like this to be dynamic so that the customization will work for different clients and clients may have different lengths for the segment. Therefore I cannot hard-code the value 3. I can make use of the SegmentValues table to retrieve the lengths of each Segment accordingly.
However, since Acumatica is already somehow carrying out this parsing (example in the UI), is there an API where Acumatica handles this logic and can provide the Sub-account as an array of strings. I tried to look into the SubAccountAttribute, PXDimensionSelectorAttribute, and SubAccountProvider but could not find anything which delivers this functionality.
Does Acumatica provide a way to split the sub-account into an array of strings or should I do this manually by identifying lengths from the Segment Values?
I believe some of the logic used to separate the segment are in the protected Definition class. The separated segments are in the Dimensions collections of the Definition class. You can access it in attributes that derive from PXDimensionAttribute class but since Definition class is protected you can't access it in a graph because PXGraph/PXGraphExtension don't derive from it.
Not much can be extracted from Dimension because most properties are protected:
You can roll your own by reading the segments of the segmented key:
Here is an example that write the segment values of the transactions subaccount in the trace for the Invoices and Memos screen:
using PX.Data;
using PX.Objects.AR;
using PX.Objects.CS;
using PX.Objects.GL;
namespace PX.Objects.SO
{
public class ARInvoiceEntry_Extension : PXGraphExtension<ARInvoiceEntry>
{
public void ARTran_RowSelected(PXCache cache, PXRowSelectedEventArgs e)
{
ARTran tran = e.Row as ARTran;
if (tran != null && tran.SubID.HasValue)
{
Sub sub = SubAccountAttribute.GetSubaccount(Base, tran.SubID.Value);
if (sub != null && sub.SubCD != null)
{
short segmentStartIndex = 0;
foreach (Segment segment in PXSelect<Segment,
Where<Segment.dimensionID, Equal<Required<Segment.dimensionID>>>,
OrderBy<Asc<Segment.segmentID>>>.Select(Base, "SUBACCOUNT"))
{
if (segment.SegmentID.HasValue && segment.Length.HasValue)
{
PXTrace.WriteInformation(string.Format("Segment {0}: {1}",
segment.SegmentID,
sub.SubCD.Substring(segmentStartIndex, segment.Length.Value)));
segmentStartIndex += segment.Length.Value;
}
}
}
}
}
}
}
Trace results:
I have a User Defined Table that I link to the BAccount table in Acumatica. What I'm trying to do is use the PXDBCreatedDateTime attribute to save the CreateDateTime when the UDFs are set. Is this posssible? It doesn't seem to work right now.
[PXTable(typeof(BAccount.bAccountID),IsOptional=true)]
public class CustomerExtension : PXCacheExtension<BAccount>
{
[PXDBCreatedDateTime()]
[PXUIField(DisplayName = "Date")]
public DateTime? CreatedDateTime { get; set; }
public class createdDateTime : IBqlField { }
}
I would assume it would not work as the BAccount table already contains a field with the same name 'CreatedDateTime'. I would first use a different field name for table extension fields as this could create some conflicts to those fields that already exist with the same name. Also, extension tables are inserted when the base table is either inserted or updated (first time after extension table is added) which may or may not occur from changes to your extension fields. This would also cause some issues for getting a good date from your PXDBCreatedDateTime field. You might be better off using a standard date time field and use some type of formula to update the date when your fields change. I would have to research the formula. You could use logic inside the setter of your user fields and add the PXDependsOnFields attribute to your date field and set your date field if null. I have not tried PXDependsOnFields in an extension - but the logic could be promising.