Skip to main content
Question

How to make project billing period default to On Demand?

  • October 22, 2026
  • 2 replies
  • 13 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. 

2 replies

  • Freshman I
  • October 22, 2026

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

@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