How to persist a graph with unrelated tables - acumatica

Lets say I have a graph as follows
public PXCancel<DAC1> Cancel;
public PXSave<DAC1> Save;
public PXSelect<DAC1> View;
public PXSelect<DAC2> Entities;
public PXSelect<DAC3> Mappings;
Currently, when a change is made to the data view of DAC2, when the save button is pressed, nothing is persisted (even though the save button becomes enabled on the UI once the change is made). Once I make a change to DAC1, then the changes to both DAC1 and DAC2 are persisted successfully.
How can I make it so that when only a change to DAC2 is made, the save button works?

You can try marking the record of the DAC1 as updated in the cache when the record of the DAC2 or DAC3 is updated.
graph.Caches[typeof(DAC1)].MarkUpdated(record);

Related

How to Save Filter values on processing page

I have a custom processing page that has 3 fields in the custom filter DAC. I want any values in these three filter fields to stay set after the user clicks Process or Process All. Right now, they are cleared out when the processing completes. How can I get them to keep their value?
The filter DAC is currently unbound - should I make it a real table in the DB?
Here are what the views look like now:
public PXFilter<POLineFilter> Filter;
[PXFilterable]
public PXFilteredProcessingJoin<POLine, POLineFilter,
InnerJoin<PMProject, On<PMProject.contractID, Equal<POLine.projectID>>>,
Where<POLine.closed.IsEqual<False>.And<POLine.cancelled.IsEqual<False>>
.And<POLine.projectID.IsEqual<POLineFilter.projectID.FromCurrent>.Or<POLineFilter.projectID.FromCurrent.IsNull>>
.And<POLine.orderNbr.IsEqual<POLineFilter.poNbr.FromCurrent>.Or<POLineFilter.poNbr.FromCurrent.IsNull>>
.And<PMProject.ownerID.IsEqual<POLineFilter.projectManager.FromCurrent>.Or<POLineFilter.projectManager.FromCurrent.IsNull>>>> POLines;
TIA!
Add the following as your 2nd view.
public PXCancel<POLineFilter> Cancel;

How can I disable the Copy/Paste Save Template action?

Acumatica offers a great feature to Save as Template which makes creating new records from the template faster and easier. However, I have a use case where I need a more interactive sort of template in which the user can create a list of 100 items and then select which items to include when creating the new record.
In this case, the standard feature for Save as Template could be confusing, especially for new users learning the system. I have been asked to disable Save as Template on the Copy/Paste menu on my custom screen and transition to this new feature. I do not want to disable Copy/Paste entirely, just the Template functionality. If I disable Copy/Paste in Access Rights, the entire menu disappears. However, the template options do not appear in Access Rights.
Copy/Paste appears to be accessible via code as the PXAction CopyPaste which can be hidden or disabled, but again, I cannot find SaveTemplate as a child that I can control.
How can I disable/hide Save as Template (CopyPaste#SaveTemplate) on an Acumatica screen, either programmatically, in access rights, or in workflow? This menu is part of the standard Acumatica menu system when specifying a primary DAC when defining the graph. Alternatively, I think it enabled via the PXCopyPasteAction<> action if manually defining buttons on the page.
You can create your own PXCopyPasteAction by just extending the base class and then adding it to your graph
quick example below
public class CustomCopyPasteAction: PXCopyPasteAction<SOOrder>
{
public CustomCopyPasteAction(PXGraph graph, string name): base(graph, name) { }
protected override void RowSelected(PXCache cache, PXRowSelectedEventArgs e)
{
base.RowSelected(cache, e);
bmSaveTemplate.Enabled = false;
}
}
The CopyPaste action is coming predefined as part of the PXGraph<TGraph,TPrimary> class. So you should be able to just simply do CopyPaste.SetEnabled(false) in the RowSelected event handler of your graph.
Another option is to try to override the CanClipboardCopyPaste virtual function of the PXGraph class.
public class PXGraph<TGraph, TPrimary> : PXGraph where TGraph : PXGraph where TPrimary : class, IBqlTable, new()
{
public override bool CanClipboardCopyPaste()
{
return true;
}
/// <summary>The action that saves changes stored in the caches to the database. The code of an application graph typically saves changes through this action as well. To invoke it from code, use the PressSave() method of the Actions property.</summary>
public PXSave<TPrimary> Save;
/// <summary>The action that discard changes to the data from the caches.</summary>
public PXCancel<TPrimary> Cancel;
/// <summary>The action that inserts a new data record into the primary cache.</summary>
public PXInsert<TPrimary> Insert;
/// <summary>The action that deletes the Current data record of the primary cache.</summary>
public PXDelete<TPrimary> Delete;
/// <summary>The action that is represented on the user interface by an expandable menu that includes Copy and Paste items.</summary>
public PXCopyPasteAction<TPrimary> CopyPaste;
/// <summary>The action that navigates to the first data record in the primary data view. The data record is set to the Current property of the primary cache.</summary>
public PXFirst<TPrimary> First;
/// <summary>The action that navigates to the previous data record in the primary data view. The data record is set to the Current property of the primary cache.</summary>
public PXPrevious<TPrimary> Previous;
/// <summary>The action that navigates to the next data record in the primary data view. The data record is set to the Current property of the primary cache.</summary>
public PXNext<TPrimary> Next;
/// <summary>The action that navigates to the last data record in the primary data view. The data record is set to the Current property of the primary cache.</summary>
public PXLast<TPrimary> Last;
}

Limiting Projects based on selector

I would like to filter the records shown on the Projects screen. I've been given the directive to see if limiting the Selector for projects (re-writing the PXSelector for the ProjectID?) would also limit the records that show up on the screen, i.e., a user would not be able to navigate to records that aren't displayed by the Selector. I don't think that's the case, as the screen's view is not limited by what is chosen by the Selector - but I wanted to verify this.
Also - as far as limiting the records that show up in the Selector (possibly re-writing the Selector/BQL using a where clause?) - I looked at the source DAC, and for the life of me I can't figure it out. There is a PXSelector on the ContractID, which doesn't use the SubstituteKey that I'm familiar with, and the ContractCD also has several attributes with which I'm unfamiliar - namely the PXRestrictor AND the PXDimensionSelector.
Bottom line:
1.) What's the best way to limit the records for Project shown in the screen's Selector? Can I just add to the PXRestrictor attribute?
2.) Would limiting the Selector's results also limit what the user can navigate to on the screen using the navigation buttons?
Whenever you need to restrict access to primary records on a data entry screen, it's always required to customize both the lookup DAC key field and the primary data view. By design, in Acumatica key fields in DAC and the primary data view are completely independent, that is why it's required to modify both pieces to achieve the desired result.
For example, to deny access to canceled projects on the Projects screen, you should add PXRestrictorAttribute to PMProject's ContractCD field and also re-declare Project primary data view:
public class ProjectEntryExt : PXGraphExtension<ProjectEntry>
{
public class cancelled : Constant<string>
{
public cancelled() : base(ProjectStatus.Cancelled) {; }
}
[PXViewName(Messages.Project)]
public PXSelect<PMProject, Where<PMProject.baseType, Equal<PMProject.ProjectBaseType>,
And<PMProject.nonProject, Equal<False>, And<PMProject.isTemplate, Equal<False>,
And<PMProject.status, NotEqual<cancelled>,
And<Match<Current<AccessInfo.userName>>>>>>>> Project;
[PXMergeAttributes(Method = MergeMethod.Append)]
[PXRestrictor(typeof(Where<PMProject.status, NotEqual<cancelled>>),
"Given Project/Contract '{0}' is cancelled", typeof(PMProject.contractCD))]
public void PMProject_ContractCD_CacheAttached(PXCache sender) { }
}

