Skip to main content
Technical ManualLooking for step-by-step instructions? In the User Manual: Operational ReportsThe Dashboard

Reports

The Reports module rebuilds the legacy operational reports as CrestApps Reports IReports: the sales report (RPT-10, its service layout RPT-11 and comparison RPT-04), the purchase report (RPT-09, RPT-05), operating expenses (RPT-12, RPT-06), other income (RPT-13, RPT-07), performance (RPT-14) and customer activity (RPT-21). The store reports (RPT-16, RPT-19, RPT-22) are in Retail. The profit and loss and the balance sheet (RPT-01 to RPT-03, RPT-08) are in Ledger.

ProjectsCrestApps.Almohaseb.Reports (module), CrestApps.Almohaseb.Reports.Core (data service, builders)
FeatureCrestApps.Almohaseb.Reports (Operational reports); depends on Accounting, Sales & receivables, Purchases and CrestApps.OrchardCore.Reports; enabled by both business recipes
Dashboard featureCrestApps.Almohaseb.Reports.Dashboard (Dashboard widgets); depends on Operational reports and OrchardCore.AdminDashboard; enabled by both business recipes
PermissionViewAlmohasebOperationalReports (View the sales, purchases, expenses, other income and performance reports)

Periods​

DateRange(From, To) with Days, IsWholeMonths, Months. ReportPeriods.GetComparison(range, comparison):

  • PreviousPeriod: whole months compare with as many whole months before (a quarter with the quarter before), other ranges with as many days before.
  • PreviousYear: the same dates a year earlier; a month end stays a month end (February 29 ↔ 28).

The legacy comparisons took two month/year pickers and ran the service sales of both periods from the first period's start date (RPT-03, RPT-07).

Data​

IOperationalReportData / OperationalReportData:

  • GetSalesAsync(range): the CategorySales (date, category, amount) of every registered ICategorySalesSource, sales tax categories left out, AlwaysMinus categories negative. DailySalesReportSource (always) reads IDailySalesService.ListAsync; ServiceTicketSalesSource (registered by ServiceTicketsStartup under [RequireFeatures(SalesConstants.ServicesFeature)], since the ticket index table only exists with the feature) reads the ticket lines, amount plus shipping.
  • GetPurchasesAsync(range): the purchase-category lines of the bills (PayableIndex.Kind = bill), as PurchaseLine (date, bill, vendor, invoice number, category, amount, ask-accountant).
  • GetReceivablesAsync(to): every ReceivableIndex row up to the date as a ReceivableMovement (customer, date, payment or not, amount; payments are indexed negative, the movement holds the amount).
  • GetLedgerLinesAsync(range, types): the posted JournalLineIndex rows of the accounts of the types, with their entry's number and the line's memo (else the entry's), entries loaded 500 ids at a time.

Builders​

OperationalReportBuilder is pure:

  • BuildGrid(range, amounts, order): an AmountGrid by key and by day, or by month over MaxDays (31) days, with column totals.
  • Compare(current, previous, order): ComparisonRows (Change, ChangePercent of the previous amount's absolute value, none from zero); keys at zero in both left out.
  • Shares(amounts, order): ShareRows; no share when the total is zero (RPT-09 divided by zero).
  • Performance(sales, purchases, order): PerformanceRows (Difference, Margin of the sales) of the categories with purchases, as in the Windows app; TotalMargin = Σ difference ÷ Σ sales (the Windows app patched it into the generated HTML).
  • CustomerActivity(range, movements, order): CustomerActivityRows (Opening from the movements before the range, Sales, Payments, Closing); customers at zero with nothing in the range left out.
  • NaturalAmount(line, type): credits less debits for income, liability and equity accounts, debits less credits otherwise.

Reports​

All in category Books and operations, with the dates of the CrestApps date range (local business dates; the current month by default) and the options of OperationalReportFilterDisplayDriver (OperationalReportFilter_Edit, Content:2): Compare with (AlmohasebReportComparison), Summary only (AlmohasebReportSummary, not on performance) and, on the purchase report, Only bills marked for the accountant (AlmohasebReportAskAccountant).

ReportNameSections
SalesReportalmohaseb-salesTotal sales (with the previous total and change), days with sales, average a day; the grid by day or month, or the share by category (summary), or the comparison by category
PurchasesReportalmohaseb-purchasesTotal purchases, bills; share by category (or comparison); lines by date and vendor with a subtotal per vendor and day
OperatingExpensesReportalmohaseb-operating-expensesExpense accounts: total, entries; share by account in chart order (or comparison); every entry under its account
OtherIncomeReportalmohaseb-other-incomeThe same for OtherIncome accounts
PerformanceReportalmohaseb-performanceSales, purchases, kept, margin (and the earlier margin); by category
CustomerActivityReportalmohaseb-customer-activityOwed at the start, sold on credit, paid, owed at the end; by customer; every credit sale, invoice and payment (no comparison)

Operating expenses and other income read the ledger (LedgerAccountsReport), so they tie to the profit and loss; the legacy reports read the expense screen and left the payroll overrides out (RPT-06, RPT-12). Cells are formatted text until CrestApps Reports has numeric cells (upstream U10).

Every report is in the Reports menu of CrestApps Reports, grouped by its category (Books and operations, Financial statements, Store, Taxes); no other menu links to reports. Each report is registered by a startup with [RequireFeatures("CrestApps.OrchardCore.Reports")] in the module that owns its data, so a module never depends on the Reports feature to run.

Dashboard widgets​

DashboardMigrations (version 1) creates two securable widget types with the DashboardWidget stereotype, each TitlePart + DashboardPart + its own part, shown by the Orchard Core admin dashboard in the DetailAdmin display type:

TypePartSettingsShows
AlmohasebIncomeSummaryWidget (RPT-25)AlmohasebIncomeSummaryWidgetPartPeriod (WidgetPeriod, default YearToDate)IFinancialStatementService.GetProfitAndLossAsync (summary): income, cost of sales, gross profit, expenses + other expenses − other income, net profit and margin; needs ViewAlmohasebFinancialStatements
AlmohasebCategoryMarginsWidget (RPT-24)AlmohasebCategoryMarginsWidgetPartPeriod (default ThisMonth), Count (1–50, default 8)OperationalReportBuilder.Performance of the period, largest sales first, and TotalMargin; needs ViewAlmohasebOperationalReports

The legacy categories dashboard computed its own totals, different from the P&L (RPT-25), and the mark-up panel called a gross margin a mark-up and dropped the last day from its rows (RPT-24); both now read the same services as the reports.

WidgetPeriods.Resolve(period, today, fiscalYearStart): ThisMonth (month start to today), LastMonth, YearToDate (fiscal year start to today), LastYear (the previous fiscal year). The fiscal year start comes from IBusinessCalendar.GetFiscalPeriodAsync.

Both business recipes enable OrchardCore.AdminDashboard and seed Profit this year (dsh-income, 2 × 1), Profit this month (dsh-income-month, 2 × 1) and Category margins this month (dsh-margins, 2 × 2) on the 6-column dashboard; the c-store recipe adds the daily close widget (Retail).

See also​

  • Ledger for the financial statements.