File size: 2,277 Bytes
c14ceee
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
"""Request context — the single object that carries the GLOBAL filters through a page render.

Instead of threading date_from / date_to / team_id / ... through every function, a page builds
one `Ctx` from the sidebar controls and passes it (or its primitives) down. Modules read only
what they need. Add a new global filter once here and every module can opt into it.

The DBA (doing-business-as) brand filter lives here as `team_id`:
    None  -> All / consolidated (Fisch + Royal)
    5     -> Fisch
    6     -> Royal
HQ / company-level modules (cash flow, balance sheet, AR/AP, consolidated P&L) ignore brand and
call `ctx.consolidated()`; operational modules (sales, customers, products, margins) honour it.
"""
from dataclasses import dataclass, replace
import core.odoo as O
import core.periods as P

# label -> team_id used by the sidebar Brand (DBA) selector
BRANDS = {'All': None, 'Fisch': 5, 'Royal': 6}


@dataclass(frozen=True)
class Ctx:
    date_from: str
    date_to: str
    period_label: str = 'Year to date'
    team_id: int | None = None        # None = All DBAs (consolidated); 5 = Fisch; 6 = Royal
    doc_mode: str = 'order'           # reserved: 'order' vs 'invoice' recognition basis

    @property
    def brand(self) -> str:
        return O.TEAM_NAMES.get(self.team_id, 'All') if self.team_id else 'All'

    @property
    def teams(self) -> list:
        """Team ids in scope (single brand, or both when consolidated)."""
        return [self.team_id] if self.team_id else list(O.TEAM_IDS)

    @property
    def window(self) -> tuple:
        return self.date_from, self.date_to

    def consolidated(self) -> 'Ctx':
        """All-DBA copy — HQ modules use this so the brand filter never scopes company numbers."""
        return replace(self, team_id=None)

    def with_period(self, date_from, date_to, label=None) -> 'Ctx':
        return replace(self, date_from=date_from, date_to=date_to,
                       period_label=label or self.period_label)


def from_ui(period_label, period_window, brand_label='All', doc_mode='order') -> Ctx:
    df, dt = period_window
    return Ctx(df, dt, period_label, BRANDS.get(brand_label), doc_mode)


def default(t=None) -> Ctx:
    df, dt = P.ytd(t)
    return Ctx(df, dt, 'Year to date', None)