Attaching Documents to Custom Table Records without a Custom Screen

I have a custom table for historical data. It's a one-time data dump directly into SQL so I'd prefer not to have to create a screen for it.
I have three columns in my table:
CompanyID INT
InvoiceNbr NVARCHAR(40)
Amount DECIMAL(19,4)
I create a new Customization Project and added a new DAC to the Code area that is linked to my custom table:
https://i.imgur.com/6mNjdou.png (Screenshot #1)
https://i.imgur.com/IdNLJkR.png (Screenshot #2)
Then I create a Generic Inquiry, but I don't get the Paper Clip and Note icons. I was hoping to use the Paper Clip to upload documents and attach them to the records in my custom table.
So, I added another column to my custom table:
NoteID UNIQUEIDENTIFIER
And I re-added the new DAC which now generates this code:
https://i.imgur.com/QvpWB5X.png (Screenshot #3)
Now I get the Paper clip and Note icons in my Generic Inquiry:
https://i.imgur.com/olCglBB.png (Screenshot #4)
I can add a note or attach a document and the icons change color which makes it seem like the notes and documents got attached to the records. But when I refresh the page, everything goes away. Also, I can tell that nothing is getting stored in the database.
So the Paper Clip and Note icons don't work.
I'm wondering if it's possible to get the Paper Clip and Note icons to work in my Generic Inquiry without building a custom screen. Is this possible?
Tim, for Notes and Attachments to work properly, your NoteID field should be decorated with the PXNote attribute, instead of the default combination of PXDBGuid- and PXUIFieldAttribute. Will everything work as expected after you replace NoteID field declaration with the code snippet below and republish the customization?
public abstract class noteID : PX.Data.IBqlField
{
}
[PXNote()]
public virtual Guid? NoteID { get; set; }

Strange Behavior with DeletedDatabaseRecord

I would like to use logical deletion in a custom screen and I have added the following to my DAC:
#region DeletedDatabaseRecord
public abstract class deletedDatabaseRecord : PX.Data.IBqlField
{
}
protected bool? _DeletedDatabaseRecord;
[PXDBBool()]
[PXDefault(false)]
public virtual bool? DeletedDatabaseRecord
{
get
{
return this._DeletedDatabaseRecord;
}
set
{
this._DeletedDatabaseRecord = value;
}
}
#endregion
The above DAC is used in a grid (in a master/detail screen). When I click on the grid delete and then save, the row gets marked as deleted in the database.
However, when I refresh the screen, the deleted rows appear again. It seems that the data view is not taking into DeletedDatabaseRecord value. I confirmed that this was set to 1 in the database.
My data view is as follows:
public PXSelect<DCRule, Where<DCRule.ruleHeaderID, Equal<Current<DCRuleHeader.ruleHeaderID>>>, OrderBy<Asc<DCRule.sequence>>> Rules;
Shouldn't the data view, automatically filter out deleted records (where DeletedDatabaseRecord = 1)? or should I handle something else in the code logic.
UPDATE 1
I have removed the DeletedDatabaseRecord from the DAC as the Design Guidelines state that they should not be included. However, I am still having the exact same issue.
UPDATE 2
I also noticed that the SQL statement is not filtering out the deleted records, and it is also not returning it as a column.
Add CompanyID column to the table where you use DeletedDatabaseRecord. After that deleted row should not appear.
One should never declare DAC fields for the following columns:
CompanyID
CompanyMask
DeletedDatabaseRecord
When you make some to Acumatica database schema, it's always a good practice to restart IIS or recycle the app pool hosting your Acumatica website, so Acumatica can re-sync the updated DB schema during domain restart as it does not track database schema changes at runtime.

Resources