Skip to main content
Checked against the product · 2026-10-05

Income Statement — User Guide

Income Statement — monthly P&L blending closed-month actuals with the forward forecast

The Income Statement is the first tab of the Financial Statements page. It shows your consolidated Profit & Loss — revenue, direct costs, indirect costs, and net income — blending closed-month actuals with the platform's forward forecast in a single view. It is a read-only view: you do not edit P&L line items here (they are computed upstream), but you control how the numbers are grouped and displayed.

Who uses it: CEO, COO, and CFO. It is the primary financial view for the leadership team.

Finding it​

In the left navigation, open Financial Intelligence → Financial Statements. The page opens on the Income Statement tab. Along the top you will also see the other statement tabs — Balance Sheet, Cash Flow, EBITDA, Covenants, Debt Schedule, Indirect Rates, and Intangibles (plus Close Review for CEO/CFO/Admin roles).

Reading the statement​

The statement is a table: the Account column on the left, then one column per period. Rows are grouped into sections (Revenue, Direct Costs, the indirect pools, and the net-income subtotals), with section headers and subtotals shown in bold.

  • Actuals vs. forecast is shown visually. Months that fall on or after the first forecast month are lightly shaded, and a teal line marks the boundary where closed actuals end and the forecast begins. Everything to the left of that line is real, closed-book data from your ERP; everything to the right is the platform's forecast.
  • Section totals drill to their accounts. Any bucket row with accounts behind it — Total Revenue, Total Direct Costs, a pool subtotal, a section header — is underlined. Click it to see every GL account that rolls into that line. A line that nothing posts to in the selected year is left unclickable on purpose, rather than opening an empty drawer.
  • EBITDA rows open the Bridge instead. The EBITDA subtotals have their own view: click one for the EBITDA Bridge drawer, which walks net income up to reported and adjusted EBITDA. They do not open the account list, because the question an EBITDA line raises is answered by a bridge rather than by a list of accounts.
  • "Jump to:" links appear above the table (when there is more than one section) so you can jump straight to Revenue, a specific indirect pool, or the net-income lines.

Drilling into a line​

Click any underlined line to open a drawer titled with that line's name, listing the GL accounts that roll into it. Each account shows its code and name, one column per month, and a full-year total. The accounts in the drawer sum to the line you clicked — that is what makes it a drill rather than a related view.

It works in Summary mode as well, which is where you are most likely to want it: collapse the statement to its buckets, then open the one that looks wrong.

Reading the drawer, and where a wrong number is actually fixed — this is the part worth knowing before you go looking:

  • Unshaded months are actuals, booked to the general ledger. A figure that is wrong here is wrong in the ledger, and that is where it gets corrected.
  • Shaded months are forecast, produced from that account's own forecast method. Each one is replaced by the booked figure when the month closes. To change one, edit the account's method in Forecast Inputs — the statement is derived, not typed, so there is nothing to edit on this page.
  • Total is the full year, actual months plus forecast months. It is not year-to-date, so do not read it as money already spent.
  • An account that does not belong on the line is mapped to that section in your chart of accounts. The fix belongs there, not on the statement.

If the drawer says no accounts post to this line in the selected year, that is a real answer about the year you are looking at, not an error — try another year.

Controls​

The control bar above the statement lets you reshape the view:

  • Monthly / Annual — switch between a 12-month (Jan–Dec) layout for one year and a multi-year column layout. The year range in Annual view is derived automatically from your data (earliest actual through your planning horizon).
  • $ / $000s — toggle between full dollars and thousands.
  • Summary — collapse the statement to just its bucket rows (Revenue, Direct Cost, Gross Profit, Fringe, Facilities, Material Handling, Overhead, G&A, Total Indirect, and the net-income lines).
  • Hide $0 rows — hide any account whose values are all zero. On by default.
  • Year — pick the fiscal year to show (Monthly view).
  • Export — download the statement to Excel.

Where the revenue and costs come from​

The forecast side of the Income Statement is assembled from a few upstream sources, so the numbers you see always tie back to work done elsewhere in the platform:

  1. Contract forecasts — revenue and direct costs from existing contracts, entered by Division Leads on the Forecast module.
  2. New-business / growth targets — revenue from anticipated new awards, set by the CEO on the Pipeline / BD page and spread into monthly amounts.
  3. Indirect forecasts — fringe, overhead, and G&A, computed from your indirect-rate configuration.

