Skip to content

Cashflow Projection Applet

A planning register for money you expect to bill and collect: programs group client engagements, engagements break into lines with a value, and each line carries target and actual billing and collection per fiscal month, which a dashboard and two reports turn into collection rates and month-by-month projections. It reads no invoice, receipt or ledger and writes nothing to them — every actual figure is typed by hand, no overnight job corrects or rolls it forward, and no alert fires when collection falls behind; the Collection Delay Report tells you, when someone opens it. It is a separate register from the CRM Engagement applet.

Your job, and the screen for it

The jobScreen or tabRead
Group client engagements into a programProgramProgram
Record an engagement and its linesEngagement › Create / Edit (Lines only after the first save; set the branch on the Account tab)Engagement
Type in each month’s target and actual billing and collection — no invoice, receipt or ledger feeds them, and SAVE on the line itself drops its Program Item linkEdit Line Item › Fiscal Period tabEngagement, line and fiscal period
See the projection month by monthReport › Cashflow Projection ReportCashflow Projection Report
Find the months where collection fell short — the report is empty for lines the screens created, so compare target and actual on the projection reportReport › Collection Delay Report; Report › Cashflow Projection ReportCollection Delay Report
See collection rates per engagementDashboardEngagement Dashboard

Overview

The Cashflow Projection Applet is a planning register for money you expect to bill and collect. You group work into programs, record each piece of client work as an engagement, break an engagement into lines with a value, and then — per line and per fiscal month — enter the target billing, target collection, actual billing and actual collection figures. A dashboard and two reports read those figures back as collection rates, outstanding amounts and month-by-month projections.

It is a standalone register. Nothing in it is a financial document: the applet does not read invoices, receipts or the ledger, and — see Lifecycle and effects — it writes nothing to them either. Every “actual” figure is typed in by hand.

Not to be confused with the Engagement Applet under CRM. That applet keeps an audit/assurance engagement register of its own; the engagements on this page are a separate register and the two are not linked.
The applet was built from a copy of the Sales Invoice applet. Its settings area still lists every sales-invoice setting, which explains the odd names you will meet there. None of that changes what the screens below do.

Where it fits

DirectionWhatWhy
BeforeCustomer MaintenanceThe Account tab and the Program Item form pick the client from the customer listing; the Conglomerate drop-down reads the conglomerate master.
BeforeEntity MaintenanceEntity Branch drop-downs list the chosen entity’s branches.
BeforeForexCurrency drop-downs are the tenant’s currency list.
BeforeTenant AdminProgram and engagement members must already be users of the tenant; the Verify button looks them up by e-mail or phone.
InsideProgram → Engagement → Line → Fiscal PeriodThe hierarchy this applet owns; the dashboard and both reports aggregate the fiscal-period rows.
AfterNothingNo document, journal, cashbook or stock record is created from this applet.

Screens and menus

The sidebar offers the menus below, plus Settings and Personalization. Opening the applet lands on Program. The header title is Cashflow Projection Applet.

MenuWhat opens
ProgramProgram Listing → Create Program / Edit Program → Select Entity (a three-column view stack)
EngagementCFP Engagement Listing → Create / Edit Engagement → Select Entity
DashboardEngagement Dashboard
Report → Cashflow Projection ReportMonth-by-month projection grid
Report → Collection Delay ReportFiscal periods where actual collection fell short of target

The settings gear (OWNER and ADMIN ranks) and the Personalization link render as in every applet.

Program

Program Listing shows Program Code, Program Name, Description, Status, Created Date, Updated Date, Created By, Updated By. The advanced search offers Program Code, Program Name, Status (ACTIVE / INACTIVE, preset to ACTIVE), Created By, Created Date and Updated Date; a free-text keyword must be at least three characters. Created By is shown in the search panel but is never applied. The first load asks for everything. There is no delete button on this listing.

Create Program has a single Main Details tab (Program Code, Program Name, Description, Status) and a CREATE button. Edit Program adds read-only audit fields and three more tabs:

TabWhat it holds
MemberProgram members: User Email, Rank, Status, Created Date, Updated Date, with a quick “Search email” filter. Add Member asks for the user’s e-mail or phone number, a Verify button that resolves it to a tenant login, a Rank (ADMIN, CONTRIBUTOR, VIEWER) and a Status. ADD stays disabled until Verify succeeds. Editing offers UPDATE and DELETE.
EngagementThe engagements that belong to this program: Title, Currency, Status, Process Status, Created By, Created Date, Updated Date. + opens an inline Create Engagement form; a row click opens Edit Engagement. Both are the same five-tab form described under Engagement below, except that the Program is fixed to the parent and there is no Program drop-down.
Program ItemThe items of this program: Item Code, Item Name, Item Type, Currency, Status, Created Date, Updated Date. Add Item / row-click Edit Item open the form in Fields; Edit has a DELETE button. Choosing Entity or Sales Entity navigates to the third column, Select Entity, and returns with the pick.

