Skip to main content

Hi,

I have run into an issue where the Billing Period dropdown highlighted at the bottom of the image is not updated by the template selector at the top of the image.

In that template, the Billing Period dropdown value has been set to ‘On Demand’, but it still shows as ‘Monthly’ as shown below.

 

This problem doesn’t occur when I create a new record from the screen above as it gives me an empty record, so selecting the template updates the Billing Period dropdown correctly.

It occurs when I create a new row from the screen shown below as it gives me a screen with some fields already filled, as shown below this first image.

Creating a new row from main Projects screen

 

Template is greyed out and Billing Period dropdown is still showing the value ‘Month’

 

As you can see in the image above, the template dropdown at the top is greyed out and parts of the form have already been filled in.

Is there a way to make sure the Billing Period field is always grabbing whetever was set in the template, if a template has been selected?

Let me know if I can clarify anything.

 

Kind regards,

Andrew

Hello @AndrewA ,

I think you are saying that when you press + to add a project from the Project Preview List, the screen opens with the template already filled in (but related template fields are not filled in as they appear on this project template as it currently appears in Preferences → Project Templates screen).  Also the Project Template can’t be changed after pressing + to add a new project.

I searched my Demo for the source of the default template. (I am using Projects module, not Construction edition).  In Project Profiles, I see a default Quote Template, but I don’t see a place to define a default Project Template. What is the source of your default project template?  Is it possible the screen is customized? 

If the screen is customized, temporarily un-publish customization projects for the Project profile screen. Does any template default to the screen with customizations unpublished?  If so, the template should be editable, so you can choose a different template. In this case, does the default template correctly populate the On Demand Billing Period?  If no template defaults into the screen, I expect you can choose the same template shown above and it will properly default the values. 

I am guessing on customizations; if I’m on the wrong track please let us know the source of the default project template, let us know about customization status, and we can carry on from there.

Laura


Hi Laura,

Sorry for the wait in getting back to you. Yep you’re exactly right in what you said in that first paragraph.

The issue is that this Projects screen is heavily customised, it is the main screen that the client uses and there have been many changes that have been applied to ensure it functions the way they would like it to. I will unpublish and let you know what happens.

Would the template field being greyed out mean that it doesn’t have the same effect on fields as it would if you could change the selection? Or does greyed out mean it can’t be changed but still should influence the other fields?


Hi Laura,

I tested the Projects screen with all the customisations for that screen unpublished, and the issue with the template field was still there.

Is there a way to check if there is some kind of code that is causing the pre-filling of fields, and potentially causing the template field to be uneditable?

If there is some code that is causing the pre-filling of fields, is there a way to temporarily turn that off so that a template can be chosen whenever the new record button (‘+’) is clicked?


Hi, one more thing you might try is clearing browser cache and then adding project from the preview list. Or try a different browser, different pc. When I add a new project, the template does not self-populate. I think the default template and billing period must be coming from somewhere else, not from the template as it looks today. Such as from a cached copy of the webpage.

Do you have multiple project templates? Or just one? If there are multiples, I wonder how one became “stuck”, how was this template selected as the default? 
 

It may be useful for Support to know your version and edition. I can’t answer your question about code, except to say un-publishing should have removed all custom code.


Hi Laura,

Here is the current version I am using: Build 2021.213.204.9588 [21.213.0038]

I tried your suggestion of other PCs and other browsers, as well as clearing the cache, but it still functions the same in all cases.

I may have to play around with the customisations a bit more as I may not have cleared the cache correctly when I unpublished customisations before. I will keep you updated on how I go.

Thanks for your help on this!


If you want always inherit values from template and override whatever standard methods or customizations do, you will need to create a customization project and assign the highest priority and inside that either override the Persist method or RowPersisted handler.

in either of these codes you can check to see if TemplateID of the current project is not null and if not then Select from PMProject where ContractID = TemplateID and update the current record desired fields with template values. It’s a pretty straightforward customization.


Hi Reza,

Thanks for your reply.