Depreciation & amortization flows in from the balance-sheet intangible schedule, and the CEO can layer one-off manual overrides on top. The closed-month side comes entirely from your ERP General Ledger. That ERP can be an external accounting system, or Arcvue Accounting itself: if you keep your books in Arcvue's own accounting product, it is a selectable ERP source that needs no separate connection to set up, and your closed-month actuals flow in from there. Either way the actuals refresh on the regular sync.

The boundary between the two is the books close date: months at or before the close show actuals; months after show forecast. Closing a month in Bookkeeping moves that line automatically.

When the statement cannot load​

These statements could not be loaded means the request did not complete, so the page makes no claim about your results; reload the page. In the Annual layout, Annual data could not be loaded is the same failure for the multi-year view, while No annual data means the request worked and no multi-year statements have been generated for those years yet.

  • Balance Sheet, Cash Flow, Covenants — the other tabs of this page (see the Financial Statements guide).
  • Indirect Rates — the read-only tab on this page showing your fringe, overhead and G&A rates per fiscal year, alongside the target tiles. It reports the rates; it does not configure them.
  • Forecast and Pipeline / BD — where contract and new-business revenue originate.
  • Scenario Planning — applies what-if overlays without touching the base forecast.

Technical reference​

Data model, GL account structure, and example SQL (for developers and power users)

All P&L data originates from three upstream sources that flow into two core tables. Revenue on the Income Statement is the sum of three sources in pl_forecasts, tagged by a source field:

  1. Contract Forecasts (source = 'contract_forecast') — Revenue and direct costs from existing contracts. Division Leads enter monthly forecasts on the Forecast Module page. forecast_rollup.py maps these to GL account codes and writes to pl_forecasts.
  2. New Business / Growth Targets (source = 'new_business') — Revenue from anticipated new awards not yet in the pipeline as contracts. CEO sets annual growth targets by division on the Pipeline/BD page. The system splits revenue into monthly amounts and allocates COGS across 7 GL accounts using historical actuals mix.
  3. Indirect Forecasts (source = 'indirect_forecast') — All indirect costs: fringe benefits (61–64.xx), overhead (71–76.xx), G&A/BD/B&P (81–86.xx), and other (92.xx). Computed by indirect_forecast_engine.py using 12 different forecast methods configured per GL account.

Additionally:

  • D&A Schedule (source = 'da_schedule') — Depreciation & amortization from the balance sheet intangible schedule. These accounts are excluded from the indirect engine to prevent double-counting.
  • Manual Overrides (source = 'manual_override') — One-off adjustments entered by the CEO.

The Actuals vs. Forecast Boundary​

The boundary between historical actuals and forecast data is controlled by the books close date stored in entity_close_dates. For example, if books are closed through December 2025:

  • FY2025 and earlier: Data comes from pl_actuals (ERP GL imports)
  • FY2026 and later: Data comes from pl_forecasts (computed by the platform)

The Income Statement merges both tables seamlessly. Months before the close date show actuals; months after show forecast.

Key Tables​

pl_actuals​

Historical actuals imported from your ERP General Ledger via nightly sync.

ColumnTypeDescription
entityTEXTAlways 'CONSOLIDATED' for standard queries
fiscal_yearINTEGERe.g., 2024, 2025
fiscal_monthINTEGER1–12
account_codeTEXTGL account code, e.g., '41.11.11', '51.11.11'
amountREALRevenue is POSITIVE, expenses are NEGATIVE
scenarioTEXT'actual' for real data, 'budget' for ERP budgets

Important notes:

  • Always filter entity = 'CONSOLIDATED' and scenario = 'actual' for real financial data
  • Amounts follow accounting sign convention: revenue positive, costs negative
  • Never filter by project status — closed projects contributed revenue during active periods
  • Data is imported during the nightly scheduled sync

pl_forecasts​

All forecasted amounts — contract revenue, direct costs, indirect costs, new business, D&A, and manual overrides.

ColumnTypeDescription
entityTEXTAlways 'CONSOLIDATED' — any module writing here MUST use this value
fiscal_yearINTEGERe.g., 2026, 2027, 2028, 2029, 2030
fiscal_monthINTEGER1–12
account_codeTEXTGL account code, e.g., '41.11.11', '71.11.11'
amountREALSame sign convention: revenue positive, expenses negative
sourceTEXTOrigin tag — see values below
source_detailTEXTAdditional detail (e.g., contract name, division)

