CoolCMS API

MarginReporter
in package

FinalYes

Read-only margin report.

Revenue, COGS and margin come only from posted (status=1) issue documents (type=2) that are not storno counter-documents (source_type <> 'storno'); without this filter transfers (also -q with a price) and storno pairs would double or skew the numbers. A separate inventory-differences line aggregates posted inventory corrections (type=4): the signed quantity SUM(q) and its value (shortages negative, surpluses positive), with the same storno exclusion: a cancelled inventory contributes nothing. The value uses the price each movement carries in DocumentService::adjust(): a shortage has the FEFO cogs_unit_price and no unit_price_base, a surplus has the batch price in unit_price_base and no cogs_unit_price.

Uses raw DBAL with the same read-only shape as StockBatchManager::watchExpiry() and StockRecalculator: no ORM hydration, no writes. The period filters on stock_documents.posted_datetime (the accounting date), the same column the admin StockDocument grid range-filters on.

Table of Contents

Constants

DOCUMENTS  : string = 'cms_mod_store_stock_documents'
MOVEMENTS  : string = 'cms_mod_store_stock_movements'

Properties

$em  : EntityManagerInterface

Methods

__construct()  : mixed
report()  : array{from: string, to: string, stockItemId: ?int, movementCount: int, revenue: string, cogs: string, margin: string, inventory: array{movementCount: int, quantity: string, cogsValue: string}}
aggregate()  : array{0: int, 1: string, 2: string}
Issue documents: [movementCount, SUM(-q * unit_price_base), SUM(-q * cogs_unit_price)].
n()  : numeric-string
rInt()  : int
rStr()  : string

Constants

DOCUMENTS

private string DOCUMENTS = 'cms_mod_store_stock_documents'

MOVEMENTS

private string MOVEMENTS = 'cms_mod_store_stock_movements'

Properties

Methods

__construct()

public __construct(EntityManagerInterface $em) : mixed
Parameters
$em : EntityManagerInterface

report()

public report(DateTimeInterface $from, DateTimeInterface $to[, int|null $stockItemId = null ]) : array{from: string, to: string, stockItemId: ?int, movementCount: int, revenue: string, cogs: string, margin: string, inventory: array{movementCount: int, quantity: string, cogsValue: string}}
Parameters
$from : DateTimeInterface
$to : DateTimeInterface
$stockItemId : int|null = null
Return values
array{from: string, to: string, stockItemId: ?int, movementCount: int, revenue: string, cogs: string, margin: string, inventory: array{movementCount: int, quantity: string, cogsValue: string}}

aggregate()

Issue documents: [movementCount, SUM(-q * unit_price_base), SUM(-q * cogs_unit_price)].

private aggregate(int $documentType, string $fromStr, string $toStr, int|null $stockItemId, bool $issueSemantics) : array{0: int, 1: string, 2: string}

Inventory documents: [movementCount, SUM(q), SUM(q * COALESCE(cogs_unit_price, unit_price_base))].

IMPORTANT: inventory movements carry their price in one of two columns (see the class doc). Multiplying the quantity by unit_price_base turned the quantity slot into the value of the surpluses (shortages are NULL there and dropped out), and q * cogs_unit_price alone left the surpluses out of the value.

Parameters
$documentType : int
$fromStr : string
$toStr : string
$stockItemId : int|null
$issueSemantics : bool
Return values
array{0: int, 1: string, 2: string}

n()

private n(string $value) : numeric-string
Parameters
$value : string
Return values
numeric-string —

bcmath wrapper (same as DocumentService::n()).

rInt()

private rInt(mixed $value) : int
Parameters
$value : mixed
Return values
int

rStr()

private rStr(mixed $value) : string
Parameters
$value : mixed
Return values
string
On this page

Search results