Skip to main content
Solved

How to make project billing period default to On Demand?

  • Oct 22, 2026 7:42 PM UTC
  • 4 replies
  • 41 views
  • Translate All

We never use monthly billing, but that’s what our project billing period (summary tab) defaults to upon setup. Each project is highly customized, so templates are not feasible. I see that the billing period populates with Monthly as soon as a customer is selected for the project; thought maybe the customer class had the setting, but it does not and I don’t see anything else that made sense to me. What do we need to do to change this default? We’re on 25R2 soon to upgrade to 26R2. 

Best answer by Steve Milner

@ssternke Jfiscus's approach is the built-in way to get On Demand. The template's Billing Period copies onto the project when you pick the template.

Without a template, there's no setting for it. It isn't on the customer class, as you found, and Projects Preferences doesn't have one either. Month is hard-coded in the Projects (PM301000) logic. When a customer goes on a project and Billing Period is still empty, the system fills in Month. That's why it shows up the moment you pick the customer.

Since templates don't fit your projects, the change has to be a customization. It's a small one. The extension below lets the stock logic run, then swaps Month for On Demand on new projects that don't use a template. I tested it on 2026 R1. A new project came up On Demand as soon as the customer went on, and an existing Month project stayed Month even when its customer was cleared and picked again.

using PX.Data;
using PX.Objects.CT;
using PX.Objects.PM;

namespace ProjectBillingOnDemand
{
    public class ProjectEntryOnDemandExt : PXGraphExtension<ProjectEntry>
    {
        public static bool IsActive() { return true; }

        protected virtual void _(Events.FieldUpdated<PMProject, PMProject.customerID> e)
        {
            ContractBillingSchedule billing = Base.Billing.Current;
            if (e.Row == null || billing == null) return;

            // New project, no template, customer just picked: replace the stock Monthly with On Demand
            if (e.Cache.GetStatus(e.Row) == PXEntryStatus.Inserted
                && e.Row.TemplateID == null
                && e.OldValue == null
                && e.Row.CustomerID != null
                && billing.Type == BillingType.Monthly)
            {
                Base.Billing.Cache.SetValueExt<ContractBillingSchedule.type>(billing, BillingType.OnDemand);
                Base.Billing.Update(billing);
            }
        }
    }
}

Add it as a Code item in a customization project. Publish it to a 25 R2 test tenant before production, and test it again after the 26 R2 upgrade.

View original

4 replies

  • Freshman I
  • Oct 22, 2026 10:06 PM UTC

We use project templates and the billing period is set on each template.  We bill all projects on demand with a fixed fee billing rule (meaning we enter it manually rather than letting the system calculate a bill).

 

 

Translate

Steve Milner
Varsity III
Forum|alt.badge.img+6
  • Varsity III
  • Answer
  • Oct 22, 2026 10:48 PM UTC

@ssternke Jfiscus's approach is the built-in way to get On Demand. The template's Billing Period copies onto the project when you pick the template.

Without a template, there's no setting for it. It isn't on the customer class, as you found, and Projects Preferences doesn't have one either. Month is hard-coded in the Projects (PM301000) logic. When a customer goes on a project and Billing Period is still empty, the system fills in Month. That's why it shows up the moment you pick the customer.

Since templates don't fit your projects, the change has to be a customization. It's a small one. The extension below lets the stock logic run, then swaps Month for On Demand on new projects that don't use a template. I tested it on 2026 R1. A new project came up On Demand as soon as the customer went on, and an existing Month project stayed Month even when its customer was cleared and picked again.

using PX.Data;
using PX.Objects.CT;
using PX.Objects.PM;

namespace ProjectBillingOnDemand
{
    public class ProjectEntryOnDemandExt : PXGraphExtension<ProjectEntry>
    {
        public static bool IsActive() { return true; }

        protected virtual void _(Events.FieldUpdated<PMProject, PMProject.customerID> e)
        {
            ContractBillingSchedule billing = Base.Billing.Current;
            if (e.Row == null || billing == null) return;

            // New project, no template, customer just picked: replace the stock Monthly with On Demand
            if (e.Cache.GetStatus(e.Row) == PXEntryStatus.Inserted
                && e.Row.TemplateID == null
                && e.OldValue == null
                && e.Row.CustomerID != null
                && billing.Type == BillingType.Monthly)
            {
                Base.Billing.Cache.SetValueExt<ContractBillingSchedule.type>(billing, BillingType.OnDemand);
                Base.Billing.Update(billing);
            }
        }
    }
}

Add it as a Code item in a customization project. Publish it to a 25 R2 test tenant before production, and test it again after the 26 R2 upgrade.

Translate

Forum|alt.badge.img+1

Hi ​@ssternke,

Steve’s spot on - there’s no native setting, so it’s either a template or a small customization.

Worth clearing up one thing though: a template doesn’t have to be a full one. You can make a bare template that only sets Billing Period = On Demand, then still customize each project freely after creating it - so “too custom for templates” doesn’t really rule this out. One catch: create the project via the “create from template” action rather than starting on the Projects screen and picking the template after, since there are reports of On Demand reverting to Monthly done that way.

If you’d rather skip templates entirely, Steve’s extension is the way - just test it on both 25 R2 and 26 R2 before production since he tested on 26 R1.

Translate

  • Author
  • Freshman I
  • Oct 23, 2026 2:44 PM UTC

​@aryanjadhav50 ​@Steve Milner ​@Jfiscus 
Thank you so much!
I realized after I posted that we could do a project template without all the detail and probably will still do that - and thank you for the tip on creating from template vs from within project - but ideally, we’d have a foolproof solution. I figured a customization was going to be necessary. I’m going to pass this on to our partner for implementation. 

Translate