Source values in pl_forecasts:

  • 'contract_forecast' — Existing contract revenue and direct costs
  • 'indirect_forecast' — Fringe, overhead, G&A computed by indirect engine
  • 'new_business' — Growth target revenue and allocated COGS
  • 'da_schedule' — Depreciation & amortization from BS schedule
  • 'manual_override' — CEO one-off adjustments

pl_line_items​

Lookup table mapping GL account codes to human-readable descriptions and display hierarchy.

ColumnTypeDescription
account_codeTEXTGL account code (primary key)
descriptionTEXTHuman-readable name, e.g., 'Non-SCA Direct Labor'
parent_codeTEXTParent in the hierarchy for subtotals
sort_orderINTEGERDisplay ordering on Income Statement
tierTEXTGrouping tier for the indirect forecast config

entity_close_dates​

The authoritative source for the books close date — the boundary between actuals and forecast.

ColumnTypeDescription
entityTEXTUse 'ALL' for the company-wide close date
accounting_close_dateTEXTDate string, e.g., '2025-12-31'
close_fiscal_yearINTEGERe.g., 2025
close_fiscal_monthINTEGERe.g., 12

Query the close date:

SELECT accounting_close_date, close_fiscal_year, close_fiscal_month
FROM entity_close_dates
WHERE entity = 'ALL';

GL Account Code Structure​

The platform uses a hierarchical GL account code system: XX.YY.ZZ

RangeCategoryExamples
4x.xx.xxRevenue41.11.11 = Non-SCA Revenue, 42.11.11 = SCA Revenue
51.xx.xxNon-SCA Direct Labor51.11.11 = Non-SCA DL
52.xx.xxSCA Direct Labor52.11.11 = SCA DL
53.xx.xxSubcontractors / Consultants53.11.11 = Subs/Consultants
54.xx.xxTravel54.11.11 = Travel
55.xx.xxMaterials / Supplies55.11.11 = Materials
56.xx.xxOther Direct Costs56.11.11 = Other DC
61–62.xxNon-SCA Fringe Benefits61.11.11 = FICA, 61.21.11 = Health Insurance
63–64.xxSCA Fringe Benefits63.11.11 = SCA FICA, 63.21.11 = SCA H&W
66.xx.xxFacility Costs66.11.11 = Rent, 66.21.11 = Utilities
71–76.xxOverhead71.11.11 = OH Labor, 71.51.11 = OH Awards
81–86.xxG&A / B&P / BD81.11.11 = G&A Labor, 82.11.11 = B&P, 83.11.11 = BD
92.xx.xxOther Income / Unallowables92.11.11 = Interest Income, 92.31.44 = Interest Expense

Key groupings for indirect cost analysis:

  • Fringe (non-SCA): account_code LIKE '61%' OR account_code LIKE '62%'
  • Fringe (SCA): account_code LIKE '63%' OR account_code LIKE '64%'
  • All Fringe: account_code LIKE '6%'
  • Overhead: account_code LIKE '7%'
  • G&A / B&P / BD: account_code LIKE '8%'
  • Other / Unallowables: account_code LIKE '9%'
  • All indirect costs: account_code LIKE '6%' OR '7%' OR '8%' OR '9%'
  • Revenue: account_code LIKE '4%'
  • Direct costs: account_code LIKE '5%'

Common Queries​

Get all tables in this SQLite database​

SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;

Note: This is a SQLite database. Do NOT use MySQL syntax like SHOW TABLES or information_schema.columns. Use sqlite_master and PRAGMA commands.

Get columns for any table​

PRAGMA table_info(pl_forecasts);

Get FY2026 revenue by month​

SELECT fiscal_month, SUM(amount) as revenue
FROM pl_forecasts
WHERE entity = 'CONSOLIDATED'
AND fiscal_year = 2026
AND account_code LIKE '4%'
GROUP BY fiscal_month
ORDER BY fiscal_month;

Get FY2026 indirect costs by account, sorted by largest​

SELECT f.account_code,
COALESCE(p.description, f.account_code) as description,
SUM(f.amount) as annual_total
FROM pl_forecasts f
LEFT JOIN pl_line_items p ON f.account_code = p.account_code
WHERE f.entity = 'CONSOLIDATED'
AND f.fiscal_year = 2026
AND (f.account_code LIKE '6%' OR f.account_code LIKE '7%'
OR f.account_code LIKE '8%' OR f.account_code LIKE '9%')
GROUP BY f.account_code
ORDER BY ABS(SUM(f.amount)) DESC;