I was testing adding an override for the RowPersisted handler by writing something like ‘This is a test’ to the Trace window using PXTrace.WriteInformation() so that I know if that event was fired. However, I couldn’t see that text in the Trace when I output the form. The only way I can get that to appear is when I change the value of the Template field in a blank form, but I am wanting to see this text appear when a form loads so that I can update the relevant dropdown at that moment.

Would you be able to provide an example of how you would set up an override function? You don’t need to add the code inside the function, I just want to see the shell of it as I want to put the test trace text in there again to see if it is hitting the right spot.


I did a little blurb for you. Add either of them to your Graph Extension. Either one should do the work (DO NOT use both). First, try the persist and trace to see how it works. You might need to modify the code.

 

        #region Persist
public delegate void PersistDelegate();
PXOverride]
public void Persist(PersistDelegate baseMethod)
{
PMProject project = Base.Project.Current;
ContractBillingSchedule projectBilling = Base.Billing.Current;

if (project != null && project.TemplateID != null)
{
PMProject template = SelectFrom<PMProject>
.Where<PMProject.contractID.IsEqual<@P.AsInt>>
.View.Select(Base, project.TemplateID);

if (template != null)
{
ContractBillingSchedule templateBilling = SelectFrom<ContractBillingSchedule>
.Where<ContractBillingSchedule.contractID.IsEqual<@P.AsInt>
.And<ContractBillingSchedule.type.IsNotNull>>
.View.SelectWindowed(Base, 0, 1, template.ContractID);

if (templateBilling != null && projectBilling != null)
{
projectBilling.Type = templateBilling.Type;
Base.Billing.Update(projectBilling);
}
}
}

baseMethod?.Invoke();
}
#endregion

#region RowPersisted
protected virtual void _(Events.RowPersisted<PMProject> e, PXRowPersisted BaseHandler)
{
if (e.Row == null) return;

// Call Base Handler
BaseHandler?.Invoke(e.Cache, e.Args);

if (e.Row.TemplateID != null)
{
PMProject template = SelectFrom<PMProject>
.Where<PMProject.contractID.IsEqual<@P.AsInt>>
.View.Select(e.Cache.Graph, e.Row.TemplateID);

if (template != null)
{
ContractBillingSchedule templateBilling = SelectFrom<ContractBillingSchedule>
.Where<ContractBillingSchedule.contractID.IsEqual<@P.AsInt>
.And<ContractBillingSchedule.type.IsNotNull>>
.View.SelectWindowed(e.Cache.Graph, 0, 1, template.ContractID);

if (templateBilling != null && Base.Billing.Current != null)
{
Base.Billing.Current.Type = templateBilling.Type;
}
}
}
}
#endregion

 


Hi Reza,

Thanks for sending that through. I tried both of your suggestions separately but they didn’t seem to work. I have a feeling that all the other customisations are stopping it from working as I get the following warning when publish those changes.

Warning: The Code#ProjectEntry object of the Graph type from the  project will be ignored because this project has lower level than the  project, which defines the same object.

Is there a way to remove this warning?


What is the priority you have assigned to this new project? Send a screenshot of your customizations here, please.

And Also your Graph Extension Code for this new project. Can you please confirm you are a programmer?


Hi Reza,

Yes I am a programmer. Here is an image of my customisations.

 

Here is the graph extension code for the new project. Ignore the PXTrace lines, I was just writing some random stuff to see if it appeared in the Trace log.

using PX.Api;
using PX.Data;
using PX.Data.DependencyInjection;
using PX.LicensePolicy;
using PX.Objects.AP;
using PX.Objects.AR;
using PX.Objects.CA;
using PX.Objects.CM;
using PX.Objects.Common;
using PX.Objects.CR;
using PX.Objects.CS;
using PX.Objects.CT;
using PX.Objects.EP;
using PX.Objects.GL;
using PX.Objects.GL.FinPeriods;
using PX.Objects.IN;
using PX.SM;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using PX.Data.BQL.Fluent;
using PX.Data.BQL;
using PX.Objects;
using PX.Objects.PM;