Engagement

CFP Engagement Listing shows Title, Currency, Status, Process Status, Created By, Created Date and Updated Date. The Title cell is an expandable group: opening it loads a detail grid of the parent program’s items (Item Code, Item Name, Item Type, Currency, Status, Created Date). The advanced search offers Title, Currency and Created Date; only Title and the dates are applied. The listing always shows only ACTIVE engagements — inactive engagements never appear here (they still appear on a program’s Engagement tab).

Every time this listing opens it also fetches the complete, unpaged engagement list a second time and writes it to the browser console — leftover debug code. On a tenant with many engagements that is a second, unpaged fetch on every visit.

Create Engagement / Edit Engagement (one form, used for both) has five tabs:

TabWhat it holds
Main DetailsEngagement Title, Program, Conglomerate, Branch, Currency, Status, Process Status, plus read-only Created/Updated Date and By in edit mode. The Branch drop-down on this tab is never populated, so its only option is – None –; set the branch on the Account tab instead.
AccountEntity Id (click to open Select Entity), a searchable Entity Branch drop-down, and read-only Status, Identity Type, Currency, Description, Entity Name, Entity Type, ID Number, Email, Phone Number copied from the chosen entity. Picking an entity stores the entity on the engagement; picking a branch stores the entity branch.
LinesOnly after the first save (“Save the engagement first before adding lines.”). A Line Listing (Title, Value, Process Status, Status, Created Date, Updated Date) with a Total Value footer that sums the listed values, a Month From / Month To filter that filters on the line’s created date, + to add a line, and row-click to edit. Edit Line Item has a Main tab and a Fiscal Period tab: a grid of the line’s fiscal-period rows (Txn Date, Fiscal Year, Fiscal Month, Fiscal Day, ARAP Open Balance, Target Billing, Target Adjustment, Target Collection, Actual Billing, Actual Collection, Remarks, Status) with its own Add / Edit / DELETE.
MemberOnly after the first save. Engagement members: Name, Email, Role, Status, Updated Date. Add Member takes an e-mail or phone number, Verify (exact match on an e-mail or mobile login of this tenant), a Rank / Role (OWNER, ADMIN, MANAGER, MEMBER, GUEST, VISITOR, ANONYMOUS; default MEMBER) and Status. Editing offers UPDATE and REMOVE.
ExportOnly after the first save. A Printable Format drop-down (preset from the PRINTABLE setting) and EXPORT AS PDF, which saves CFP_ENGAGEMENT_<guid>.pdf. The same action sits behind the PRINT PDF button in the title bar of the edit form.

The SAVE button is disabled while the form is invalid only in create mode; in edit mode it is always enabled and does not re-check validity.

Dashboard

Engagement Dashboard loads up to 5,000 engagements in one request, each with the sum and count of its lines and the sums of its fiscal-period figures, and then computes everything in the browser:

  • Filters — fiscal-year presets (This Year, Last Year, Last 3 Years, Last 5 Years), Engagement Title (matched against title or currency code), Process Status (multi), Currency (multi, from a fixed list of 13 ISO codes built into the screen, not from Forex), Fiscal Year From / To, Fiscal Month, Fiscal Day, Fiscal Txn Date From / To, Created From / To. When any fiscal filter is set, only engagements with at least one matching fiscal-period row are returned and the sums cover only those rows — and the screen opens with Fiscal Year From / To already set to the current year, so that narrowing is in force before you touch anything. No status filter is sent, so INACTIVE engagements are included.
  • KPI cards — Active Engagements (row count), Engagement Value (sum of line values), Target Billing, Target Collection, Actual Collection, Collection Rate, Billing Realization Rate, Pending Amount, AR/AP Open (sum of ARAP Open Balance). What each one is actually counting, and what it quietly leaves out, is in Where each report figure comes from.
  • Charts — top engagements by line value; collection rate by engagement; process-status distribution; actual collection by currency; highest actual collection; engagements with the most fiscal-period rows. Clicking a chart segment filters the table below it (a removable chip).
  • Table — Title, Currency, Status, Process Status, Lines, Target Collection, Actual Collection, Pending, Collection Rate, and a “View details” icon that only shows a toast. Export writes the table to CSV.

Reports

Cashflow Projection Report: search by Program Name, Engagement, Fiscal Year (a select of the current year ± 2, preset to the current year), Month From and Month To. One row per engagement, pinned Program and Engagement columns, then a Total for <year> group — Total Project Value, Project Balance, Target Billing, Adjustment, Adjusted Target Billing, Actual Billing, Target Collection, Actual Collection, Outstanding Amount — and one column group per month in the range with Open Bal, Target Billing, Adjustment, Adj. Target Billing, Actual Billing, Target Collection, Actual Collection and Remarks. Expanding a row loads a per-item detail grid. The formulas are in Where each report figure comes from.

