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.
| Projects | CrestApps.Almohaseb.Reports (module), CrestApps.Almohaseb.Reports.Core (data service, builders) |
| Feature | CrestApps.Almohaseb.Reports (Operational reports); depends on Accounting, Sales & receivables, Purchases and CrestApps.OrchardCore.Reports; enabled by both business recipes |
| Dashboard feature | CrestApps.Almohaseb.Reports.Dashboard (Dashboard widgets); depends on Operational reports and OrchardCore.AdminDashboard; enabled by both business recipes |
| Permission | ViewAlmohasebOperationalReports (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): theCategorySales (date, category, amount) of every registeredICategorySalesSource, sales tax categories left out,AlwaysMinuscategories negative.DailySalesReportSource(always) readsIDailySalesService.ListAsync;ServiceTicketSalesSource(registered byServiceTicketsStartupunder[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), asPurchaseLine(date, bill, vendor, invoice number, category, amount, ask-accountant).GetReceivablesAsync(to): everyReceivableIndexrow up to the date as aReceivableMovement(customer, date, payment or not, amount; payments are indexed negative, the movement holds the amount).GetLedgerLinesAsync(range, types): the postedJournalLineIndexrows 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): anAmountGridby key and by day, or by month overMaxDays(31) days, with column totals.Compare(current, previous, order):ComparisonRows (Change,ChangePercentof 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,Marginof 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 (Openingfrom 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).
| Report | Name | Sections |
|---|---|---|
SalesReport | almohaseb-sales | Total 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 |
PurchasesReport | almohaseb-purchases | Total purchases, bills; share by category (or comparison); lines by date and vendor with a subtotal per vendor and day |
OperatingExpensesReport | almohaseb-operating-expenses | Expense accounts: total, entries; share by account in chart order (or comparison); every entry under its account |
OtherIncomeReport | almohaseb-other-income | The same for OtherIncome accounts |
PerformanceReport | almohaseb-performance | Sales, purchases, kept, margin (and the earlier margin); by category |
CustomerActivityReport | almohaseb-customer-activity | Owed 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:
| Type | Part | Settings | Shows |
|---|---|---|---|
AlmohasebIncomeSummaryWidget (RPT-25) | AlmohasebIncomeSummaryWidgetPart | Period (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) | AlmohasebCategoryMarginsWidgetPart | Period (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.