Acumatica · Customization

Acumatica Project Screen — A Deep Dive

Acumatica Project Screen — A Deep Dive is the screen the user actually lives in. Every other piece of Acumatica — the workflows, the reports, the integrations — exists to feed.

John Kihiu12 min read

Projects (PM301000) is the anchor screen of Acumatica's Project Accounting module, built on ProjectEntry over the PMProject DAC, with PMTask underneath for the task-level breakdown that budgets, billing, and time entry all key off. Almost every other module — AP, AR, GL, even Sales Orders — can tag a transaction with a Project and Task, which makes this screen's customizations disproportionately far-reaching for how few people work in it directly.

Projects vs. the "non-project" code

Every transaction that could be tagged with a project has to resolve to something in that field — Acumatica handles this with a reserved "non-project" placeholder code so that GL/AP/AR transactions not actually tied to a real project still have a valid value. A customization that filters "all project-related transactions" by excluding null needs to exclude the non-project code specifically, not just check for blank.

Key tabs

Extending ProjectEntry

A common customization is enforcing that a project can't move to Active status without a complete budget on every task, or that time entries can't be posted against a task marked Closed — both are validation layered on top of status transitions rather than changes to the billing engine itself, which is complex enough that most teams configure it rather than override it.

C# · GRAPH EXTENSION
public class ProjectEntry_Extension : PXGraphExtension<ProjectEntry>
{
    protected virtual void PMProject_Status_FieldVerifying(PXCache cache,
        PXFieldVerifyingEventArgs e)
    {
        string newStatus = (string)e.NewValue;
        var row = (PMProject)e.Row;
        if (newStatus != "A" || row == null) return;

        bool hasUnbudgetedTask = PXSelect<PMTask,
            Where<PMTask.projectID, Equal<Required<PMTask.projectID>>,
                And<PMTask.curyBudgetTotal, Equal<decimal0>>>>
            .Select(Base, row.ContractID).Any();

        if (hasUnbudgetedTask)
            throw new PXSetPropertyException("All tasks must have a budget before the project can go active.");
    }
}

Custom fields and tabs via the Customization Project Editor

Adding a field to Summary or a task is a standard DAC extension. Because Project/Task is referenced by transaction screens across nearly every module, a custom field meant to influence posting or billing behavior needs to be checked at each of those entry points — the same "enforce it where it's used, not just where it's defined" pattern seen on the Chart of Accounts screen, amplified here by how many modules touch project data.

Common validation and event-handler use cases

Beyond status-gated budget checks: validating that a task's billing rule is compatible with its budget structure (percentage-complete billing needs a defined budget baseline to calculate against), syncing project status changes to a linked Sales Order or Case for cross-departmental visibility, and triggering a revenue recognition review when a task's percentage complete jumps by more than a configured threshold in one update.

Gotchas

Budget figures are stored at the task level, and project-level totals are a rollup — a customization that edits or reports on project-level budget fields directly, bypassing the task breakdown, will drift from what the Budget tab actually shows. Billing rules vary enough between time-and-materials and fixed-fee/milestone structures that generic "calculate what to invoice" logic written against one rule type usually doesn't transfer to the other without real rework. And change orders exist specifically so original budget and approved scope changes stay distinguishable — a customization that merges change-order amounts directly into the original budget loses the variance reporting the whole feature exists to provide.

Project fields propagate everywhere — test broadly

Because nearly every transactional screen can carry a Project/Task tag, a customization to PMProject or PMTask needs testing against AP, AR, GL, and Sales Order entry, not just the Projects screen itself. A change that looks correct here can break validation on a completely unrelated screen that also references the task.

Wrapping up

Projects is less a single screen than a hub that half the other modules quietly depend on through the Project/Task fields they expose. Customizations here need the widest blast-radius thinking of any screen in this series — validate at the source, but test at every downstream screen that can reference a task.

John Kihiu
Acumatica ERP Developer · Laravel Engineer

Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.