Collection Delay Report: search by Program Name, Engagement, Fiscal Year, Month From and Month To. Columns Program, Engagement, Item, Year, Month, Target, Actual, Variance, Status — one row per fiscal-period row whose actual collection is below its target collection.

Configuration

Before you can use it

PrerequisiteWhere it is setWhy it matters
Customers / entitiesCustomer MaintenanceThe Account tab and the Program Item form select from the customer listing. Conglomerates come from the same master.
Entity branchesEntity MaintenanceEntity Branch drop-downs list the selected entity’s branches; without them the drop-down offers only – None –.
CurrenciesForexCurrency is required on an engagement; the list is the first 200 currencies of the tenant.
Tenant usersTenant AdminMembers are tenant logins; Verify fails with User not found for anyone who is not yet a user of the tenant.
Server-side permissionsSettings → Permission Wizard / Permission Set / User Permission / Role Permission in this appletEvery screen checks an API_TNT_DM_ERP_CFP_* code (table below). A user with none of them sees empty grids and Failed to load … toasts.
A .jrxml printable (optional)Settings → Printable Format SettingsNeeded only for PRINT PDF / EXPORT AS PDF.

Applet settings

The settings gear opens the shared settings shell, whose menu for this applet is: System Configuration — Application Settings, Default Selection, Printable Format Settings; Server Side Permissions — Permission Wizard, Permission Set, User Permission, Role Permission; Developer Tools — Release Notes. A handful of other settings screens inherited from the Sales Invoice applet (e-mail templates, webhooks, feature visibility, branch settings, workflow settings and others) have no menu entry and are reachable only by typing their address; they do nothing for this applet.

Application Settings is the shared field-configuration screen, not an applet-local one. In the build of this applet served on 2026-10-06 (published 2026-07-23), it shows the full Sales Invoice set of tabs — Gen Doc Listing, Main Details, Account, Line Items and the rest — and a CHANGE VIEW button that switches to one long vertical list of the same controls. Almost every control on it saves a key this applet never reads. It has no Hide Program or Hide Engagement switch: the applet reads those two keys (table below), but on this build they can be set only through the API. Only an OWNER or ADMIN can open it. SAVE writes the whole form as the applet’s master settings.

Dated note, 2026-10-06. The shared screen’s current source, which this applet picks up when it is next rebuilt, trims the view for this applet to three tabs — Sidebar Menu (with Hide Program and Hide Engagement), Advanced Search Filter and Free Gift — and hides CHANGE VIEW. One caution carries over: if anyone presses CHANGE VIEW on today’s build and saves, the tenant’s settings remember the vertical layout, and after the rebuild the screen opens in that full vertical list with no button to leave it. Press CHANGE VIEW back to the tab layout and save before then.

Settings that are declared, rendered, persisted and actually read by this applet:

SettingWhereWhat it controlsDefaultEffect when changed
Hide Program (HIDE_PROGRAM_MENU)The API only, on today’s build (Application Settings → Sidebar Menu after the next rebuild — see the dated note above)Removes Program from the sidebar.offThe menu item disappears on the next load. The screen still exists, and the applet still opens on it, so it remains reachable.
Hide Engagement (HIDE_ENGAGEMENT_MENU)As aboveRemoves Engagement from the sidebar.offAs above. The Dashboard and Report menus have no equivalent toggle.
Default printable format (PRINTABLE)Printable Format Settings → SET DEFAULTThe format pre-selected in the Export tab of every engagement form.noneThe Export tab’s drop-down and the PRINT PDF button use it until you pick another format on that screen.
Default Toggle Column (DEFAULT_TOGGLE_COLUMN, personal)Personalization → Default SelectionSINGLE or DOUBLE column layout for the Program and Engagement view stacks. Also rewritten every time you press the column toggle in a listing.noneBoth containers and both listings read it on load.
Enable Vertical Orientation (VERTICAL_ORIENTATION) with Default Tab Orientation (DEFAULT_ORIENTATION, personal)Application Settings → Gen Doc Listing → Vertical UI Setting; Personalization → Default SelectionA tenant-wide switch that hands the column layout to each user’s Default Tab Orientation.offWhen the switch is on, the Program and Engagement stacks open in two columns if your Default Tab Orientation is HORIZONTAL (or your Default Toggle Column is DOUBLE), and in one column otherwise. When it is off, Default Tab Orientation changes nothing and Default Toggle Column alone decides. On a phone-width screen neither is read.