Compare FY2025 actuals to FY2026 forecast for indirect costs​

SELECT COALESCE(a.account_code, f.account_code) as account_code,
p.description,
a.actual_total as fy2025_actual,
f.forecast_total as fy2026_forecast,
ROUND(f.forecast_total - COALESCE(a.actual_total, 0), 2) as variance
FROM (
SELECT account_code, SUM(amount) as actual_total
FROM pl_actuals
WHERE fiscal_year = 2025 AND scenario = 'actual' AND entity = 'CONSOLIDATED'
AND (account_code LIKE '6%' OR account_code LIKE '7%'
OR account_code LIKE '8%' OR account_code LIKE '9%')
GROUP BY account_code
) a
LEFT JOIN (
SELECT account_code, SUM(amount) as forecast_total
FROM pl_forecasts
WHERE fiscal_year = 2026 AND entity = 'CONSOLIDATED'
AND (account_code LIKE '6%' OR account_code LIKE '7%'
OR account_code LIKE '8%' OR account_code LIKE '9%')
GROUP BY account_code
) f ON a.account_code = f.account_code
LEFT JOIN pl_line_items p ON COALESCE(a.account_code, f.account_code) = p.account_code
ORDER BY ABS(COALESCE(f.forecast_total, 0)) DESC;

Get full P&L summary for a fiscal year (actuals or forecast)​

-- For actuals year (e.g., 2025):
SELECT
CASE
WHEN account_code LIKE '4%' THEN 'Revenue'
WHEN account_code LIKE '5%' THEN 'Direct Costs'
WHEN account_code LIKE '6%' THEN 'Fringe Benefits'
WHEN account_code LIKE '7%' THEN 'Overhead'
WHEN account_code LIKE '8%' THEN 'G&A / B&P / BD'
WHEN account_code LIKE '9%' THEN 'Other'
END as category,
SUM(amount) as total
FROM pl_actuals
WHERE fiscal_year = 2025 AND scenario = 'actual' AND entity = 'CONSOLIDATED'
GROUP BY category
ORDER BY category;

Get revenue by source for FY2026​

SELECT source, SUM(amount) as revenue
FROM pl_forecasts
WHERE entity = 'CONSOLIDATED'
AND fiscal_year = 2026
AND account_code LIKE '4%'
GROUP BY source;

Monthly P&L trend (combining actuals + forecast)​

-- Actuals months (before close date):
SELECT fiscal_year, fiscal_month, SUM(amount) as net_income
FROM pl_actuals
WHERE entity = 'CONSOLIDATED' AND scenario = 'actual'
GROUP BY fiscal_year, fiscal_month

UNION ALL

-- Forecast months (after close date):
SELECT fiscal_year, fiscal_month, SUM(amount) as net_income
FROM pl_forecasts
WHERE entity = 'CONSOLIDATED'
GROUP BY fiscal_year, fiscal_month

ORDER BY fiscal_year, fiscal_month;

Data Flow Diagram​

ERP GL (nightly sync)
|
pl_actuals (historical)
|
|--> Income Statement (actuals months)
|--> Indirect Engine (trailing averages from actuals)

Forecast Module (Division Lead input)
|
forecast_rollup.py
|
pl_forecasts (source='contract_forecast')
|
|--> Income Statement (forecast months)

Pipeline/BD (CEO growth targets)
|
new_business_rollup.py
|
pl_forecasts (source='new_business')
|
|--> Income Statement (forecast months)

Indirect Rates (indirect config)
|
indirect_forecast_engine.py
|
pl_forecasts (source='indirect_forecast')
|
|--> Income Statement (forecast months)

D&A Schedule (balance sheet)
|
pl_forecasts (source='da_schedule')
|
|--> Income Statement (forecast months)

Relationships to Other Modules​

  • Forecast Module → Writes revenue + direct costs to pl_forecasts (source='contract_forecast')
  • Pipeline/BD → Writes growth target revenue + COGS to pl_forecasts (source='new_business')
  • Indirect Rates → Configures how each indirect GL account is forecasted; engine writes to pl_forecasts (source='indirect_forecast')
  • Financial Statements (BS/CFS) → Reads net income from P&L to drive retained earnings, cash flow, and covenant calculations
  • Scenario Planning → Applies overlay adjustments to P&L data (never modifies base forecast)
  • Reporting → All reporting tabs pull P&L data from these same tables
  • Dashboard → Hero metrics (revenue, EBITDA, net income) computed from pl_actuals + pl_forecasts