dodil/erp-brick-purchasing

DODIL ERP brick: purchasing

src/brick_purchasing/domain/rows.py

"""Small domain objects for the aggregates of slice 2 and the migration: sourcing, agreements, down payments, self-billing,
consignment, CIS. They carry the same fields as their tables (infrastructure/tables.py builds the tables from these dataclasses)."""
from dataclasses import dataclass, field
from datetime import date, datetime
from decimal import Decimal
from typing import Optional

from brick_purchasing.domain.values import ZERO


@dataclass
class RfqLine:
    rfq_id: str
    line_no: int
    product_id: str = ""
    description: str = ""
    quantity: Decimal = ZERO
    unit_code: str = ""


@dataclass
class RfqInvitation:
    rfq_id: str
    bp_id: int
    first_sent_at: Optional[datetime] = None
    sends: int = 0
    sent_to: str = ""


@dataclass
class SupplierQuote:
    rfq_id: str
    bp_id: int
    revision: int
    received_on: Optional[date] = None
    late: bool = False
    valid_to: Optional[date] = None
    currency: str = "GBP"
    lines_json: str = "[]"                 # [{line_no, unit_price, unit_code, pricing_quantity, delivery_days}]
    net_total: Decimal = ZERO


@dataclass
class Rfq:
    rfq_id: str
    rfq_no: str = ""
    request_id: str = ""
    status: str = "draft"                  # draft | sent | awarded | closed
    deadline: Optional[date] = None
    currency: str = "GBP"
    created_by_email: str = ""
    created_by_sub: str = ""
    sent_on: Optional[date] = None
    awarded_bp_id: Optional[int] = None
    award_reason: str = ""
    order_id: str = ""
    close_reason: str = ""
    lines: list = field(default_factory=list, repr=False)
    invitations: list = field(default_factory=list, repr=False)
    quotes: list = field(default_factory=list, repr=False)
    events: list = field(default_factory=list, repr=False)


@dataclass
class AgreementLine:
    agreement_id: str
    line_no: int
    product_id: str = ""
    description: str = ""
    unit_code: str = ""
    unit_numerator: int = 1
    unit_denominator: int = 1
    target_quantity: Decimal = ZERO
    unit_price: Decimal = ZERO
    pricing_unit_code: str = ""
    pricing_numerator: int = 1
    pricing_denominator: int = 1
    pricing_quantity: int = 1
    base_unit_code: str = ""


@dataclass
class ScheduleLine:
    agreement_id: str
    line_no: int
    revision: int
    delivery_date: date
    quantity: Decimal = ZERO
    unit_code: str = ""
    firm: bool = False
    changed_reason: str = ""
    released_jit: bool = False


@dataclass
class ScheduleRelease:
    agreement_id: str
    release_no: int
    kind: str = "forecast"                 # forecast | jit
    sent_at: Optional[datetime] = None
    sent_to: str = ""
    lines_json: str = "[]"
    call_off_order_id: str = ""
    sent_by: str = ""


@dataclass
class PurchaseAgreement:
    agreement_id: str
    bp_id: int = 0
    kind: str = "quantity_contract"        # quantity_contract | value_contract | scheduling_agreement
    supplier_ref: str = ""
    agreement_no: str = ""
    revision: int = 1
    valid_from: Optional[date] = None
    valid_to: Optional[date] = None
    target_value: Decimal = ZERO
    currency: str = "GBP"
    status: str = "draft"                  # draft | to_approve | active | closed
    firm_zone_days: int = 7
    buyer_email: str = ""
    buyer_sub: str = ""
    approved_by_email: str = ""
    approved_by_sub: str = ""
    approved_on: Optional[date] = None
    submitted_on: Optional[date] = None
    release_levels: int = 1
    release_thresholds: str = "[]"
    strategy_valid_from: Optional[date] = None
    pending_json: str = ""                 # a revision awaiting approval: releases continue under the approved values
    close_reason: str = ""
    lines: list = field(default_factory=list, repr=False)
    schedule: list = field(default_factory=list, repr=False)
    releases_sent: list = field(default_factory=list, repr=False)
    releases: list = field(default_factory=list, repr=False)
    events: list = field(default_factory=list, repr=False)


@dataclass
class DownPaymentClearing:
    down_payment_id: str
    bill_id: str
    seq: int
    amount: Decimal = ZERO
    tax_code: str = ""
    cleared_by_email: str = ""
    cleared_on: Optional[date] = None
    reason: str = ""


@dataclass
class DownPayment:
    down_payment_id: str
    dp_no: str = ""
    purchase_order_id: str = ""
    bp_id: int = 0
    net_amount: Decimal = ZERO
    tax_code: str = ""
    tax_amount: Decimal = ZERO
    gross_amount: Decimal = ZERO
    currency: str = "GBP"
    due_date: Optional[date] = None
    status: str = "requested"
    requested_by_email: str = ""
    requested_by_sub: str = ""
    approved_by_email: str = ""
    approved_by_sub: str = ""
    approved_on: Optional[date] = None
    payment_id: str = ""
    invoice_bill_id: str = ""
    paid_on: Optional[date] = None
    refund_reference: str = ""
    cancel_reason: str = ""
    clearings: list = field(default_factory=list, repr=False)
    events: list = field(default_factory=list, repr=False)