Rendered on the same screens and persisted, but read by nothing in this applet (changing them does nothing here):

  • Application Settings: every control except Enable Vertical Orientation and the two search keys in the next table — including HIDE_TRANSACTION_DATE (no search in this applet has a transaction date). There is no audit-trail menu on today’s build. Dated note, 2026-10-06: the shared sidebar’s current source adds an Audit Trail entry for owners and administrators, which opens the platform’s shared audit-trail screen; after the next rebuild it will appear here too. The Sidebar Menu switch HIDE_AUDIT_TRAIL_MENU removes it for everyone who is not granted an audit-trail permission of their own.
  • Default Selection (master): Default Branch, Default Location, Default Pricing Scheme, Unit Price Decimal Precision, Transaction Date Logic and the “Details Tab Ordering” list are all fields of the sales-invoice screen this was built from. None of them affects a screen here.
  • Personalization → Default Selection: Default Branch, Default Location, Default Delivery Branch and Default Delivery Location. (Default Tab Orientation is read only while Enable Vertical Orientation is on — table above.)

Read at runtime without a control of their own — this applet passes its settings into the shared advanced search on the Program and Engagement listings and both reports, which honours them:

KeyWhereEffect here
HIDE_CREATED_DATEApplication Settings → Advanced Search FilterHides the Created Date filter on the Program and Engagement listings.
HIDE_UPDATED_DATEApplication Settings → Advanced Search FilterHides the Updated Date filter on the Program listing.

Printable Format Settings lists the tenant’s printable formats registered under the Sales Invoice document type (Default, Format Code, Format Name, File Name, File Size, Created Date, Updated Date, Updated By). + uploads a new format (Format Code, Format Name, one .jrxml file — the button stays disabled for any other extension) and SET DEFAULT stores the selected row as PRINTABLE. The document type is fixed, so the formats you see here are the tenant’s Sales Invoice printable formats, and a CFP engagement template must be registered under that type even though the parameters it receives (the engagement’s title, currency, status, process status, program, entity, entity branch, conglomerate, created and updated dates, and per line its title, value, process status and status) are nothing like an invoice’s.

Settings in other applets that control this applet

None found. The applet reads no financial configuration, no default GL mapping, no document numbering and no tax code.

Who can change what

There are no client-side permission codes defined for this applet, so the Applet Access screen has nothing to grant; a request to create them is open. The applet still asks for the Sales Invoice codes it inherited, but the menu entries they would show (Pick Pack Queue, File Import, Approval and the like) do not exist in this applet, so granting them changes nothing.

Server-side gates (one family per record type, each with OWNER, ADMIN, CREATE, READ, UPDATE, DELETE):

AreaPermission familyNotes
ProgramAPI_TNT_DM_ERP_CFP_PROGRAM_HDR_*
Program memberAPI_TNT_DM_ERP_CFP_PROGRAM_MEMBER_*
EngagementAPI_TNT_DM_ERP_CFP_ENGAGEMENT_HDR_*READ also gates PDF export and the dashboard.
Engagement lineAPI_TNT_DM_ERP_CFP_ENGAGEMENT_LINE_*
Engagement memberAPI_TNT_DM_ERP_CFP_ENGAGEMENT_MEMBER_*
Program itemAPI_TNT_DM_ERP_CFP_ENGAGEMENT_FI_ITEM_HDR_*
Fiscal period rowAPI_TNT_DM_ERP_CFP_FP_ENG_LINE_LINK_*READ gates both reports.
Fiscal period audit trailAPI_TNT_DM_ERP_CFP_FP_ENG_LINE_LINK_AUDIT_TRAIL_*Nothing in the product writes or reads the audit trail.

Portal (customer-login) users have a separate read path gated by their login-to-entity link rather than a permission code. The applet’s screens do not use it.

Fields

Validation happens on the screen; the server validates none of the business fields (see What the backend actually validates).

Taken together the seven forms capture this, and nothing else. Program — Main Details: Program Code, Program Name, Description, Status, plus read-only Created/Updated Date and By in edit mode. Program — Member: an e-mail or phone number to verify, Rank, Status. Program — Program Item: Item Code, Item Name, Item Type, Currency, Entity, Entity Branch, Sales Entity, External PIC 01, External PIC 02, Remark, Status. Engagement — Main Details: Engagement Title, Program, Conglomerate, Branch, Currency, Status, Process Status. Engagement — Account: Entity Id and Entity Branch are the only two controls that write; Status, Identity Type, Currency, Description, Entity Name, Entity Type, ID Number, Email and Phone Number are read-only copies of the chosen entity, and the engagement’s own form does not require an entity, so an engagement saves without one. Engagement — Line: Title, Value, Process Status, Status. Engagement — Fiscal Period: Fiscal Year, Fiscal Month, Fiscal Day, Txn Date, ARAP Open Balance, Target Billing, Target Adjustment, Target Collection, Actual Billing, Actual Collection, Remarks, Status. Engagement — Member: an e-mail or phone number to verify, Rank / Role, Status.

Status defaults to ACTIVE on every form, Item Type to SERVICE and Member Rank / Role to MEMBER. Everything below is the part of those forms that behaves in a way the screen does not show.

Program and Program Item

