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
- Summary — status, project manager, and customer, plus rolled-up budget-vs-actual figures.
- Tasks — the PMTask breakdown, each task carrying its own budget, billing rule, and status independent of the project header.
- Budget — the detailed budget lines by cost code/account, the basis for budget-vs-actual reporting and (optionally) commitment checks against POs.
- Billing — the rules governing how project activity becomes an AR invoice — time and materials, fixed-fee milestones, or percentage complete, each with materially different calculation logic.
- Change Orders — formal budget/scope revisions, tracked separately from the original budget so variance reporting can distinguish scope creep from estimation error.
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.
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.
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.
Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.