namespace PX.Objects.PM
{
public class ProjectEntry_Extension : PXGraphExtension<ProjectEntry>
{

#region RowPersisted
protected virtual void _(Events.RowPersisted<PMProject> e, PXRowPersisted BaseHandler)
{
if (e.Row == null) return;
PXTrace.WriteInformation('Start of function');

// Call Base Handler
BaseHandler?.Invoke(e.Cache, e.Args);

if (e.Row.TemplateID != null)
{
PXTrace.WriteInformation('Template selected');
PMProject template = SelectFrom<PMProject>
.Where<PMProject.contractID.IsEqual<@P.AsInt>>
.View.Select(e.Cache.Graph, e.Row.TemplateID);

if (template != null)
{
PXTrace.WriteInformation('Template found');
ContractBillingSchedule templateBilling = SelectFrom<ContractBillingSchedule>
.Where<ContractBillingSchedule.contractID.IsEqual<@P.AsInt>
.And<ContractBillingSchedule.type.IsNotNull>>
.View.SelectWindowed(e.Cache.Graph, 0, 1, template.ContractID);

if (templateBilling != null && Base.Billing.Current != null)
{
PXTrace.WriteInformation('Template and current billing found');
Base.Billing.Current.Type = templateBilling.Type;
}
}
}
}
#endregion
}
}

 

Kind regards,

Andrew


I see you have assigned the lowest priority to this project, not the highest. Also, I see you have customized PMProject Screen in many customization projects. It is not good practice let alone the best practice. You need to combine them into one.


Oh ok, I will look at combining them together and let you know how I go

 


Hello, I am having an issue using this logic to get the Payroll Accounts to populate when a template is selected.  Below are the fields I’m looking at.    I have used the code above to try to get 1 working but because the records are on the PMProject. not detail or related table I think I may be getting an issue with my syntax. 

using PX.Data.EP;
using PX.Data.ReferentialIntegrity.Attributes;
using PX.Data.SQLTree;
using PX.TM;
using PX.Objects.TX;
using PX.Api;
using PX.Data;
using PX.Data.DependencyInjection;
using PX.LicensePolicy;
using PX.Objects.AP;
using PX.Objects.AR;
using PX.Objects.CA;
using PX.Objects.CM.Extensions;
using PX.Objects.Common;
using PX.Objects.CR;
using PX.Objects.CS;
using PX.Objects.CT;
using PX.Objects.EP;
using PX.Objects.Extensions.MultiCurrency;
using PX.Objects.GL;
using PX.Objects.GL.FinPeriods;
using PX.Objects.IN;
using PX.SM;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using PX.Data.BQL.Fluent;
using PX.Data.BQL;
using PX.Common;
using PX.Objects.PO;
using PX.Objects.SO;
using PX.Objects.CR.Extensions;
using PX.Objects;
using PX.Objects.PM;

namespace PX.Objects.PM
{
public class ProjectEntry_Extension : PXGraphExtension<PX.Objects.PM.ProjectEntry>
{
#region RowPersisted
protected virtual void _(Events.RowPersisted<PMProject> e, PXRowPersisted BaseHandler)
{
if (e.Row == null) return;

// Call Base Handler
BaseHandler?.Invoke(e.Cache, e.Args);

if (e.Row.TemplateID != null)
{
PMProject template = SelectFrom<PMProject>
.Where<PMProject.contractID.IsEqual<@P.AsInt>>
.View.Select(e.Cache.Graph, e.Row.TemplateID);

if (template != null)
{
PMProject templateAccounts = SelectFrom<PMProject>
.Where<PMProject.contractID.IsEqual<@P.AsInt>
.And<PMProject.EarningsAcctID.IsNotNull>>
.View.SelectWindowed(e.Cache.Graph, 0, 1, template.ContractID);

if (templateAccounts != null && Base.ProjectProperties.Current != null)
{
Base.ProjectProperties.Current.EarningsAcctID = templateAccounts.EarningsAcctID;
}
}
}
}
#endregion

}

}

Error: 

\App_RuntimeCode\ProjectEntry.cs(59): error CS0426: The type name 'EarningsAcctID' does not exist in the type 'PMProject'

Reply