FieldWhat it does that the screen does not show
Program CodeThe duplicate check runs on the one screen a duplicate cannot arrive by. Edit Program checks the code as you type, shows “This code already exists. Saving will fail.” and disables SAVE — and that message is wrong: the server has no uniqueness rule for program codes, so the save would have succeeded. Create Program runs no check at all. So a duplicate created on the Create screen is accepted in silence, and the two programs then appear under the same name on the projection report, which orders by program name.
Item CodeNo uniqueness check on the screen or the server. The Cashflow Projection Report’s detail grid is ordered by item code, so duplicates interleave silently.
Sales EntityNo projection, report or posting behaviour keys off it — but it is not inert: the form re-fetches the entity to re-display its name and the item listing can filter on it.
Rank (program member)ADMIN, CONTRIBUTOR, VIEWER. The server accepts any value, offers no filter on it, and nothing in the applet or the server grants or denies anything by it. It is a label you keep for yourself. Server-side permissions are the only real gate — see Who can change what.

Engagement, line and fiscal period

FieldWhat it does that the screen does not show
Branch (Main Details)Never populated, so the only option is – None –. The Account tab’s Entity Branch drop-down writes the same value; use that one.
Process StatusPENDING_REVIEW, APPROVED, DUPLICATE, REJECTED or none. On the engagement header only those four values (or blank) are accepted — anything else sent through the API is rejected. On the line the same four labels are stored as plain text. It is a label, not a workflow: nothing locks a record after “Approved”.
Status (engagement)The Engagement menu shows only ACTIVE engagements and offers no status filter, so setting an engagement INACTIVE removes it from that menu — but not from its program’s Engagement tab, not from the dashboard and not from either report, all of which exclude only deleted rows. “Inactive” here hides a row from one screen and from nothing else.
Value (line)Summed in three places at three different scopes: as Total Value on the Lines tab (the at-most-200 lines that tab fetched), as Engagement Value on the dashboard (every line of the engagement, ignoring the dashboard’s fiscal filter) and as Total Project Value on the projection report (every line, ignoring the report’s year and month). None of the three is a figure for the period you are looking at.
Fiscal Year / Fiscal MonthBoth required on the form; neither is range-checked anywhere, on the screen or on the server. A row keyed to month 13 is stored, is summed into the projection report’s year total, and has no column in the grid — which is the commonest reason a year total does not equal the months across from it. See Where each report figure comes from.
Actual Billing / Actual CollectionTyped in by hand, and never reconciled: no invoice, receipt or ledger balance feeds or checks either of them, and no warning fires when actual billing exceeds the line’s own Value. Two people entering the same month’s figures from different spreadsheets is the ordinary failure here, and the applet cannot detect it.
Status (fiscal period)The dashboard and both reports exclude only deleted rows. Setting a fiscal-period row INACTIVE therefore changes no reported figure. To take a row out of the numbers you must delete it — on the fiscal-period row itself, not on its line (see Relationships and deletes).
Rank / Role (engagement member)OWNER, ADMIN, MANAGER, MEMBER, GUEST, VISITOR, ANONYMOUS, default MEMBER; free text on the server, and it grants nothing. It is read: the member listing filters and keyword-searches on it, and the Collection Delay Report’s project-manager filter looks for the exact role Project Manager — which this drop-down cannot produce.

Two editors replace the whole row; the other three do not

There is no partial update in this register. Every save replaces every field of the record with what the screen sent; the server fills in only the two dates and never reads the stored record first. A field your screen did not send is written blank.

Three of the five editors send the whole record and are safe: the engagement form and the program form both start from the loaded record before applying the form values, and the Program Item form happens to carry a control for every one of its fields.

The other two rebuild the record from the form and patch the audit fields back on:

EditorWhat it sendsWhat is written blank
Edit Line Item → SAVEengagement, title, value, process status, status, plus the audit fieldsThe line’s link to a Program Item — the link that both reports depend on.
Edit Fiscal Period → SAVEthe twelve business fields the form shows, plus the audit fieldsThe recurring-period grouping fields.

The line case is the one that bites, because it silently undoes the only workaround there is. No screen in any applet sets the line-to-Program-Item link, so the only way to link a line to a Program Item — and the only way to make the Collection Delay Report or the projection report’s detail grid return anything — is through the API. Open that line in the UI afterwards, change nothing, press SAVE, and the link is gone again, under a “Line item updated successfully.” toast.

The fiscal-period case costs nothing today, because nothing writes the recurring-period fields either. They are not dead, though: the fiscal-period listing can filter on them and returns them. If an integration ever starts grouping recurring periods, a single screen edit will unpick the chain — how one-time versus recurring periods are meant to be expressed is still an open question.

Lifecycle and effects

Posting proof

AspectValue
Server document typeNone. Nothing in this register is a server document type, and no journal posting handler knows it.
Amount signumNot applicable — no financial-document validation exists for these records. The validation that does run checks structure only (identity, revision, status, audit users, dates).
Quantity signumNot applicable — no stock processor references this register.
Dr/Cr equationNone. Nothing in the journal, stock-balance, stock-processor or generic-document code refers to this register.
GL precedenceNot applicable. No GL code is stored on any of its records.
Stock processorNone.
What VOID reversesThere is no VOID and no FINAL. Every write is a plain insert or update, and DELETE is a status change: the row stays in the database with status DELETED, and every screen and report leaves it out.

Everything the dashboard and reports show is therefore an arithmetic view of what users typed into the fiscal-period rows. Actual billing and actual collection are not reconciled against Sales Invoices or Receipt Vouchers.

Nothing is queued, so nothing happens afterwards

Most applets in BigLedger separate saving from finalising: the second starts a background run that fans out into stock, journals, the cashbook and more. This applet has none of that, and the absence is worth stating precisely because it is the reason the figures never move on their own:

  • Shipped — there is no background job for this register anywhere in the product.
  • Registered — nothing for this register appears in the Scheduler applet’s processor picker.
  • Scheduled — nothing to schedule; there is no scheduled recalculation, roll-forward or reminder.
  • Run — nothing runs. Every number on the dashboard and both reports is computed by the request that asked for it, from rows a person typed.

So there is no overnight job that will fix a figure you entered wrongly, no roll-forward that carries December’s closing balance into January’s ARAP Open Balance, and no alert when actual collection falls behind target. The Collection Delay Report is the only thing that will ever tell you, and only when somebody opens it.

Statuses

Every record has a Status (ACTIVE / INACTIVE from the screens; the server default is ACTIVE). A third value, DELETED, is what every delete writes; listings, the dashboard and both reports skip those rows, and an API query sees them only when it asks for that status by name. Engagement headers and lines also carry a Process Status label with four values (PENDING_REVIEW, APPROVED, DUPLICATE, REJECTED). There are no transitions: any value can be set at any time, nothing locks a record after “Approved”, and no notification, workflow or approval step is attached (the Workflow Settings screen in the settings area is inherited from the Sales Invoice applet and has no menu entry).

Relationships and deletes

  • Engagement → Program, Line → Engagement, Fiscal Period → Line and Engagement, Member → Program or Engagement, Program Item → Program are enforced relationships.
  • DELETE buttons (program item, program member, engagement line, fiscal period, engagement member) do not remove the row: they set its status to DELETED. Nothing is checked first, so a row that others still point at is deleted all the same, and its children are left as they were. That matters most for an engagement line. Its fiscal-period rows stay ACTIVE and keep counting in the Cashflow Projection Report’s monthly and year figures, in the dashboard’s billing and collection totals and in the Collection Delay Report — while the line’s own Value drops out of Total Project Value and Engagement Value, and the rows can no longer be opened, because the Fiscal Period tab is reached only through the line. Delete a line’s fiscal-period rows first, then the line. If the line is already gone, the leftover rows can be deleted only through the API (the fiscal-period endpoint, by row).
  • Failed to delete … therefore never means “still referenced”. It appears when the row was already deleted (for example by someone else, in another tab) or when you lack the delete permission for that record type.
  • Programs and engagements have no delete button anywhere in the UI; set them INACTIVE instead. The API can delete them the same way — a status change that leaves their engagements, lines and fiscal-period rows untouched.
  • The fiscal-period audit trail exists as a record type with its own API, but nothing in the product writes to it and no screen reads it. It stays empty unless something outside the product writes it.

What the backend actually validates

On create and update the server checks that the record identity is new (create) or exists (update), that the revision and status are set, that the creating and updating users are real logins, and that the dates are present; on create it fills the dates, defaults Status to ACTIVE and generates a revision. No relationship, code uniqueness, month range, currency existence or role value is checked on the server; the only “duplicate” errors it knows are duplicate identities. A bad reference surfaces as a database error, which the screens show as a generic Failed to create/update … toast.

Where each report figure comes from

Nothing here is stored. Every figure on the dashboard and on both reports is recomputed by the request that asked for it, from the fiscal-period rows and engagement lines as they stand at that moment. All three exclude only deleted rows — so in practice they include everything, INACTIVE rows included.

The one thing to know before reading any of the three: each of them mixes figures scoped to the period you chose with figures scoped to all time, in the same row, with no visual difference between them. Three columns are lifetime figures wearing a period heading.

Cashflow Projection Report

ColumnWhere the number comes from
Every monthly column — Open Bal, Target Billing, Adjustment, Actual Billing, Target Collection, Actual CollectionThe sum over the engagement’s fiscal-period rows for that month in the chosen year, across all its lines. Two lines with a March row are added together.
Monthly Adj. Target BillingTarget Billing + Target Adjustment, summed — a blank is a zero, not a gap.
Monthly RemarksAlways blank. The summary does not carry remarks; only the detail grid does.
Monthly Outstanding AmountTarget Collection − Actual Collection, summed. Computed but not given a monthly column, so you only ever see it as a year total.
Total for <year> — the seven billing and collection columnsThe monthly figures summed again — over the months you filtered to, not over the year. With Month From 3 and Month To 6 the group headed Total for 2026 is the total for March to June. The heading does not say so.
Total Project ValueThe sum of the engagement’s line values with no year and no month filter at all. It is the same number in every year’s report.
Project BalanceYear target collection − year actual collection — the identical number to Outstanding Amount, and nothing to do with Total Project Value beside it. A project whose value is RM 400,000 and which has collected everything planned this year shows Project Balance 0, not 400,000.

Two consequences worth having in mind:

  • Engagements with nothing in the chosen year still appear, as a full row of zeros with their lifetime Total Project Value filled in. The year filter narrows the fiscal-period figures, not the engagement list, which is filtered only by “not deleted” and the Program / Engagement name search.
  • A year total can exceed the months shown. Nothing validates the fiscal month into 1–12, and on first load the screen sends no month range at all — the grid builds columns for 1 to 12 from its own defaults while the query sums every month value present. A row keyed to month 0 or 13 lands in the year total with no column to sit under. The expand-row detail grid always sends the 1–12 range, so the detail will not add up to the summary either.

Rows are engagements joined to their program, ordered by program name then title, twenty per page — an engagement saved with Program = – None – is not listed at all. The status bar’s record count is not a count: the screen reports “rows fetched, plus one if a full page came back”. Use All (which asks for 9,999) if you need the real extent.

The detail grid lists one row per engagement line that is linked to a Program Item, with the line’s value as Project Value. Because no screen writes that link (see Two editors replace the whole row), expanding a row on a UI-built engagement returns nothing.

Collection Delay Report

One row per fiscal-period row where actual collection is below target collection, for lines that are linked to a Program Item and engagements that belong to a program. Variance is actual − target, negative by construction. The same Program Item requirement means this report can only ever be empty for rows the UI created.

It also carries a project-manager filter that the UI does not expose, which matches engagement members whose role is exactly Project Manager — a value the Rank drop-down cannot produce. If an API caller ever does set that role on two members of one engagement, every qualifying fiscal-period row is listed twice.

Engagement Dashboard

The dashboard asks for one page of up to 5,000 engagements and computes everything in the browser. Three things about those numbers are invisible on the screen:

  • It opens filtered to the current year. Fiscal Year From / To start at this year, which the server treats as a fiscal filter and therefore returns only engagements that have at least one matching fiscal-period row. An engagement with no row for this year is not counted at all — including in the Active Engagements card, which is simply the number of rows returned.
  • Engagement Value and Lines ignore that filter. The line totals are never constrained by the fiscal window, so the value and line count are lifetime figures sitting beside windowed collection figures.
  • The money cards add currencies together. The cards sum target billing, target collection, actual collection and ARAP open balance straight across every row with no grouping. On a tenant with MYR and USD engagements the Engagement Value, Target Collection and Pending Amount cards are numbers with no currency. The Currency filter is the only way to make them mean anything, and it is a fixed list of 13 ISO codes built into the screen rather than the tenant’s Forex list.

Collection Rate is actual ÷ target collection × 100 and Pending Amount is max(0, target − actual collection), so an engagement that over-collected does not net off against one that under-collected. Billing Realization Rate divides actual collection by target billing — two different quantities — so it is a cash-conversion ratio, not a billing accuracy one, whatever the name suggests.

Related applets

  • Customer Maintenance — the customer listing behind every Select Entity column, and the conglomerate master behind the Conglomerate drop-down.
  • Entity Maintenance — where an entity’s branches are maintained; both Entity Branch drop-downs read them.
  • Forex — the currency list on engagements and program items.
  • Tenant Admin — the tenant users that program and engagement members are resolved from.

Troubleshooting

SymptomCauseFix
Collection Delay Report is empty although fiscal-period rows have actual below targetThe report lists only lines that are linked to a Program Item, and no screen in any applet ever sets that link.Set the line’s Program Item link through the API. Then do not open that line in the UI again: Edit Line Item rebuilds the row from its four form controls, so pressing SAVE clears the link again under a success toast — see Two editors replace the whole row.
Expanding an engagement on the Cashflow Projection Report shows no detail rowsSame cause: the detail lists only lines linked to a program item. The summary row still shows the totals.As above.
A row’s Total for <year> does not equal its month columns added upTwo different causes, both invisible. If you set Month From / Month To, the year group is the total of those months only — the heading still names the year. If you did not, the query sums every fiscal month present, including values outside 1–12 that the grid has no column for, because nothing validates the month on entry or on save.Check the line’s Fiscal Period tab for a row with an impossible month and correct it. To reconcile deliberately, set Month From 1 and Month To 12 — that clamps the query to months the grid can show.
Total Project Value looks far too large, or Project Balance does not equal it minus what was collectedTotal Project Value is the sum of every line of the engagement with no year or month filter at all, so it repeats unchanged in every year’s report. Project Balance is a different quantity entirely — year target collection minus year actual collection, the same number as Outstanding Amount.Read Total Project Value as the lifetime contract value and Project Balance as this period’s collection shortfall. There is no column for “value still to bill”.
The dashboard shows fewer engagements than the Engagement listingThe dashboard opens with Fiscal Year From / To preset to the current year, and any fiscal filter restricts the result to engagements that have at least one fiscal-period row in that window. An engagement with no row for this year is absent from the count, the KPIs, the charts and the table.Clear both Fiscal Year fields and apply, which drops the fiscal filter and returns every engagement.
A KPI card’s total makes no sense for any one currencyThe money cards sum every returned row with no currency grouping, so a tenant with MYR and USD engagements gets a number that is neither.Set the Currency filter to one code before reading the money cards. Note the filter is a fixed list of 13 ISO codes, not the tenant’s currency list.
An engagement is missing from the Cashflow Projection ReportThe report lists only engagements that belong to a program; an engagement saved with Program = – None – is skipped.Set the Program on the engagement’s Main Details tab.
Engagement vanished from the Engagement menuThe Engagement listing shows only ACTIVE engagements and offers no status filter, so an engagement set to INACTIVE disappears from that menu.Open the parent program → Engagement tab, which lists engagements of any status, or set it back to ACTIVE.
The Branch drop-down on Main Details only offers – None –The list is never loaded on that tab.Pick the entity on the Account tab; its Entity Branch drop-down is the one that works and writes the same value.
Two programs with the same Program CodeCreate Program runs no check before saving, and the server has no uniqueness rule; only Edit Program checks the code and disables SAVE — on the screen a duplicate cannot arrive by. Both screens would show Program code “…” already exists if the server ever refused a duplicate code; it never does, so that message is not a safety net.Search the listing before creating. To rename one of them, note that Edit Program will block the save if the new code collides.
“Failed to delete line item.” / “Failed to delete item.” / “Failed to delete member.” / “Failed to delete fiscal period.”Not a reference check — deletes check none. Either the row was already deleted (someone else, or another tab, got there first) or you lack that record type’s delete permission.Reload the listing; if the row is gone, nothing more is needed. Otherwise ask for the …_DELETE permission of that record type (table in Who can change what).
A line was deleted but its months still show on the projection report, the dashboard or the Collection Delay ReportDeleting a line leaves its fiscal-period rows in place, and the reports read the fiscal-period rows directly.Delete the fiscal-period rows before the line. For a line already deleted, delete its fiscal-period rows through the API, or ask support.
“User not found for the given email or phone number.” / “User not found in this tenant.”Verify matches the login exactly (e-mail, case-insensitive) against this tenant’s users. The person is not yet a tenant user, or typed a different alias.Add the user in Tenant Admin first, then verify again with the login e-mail.
Lines tab Month From / Month To hides lines that clearly belong to that monthThe filter is applied to the line’s created date, not to the fiscal periods under it.Clear the filter, or use the Cashflow Projection Report with a month range.
“Search keyword must more than 2 characters.”The Program and Engagement listings reject free-text keywords shorter than three characters.Type at least three characters, or use the advanced search fields.
Dashboard “Active Engagements” counts inactive onesThe dashboard sends no status filter, so every engagement not deleted is returned.Set the process status or currency filters to narrow the set; there is no status filter on the dashboard.
Dashboard currency filter lacks the tenant’s currencyThe Currency filter is a fixed list of 13 codes built into the screen, not the Forex list.Leave the filter empty; the KPI and charts still group by whatever currency codes the engagements carry.
No PDF from EXPORT AS PDF / PRINT PDFThe button is disabled until a Printable Format is selected, and the list only contains formats registered under the Sales Invoice document type. A template built with invoice fields renders blank sections because the CFP print supplies different parameters.Upload a .jrxml built for the CFP parameters under Printable Format Settings, press SET DEFAULT, then export.
Only Program and Engagement can be hidden from the sidebarOnly HIDE_PROGRAM_MENU and HIDE_ENGAGEMENT_MENU exist; the Dashboard and reports have no toggle.Use server-side permissions (API_TNT_DM_ERP_CFP_FP_ENG_LINE_LINK_READ for the reports, …_ENGAGEMENT_HDR_READ for the dashboard) to deny access instead.
Engagement listing feels slow and the browser console fills with [EngagementListing] DEBUG …Leftover debug code fetches every engagement unpaged on grid init and logs each query and response.Nothing to configure; it is in the shipped code.
No column view on the Program / Engagement sub-screensThe Member, Lines and Item tabs render inline rather than in the three-column stack.Known limitation.

Related documentation

Last updated on