from __future__ import annotations

from datetime import date, datetime, timezone
from decimal import Decimal

from sqlalchemy import Boolean, Date, DateTime, ForeignKey, Integer, Numeric, String, Text, UniqueConstraint
from sqlalchemy.orm import Mapped, mapped_column, relationship

from app.core.db.common import CommonBase


class BillingSettings(CommonBase):
    __tablename__ = "billing_settings"
    __table_args__ = (
        UniqueConstraint("tenant_id", "branch_id", name="uq_billing_settings_tenant_branch"),
    )

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    tenant_id: Mapped[int] = mapped_column(ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False, index=True)
    branch_id: Mapped[int | None] = mapped_column(ForeignKey("branches.id", ondelete="SET NULL"), nullable=True, index=True)

    invoice_prefix: Mapped[str] = mapped_column(String(40), nullable=False, default="INV")
    next_invoice_no: Mapped[int] = mapped_column(Integer, nullable=False, default=1)
    padding: Mapped[int] = mapped_column(Integer, nullable=False, default=4)
    default_gst_rate: Mapped[Decimal] = mapped_column(Numeric(5, 2), nullable=False, default=Decimal("18.00"))
    default_tax_type: Mapped[str] = mapped_column(String(20), nullable=False, default="CGST_SGST")

    legal_name: Mapped[str | None] = mapped_column(String(200), nullable=True)
    gstin: Mapped[str | None] = mapped_column(String(20), nullable=True)
    pan: Mapped[str | None] = mapped_column(String(10), nullable=True)
    state_code: Mapped[str | None] = mapped_column(String(2), nullable=True)
    billing_address: Mapped[str | None] = mapped_column(Text, nullable=True)
    contact_email: Mapped[str | None] = mapped_column(String(255), nullable=True)
    contact_mobile: Mapped[str | None] = mapped_column(String(50), nullable=True)
    website_url: Mapped[str | None] = mapped_column(String(255), nullable=True)

    invoice_title: Mapped[str | None] = mapped_column(String(80), nullable=True)
    invoice_number_format: Mapped[str | None] = mapped_column(String(120), nullable=True)
    default_due_days: Mapped[int] = mapped_column(Integer, nullable=False, default=15)
    default_sac_code: Mapped[str | None] = mapped_column(String(20), nullable=True)

    bank_name: Mapped[str | None] = mapped_column(String(200), nullable=True)
    bank_account_name: Mapped[str | None] = mapped_column(String(200), nullable=True)
    bank_account_number: Mapped[str | None] = mapped_column(String(50), nullable=True)
    bank_ifsc: Mapped[str | None] = mapped_column(String(20), nullable=True)
    upi_id: Mapped[str | None] = mapped_column(String(100), nullable=True)
    bank_details: Mapped[str | None] = mapped_column(Text, nullable=True)

    payumoney_enabled: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
    payumoney_mode: Mapped[str] = mapped_column(String(20), nullable=False, default="TEST")
    payumoney_merchant_key: Mapped[str | None] = mapped_column(String(120), nullable=True)
    payumoney_merchant_salt: Mapped[str | None] = mapped_column(String(200), nullable=True)
    payumoney_merchant_id: Mapped[str | None] = mapped_column(String(120), nullable=True)
    payumoney_product_info: Mapped[str | None] = mapped_column(String(200), nullable=True)

    cashfree_enabled: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
    cashfree_mode: Mapped[str] = mapped_column(String(20), nullable=False, default="TEST")
    cashfree_client_id: Mapped[str | None] = mapped_column(String(180), nullable=True)
    cashfree_client_secret: Mapped[str | None] = mapped_column(String(240), nullable=True)
    cashfree_api_version: Mapped[str] = mapped_column(String(20), nullable=False, default="2023-08-01")
    cashfree_order_note: Mapped[str | None] = mapped_column(String(250), nullable=True)

    authorised_signatory_name: Mapped[str | None] = mapped_column(String(200), nullable=True)
    declaration: Mapped[str | None] = mapped_column(Text, nullable=True)
    terms: Mapped[str | None] = mapped_column(Text, nullable=True)
    footer_note: Mapped[str | None] = mapped_column(Text, nullable=True)

    created_at_utc: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)
    updated_at_utc: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc), nullable=False)


class BillingInvoiceGenerationBatch(CommonBase):
    __tablename__ = "billing_invoice_generation_batches"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    tenant_id: Mapped[int] = mapped_column(ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False, index=True)
    branch_id: Mapped[int | None] = mapped_column(ForeignKey("branches.id", ondelete="SET NULL"), nullable=True, index=True)

    billing_period_from: Mapped[date] = mapped_column(Date, nullable=False, index=True)
    billing_period_to: Mapped[date] = mapped_column(Date, nullable=False, index=True)
    financial_year: Mapped[str | None] = mapped_column(String(20), nullable=True, index=True)
    frequency: Mapped[str | None] = mapped_column(String(20), nullable=True, index=True)
    status: Mapped[str] = mapped_column(String(20), nullable=False, default="DRAFT_CREATED", index=True)

    selected_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
    created_invoice_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
    skipped_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
    error_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
    remarks: Mapped[str | None] = mapped_column(Text, nullable=True)

    generated_by_user_id: Mapped[int | None] = mapped_column(ForeignKey("users.id"), nullable=True)
    generated_at_utc: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)

    invoices = relationship("BillingInvoice", back_populates="generation_batch")


class BillingInvoice(CommonBase):
    __tablename__ = "billing_invoices"
    __table_args__ = (
        UniqueConstraint("tenant_id", "invoice_no", name="uq_billing_invoices_tenant_invoice_no"),
    )

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    tenant_id: Mapped[int] = mapped_column(ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False, index=True)
    branch_id: Mapped[int | None] = mapped_column(ForeignKey("branches.id", ondelete="SET NULL"), nullable=True, index=True)
    client_id: Mapped[int] = mapped_column(ForeignKey("clients.id", ondelete="RESTRICT"), nullable=False, index=True)
    engagement_id: Mapped[int | None] = mapped_column(ForeignKey("client_service_subscriptions.id", ondelete="SET NULL"), nullable=True, index=True)
    generation_batch_id: Mapped[int | None] = mapped_column(ForeignKey("billing_invoice_generation_batches.id", ondelete="SET NULL"), nullable=True, index=True)

    invoice_no: Mapped[str] = mapped_column(String(60), nullable=False, index=True)
    invoice_date: Mapped[date] = mapped_column(Date, nullable=False, default=date.today, index=True)
    due_date: Mapped[date | None] = mapped_column(Date, nullable=True, index=True)
    billing_period_from: Mapped[date | None] = mapped_column(Date, nullable=True)
    billing_period_to: Mapped[date | None] = mapped_column(Date, nullable=True)
    financial_year: Mapped[str | None] = mapped_column(String(20), nullable=True, index=True)

    invoice_title: Mapped[str | None] = mapped_column(String(80), nullable=True)
    place_of_supply: Mapped[str | None] = mapped_column(String(120), nullable=True)
    reverse_charge: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)

    client_legal_name: Mapped[str | None] = mapped_column(String(200), nullable=True)
    client_trade_name: Mapped[str | None] = mapped_column(String(200), nullable=True)
    client_gstin: Mapped[str | None] = mapped_column(String(20), nullable=True)
    client_pan: Mapped[str | None] = mapped_column(String(20), nullable=True)
    client_billing_address: Mapped[str | None] = mapped_column(Text, nullable=True)
    client_state: Mapped[str | None] = mapped_column(String(100), nullable=True)
    client_state_code: Mapped[str | None] = mapped_column(String(2), nullable=True)
    client_email: Mapped[str | None] = mapped_column(String(255), nullable=True)
    client_mobile: Mapped[str | None] = mapped_column(String(50), nullable=True)

    tax_type: Mapped[str] = mapped_column(String(20), nullable=False, default="CGST_SGST")
    subtotal: Mapped[Decimal] = mapped_column(Numeric(14, 2), nullable=False, default=Decimal("0.00"))
    discount_amount: Mapped[Decimal] = mapped_column(Numeric(14, 2), nullable=False, default=Decimal("0.00"))
    taxable_amount: Mapped[Decimal] = mapped_column(Numeric(14, 2), nullable=False, default=Decimal("0.00"))
    cgst_amount: Mapped[Decimal] = mapped_column(Numeric(14, 2), nullable=False, default=Decimal("0.00"))
    sgst_amount: Mapped[Decimal] = mapped_column(Numeric(14, 2), nullable=False, default=Decimal("0.00"))
    igst_amount: Mapped[Decimal] = mapped_column(Numeric(14, 2), nullable=False, default=Decimal("0.00"))
    round_off: Mapped[Decimal] = mapped_column(Numeric(14, 2), nullable=False, default=Decimal("0.00"))
    total_amount: Mapped[Decimal] = mapped_column(Numeric(14, 2), nullable=False, default=Decimal("0.00"))
    amount_received: Mapped[Decimal] = mapped_column(Numeric(14, 2), nullable=False, default=Decimal("0.00"))
    tds_deducted: Mapped[Decimal] = mapped_column(Numeric(14, 2), nullable=False, default=Decimal("0.00"))
    bank_charges: Mapped[Decimal] = mapped_column(Numeric(14, 2), nullable=False, default=Decimal("0.00"))
    balance_amount: Mapped[Decimal] = mapped_column(Numeric(14, 2), nullable=False, default=Decimal("0.00"))
    amount_in_words: Mapped[str | None] = mapped_column(String(500), nullable=True)

    status: Mapped[str] = mapped_column(String(20), nullable=False, default="DRAFT", index=True)
    notes: Mapped[str | None] = mapped_column(Text, nullable=True)
    terms: Mapped[str | None] = mapped_column(Text, nullable=True)

    created_by_user_id: Mapped[int | None] = mapped_column(ForeignKey("users.id"), nullable=True)
    approved_by_user_id: Mapped[int | None] = mapped_column(ForeignKey("users.id"), nullable=True)
    posted_at_utc: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    created_at_utc: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)
    updated_at_utc: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc), nullable=False)

    client = relationship("Client")
    engagement = relationship("ClientServiceSubscription", foreign_keys=[engagement_id])
    generation_batch = relationship("BillingInvoiceGenerationBatch", back_populates="invoices")
    lines = relationship("BillingInvoiceLine", back_populates="invoice", cascade="all, delete-orphan", order_by="BillingInvoiceLine.sort_order.asc()")
    payments = relationship("BillingPayment", back_populates="invoice", cascade="all, delete-orphan", order_by="BillingPayment.payment_date.desc(), BillingPayment.id.desc()")
    online_transactions = relationship("BillingOnlinePaymentTransaction", back_populates="invoice", cascade="all, delete-orphan", order_by="BillingOnlinePaymentTransaction.created_at_utc.desc(), BillingOnlinePaymentTransaction.id.desc()")


class BillingPayment(CommonBase):
    __tablename__ = "billing_payments"
    __table_args__ = (
        UniqueConstraint("tenant_id", "receipt_no", name="uq_billing_payments_tenant_receipt_no"),
    )

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    tenant_id: Mapped[int] = mapped_column(ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False, index=True)
    branch_id: Mapped[int | None] = mapped_column(ForeignKey("branches.id", ondelete="SET NULL"), nullable=True, index=True)
    invoice_id: Mapped[int] = mapped_column(ForeignKey("billing_invoices.id", ondelete="CASCADE"), nullable=False, index=True)
    client_id: Mapped[int] = mapped_column(ForeignKey("clients.id", ondelete="RESTRICT"), nullable=False, index=True)

    receipt_no: Mapped[str] = mapped_column(String(60), nullable=False, index=True)
    receipt_date: Mapped[date] = mapped_column(Date, nullable=False, default=date.today, index=True)
    payment_date: Mapped[date] = mapped_column(Date, nullable=False, default=date.today, index=True)
    financial_year: Mapped[str | None] = mapped_column(String(20), nullable=True, index=True)
    amount_received: Mapped[Decimal] = mapped_column(Numeric(14, 2), nullable=False, default=Decimal("0.00"))
    tds_deducted: Mapped[Decimal] = mapped_column(Numeric(14, 2), nullable=False, default=Decimal("0.00"))
    bank_charges: Mapped[Decimal] = mapped_column(Numeric(14, 2), nullable=False, default=Decimal("0.00"))
    mode: Mapped[str] = mapped_column(String(30), nullable=False, default="BANK")
    reference_no: Mapped[str | None] = mapped_column(String(120), nullable=True)
    payment_gateway: Mapped[str | None] = mapped_column(String(50), nullable=True)
    gateway_transaction_id: Mapped[str | None] = mapped_column(String(120), nullable=True)
    remarks: Mapped[str | None] = mapped_column(Text, nullable=True)
    status: Mapped[str] = mapped_column(String(20), nullable=False, default="RECEIVED", index=True)

    created_by_user_id: Mapped[int | None] = mapped_column(ForeignKey("users.id"), nullable=True)
    created_at_utc: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)
    updated_at_utc: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc), nullable=False)

    invoice = relationship("BillingInvoice", back_populates="payments")
    client = relationship("Client")


class BillingOnlinePaymentTransaction(CommonBase):
    __tablename__ = "billing_online_payment_transactions"
    __table_args__ = (
        UniqueConstraint("tenant_id", "txnid", name="uq_billing_online_payment_tenant_txnid"),
    )

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    tenant_id: Mapped[int] = mapped_column(ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False, index=True)
    branch_id: Mapped[int | None] = mapped_column(ForeignKey("branches.id", ondelete="SET NULL"), nullable=True, index=True)
    invoice_id: Mapped[int] = mapped_column(ForeignKey("billing_invoices.id", ondelete="CASCADE"), nullable=False, index=True)
    client_id: Mapped[int] = mapped_column(ForeignKey("clients.id", ondelete="RESTRICT"), nullable=False, index=True)

    provider: Mapped[str] = mapped_column(String(40), nullable=False, default="PAYUMONEY", index=True)
    mode: Mapped[str] = mapped_column(String(20), nullable=False, default="TEST")
    txnid: Mapped[str] = mapped_column(String(80), nullable=False, index=True)
    amount: Mapped[Decimal] = mapped_column(Numeric(14, 2), nullable=False, default=Decimal("0.00"))
    productinfo: Mapped[str | None] = mapped_column(String(250), nullable=True)
    firstname: Mapped[str | None] = mapped_column(String(120), nullable=True)
    email: Mapped[str | None] = mapped_column(String(255), nullable=True)
    phone: Mapped[str | None] = mapped_column(String(50), nullable=True)

    payu_payment_id: Mapped[str | None] = mapped_column(String(120), nullable=True, index=True)
    cashfree_order_id: Mapped[str | None] = mapped_column(String(120), nullable=True, index=True)
    cashfree_cf_order_id: Mapped[str | None] = mapped_column(String(120), nullable=True, index=True)
    cashfree_payment_session_id: Mapped[str | None] = mapped_column(String(500), nullable=True)
    cashfree_payment_id: Mapped[str | None] = mapped_column(String(120), nullable=True, index=True)
    webhook_event_id: Mapped[str | None] = mapped_column(String(120), nullable=True, index=True)
    bank_ref_num: Mapped[str | None] = mapped_column(String(120), nullable=True)
    mihpayid: Mapped[str | None] = mapped_column(String(120), nullable=True)
    status: Mapped[str] = mapped_column(String(30), nullable=False, default="INITIATED", index=True)
    gateway_status: Mapped[str | None] = mapped_column(String(80), nullable=True)
    response_hash: Mapped[str | None] = mapped_column(String(200), nullable=True)
    raw_response: Mapped[str | None] = mapped_column(Text, nullable=True)
    receipt_payment_id: Mapped[int | None] = mapped_column(ForeignKey("billing_payments.id", ondelete="SET NULL"), nullable=True, index=True)

    created_at_utc: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)
    updated_at_utc: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc), nullable=False)
    completed_at_utc: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)

    invoice = relationship("BillingInvoice", back_populates="online_transactions")
    client = relationship("Client")
    receipt_payment = relationship("BillingPayment", foreign_keys=[receipt_payment_id])


class BillingInvoiceLine(CommonBase):
    __tablename__ = "billing_invoice_lines"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    invoice_id: Mapped[int] = mapped_column(ForeignKey("billing_invoices.id", ondelete="CASCADE"), nullable=False, index=True)
    service_id: Mapped[int | None] = mapped_column(ForeignKey("service_catalogues.id", ondelete="SET NULL"), nullable=True, index=True)
    engagement_id: Mapped[int | None] = mapped_column(ForeignKey("client_service_subscriptions.id", ondelete="SET NULL"), nullable=True, index=True)
    fee_group_id: Mapped[int | None] = mapped_column(ForeignKey("billing_fee_groups.id", ondelete="SET NULL"), nullable=True, index=True)

    description: Mapped[str] = mapped_column(String(500), nullable=False)
    sac_code: Mapped[str | None] = mapped_column(String(20), nullable=True)
    billing_period_from: Mapped[date | None] = mapped_column(Date, nullable=True)
    billing_period_to: Mapped[date | None] = mapped_column(Date, nullable=True)
    quantity: Mapped[Decimal] = mapped_column(Numeric(12, 2), nullable=False, default=Decimal("1.00"))
    rate: Mapped[Decimal] = mapped_column(Numeric(14, 2), nullable=False, default=Decimal("0.00"))
    discount_amount: Mapped[Decimal] = mapped_column(Numeric(14, 2), nullable=False, default=Decimal("0.00"))
    taxable_amount: Mapped[Decimal] = mapped_column(Numeric(14, 2), nullable=False, default=Decimal("0.00"))
    gst_rate: Mapped[Decimal] = mapped_column(Numeric(5, 2), nullable=False, default=Decimal("18.00"))
    cgst_amount: Mapped[Decimal] = mapped_column(Numeric(14, 2), nullable=False, default=Decimal("0.00"))
    sgst_amount: Mapped[Decimal] = mapped_column(Numeric(14, 2), nullable=False, default=Decimal("0.00"))
    igst_amount: Mapped[Decimal] = mapped_column(Numeric(14, 2), nullable=False, default=Decimal("0.00"))
    line_total: Mapped[Decimal] = mapped_column(Numeric(14, 2), nullable=False, default=Decimal("0.00"))
    sort_order: Mapped[int] = mapped_column(Integer, nullable=False, default=1)

    invoice = relationship("BillingInvoice", back_populates="lines")
    service = relationship("ServiceCatalogue")


class BillingFeeGroup(CommonBase):
    __tablename__ = "billing_fee_groups"
    __table_args__ = (
        UniqueConstraint("tenant_id", "group_code", name="uq_billing_fee_groups_tenant_code"),
    )

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    tenant_id: Mapped[int] = mapped_column(ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False, index=True)
    branch_id: Mapped[int | None] = mapped_column(ForeignKey("branches.id", ondelete="SET NULL"), nullable=True, index=True)
    client_id: Mapped[int] = mapped_column(ForeignKey("clients.id", ondelete="CASCADE"), nullable=False, index=True)
    partner_id: Mapped[int | None] = mapped_column(ForeignKey("users.id", ondelete="SET NULL"), nullable=True, index=True)

    group_code: Mapped[str] = mapped_column(String(80), nullable=False, index=True)
    group_name: Mapped[str] = mapped_column(String(200), nullable=False)
    billing_mode: Mapped[str] = mapped_column(String(20), nullable=False, default="PACKAGE")
    frequency: Mapped[str] = mapped_column(String(20), nullable=False, default="Monthly")
    fee_amount: Mapped[Decimal] = mapped_column(Numeric(14, 2), nullable=False, default=Decimal("0.00"))
    gst_rate: Mapped[Decimal] = mapped_column(Numeric(5, 2), nullable=False, default=Decimal("18.00"))
    tax_type: Mapped[str] = mapped_column(String(20), nullable=False, default="CGST_SGST")
    effective_from: Mapped[date | None] = mapped_column(Date, nullable=True)
    effective_to: Mapped[date | None] = mapped_column(Date, nullable=True)
    auto_generate: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
    is_active: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True, index=True)
    notes: Mapped[str | None] = mapped_column(Text, nullable=True)

    created_by_user_id: Mapped[int | None] = mapped_column(ForeignKey("users.id"), nullable=True)
    updated_by_user_id: Mapped[int | None] = mapped_column(ForeignKey("users.id"), nullable=True)
    created_at_utc: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)
    updated_at_utc: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc), nullable=False)

    client = relationship("Client")
    services = relationship("BillingFeeGroupService", back_populates="fee_group", cascade="all, delete-orphan", order_by="BillingFeeGroupService.sort_order.asc()")


class BillingFeeGroupService(CommonBase):
    __tablename__ = "billing_fee_group_services"
    __table_args__ = (
        UniqueConstraint("fee_group_id", "service_id", name="uq_billing_fee_group_services_group_service"),
    )

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    fee_group_id: Mapped[int] = mapped_column(ForeignKey("billing_fee_groups.id", ondelete="CASCADE"), nullable=False, index=True)
    service_id: Mapped[int] = mapped_column(ForeignKey("service_catalogues.id", ondelete="RESTRICT"), nullable=False, index=True)
    line_description: Mapped[str | None] = mapped_column(String(500), nullable=True)
    allocation_type: Mapped[str] = mapped_column(String(20), nullable=False, default="Included")
    line_amount: Mapped[Decimal] = mapped_column(Numeric(14, 2), nullable=False, default=Decimal("0.00"))
    percentage: Mapped[Decimal | None] = mapped_column(Numeric(5, 2), nullable=True)
    sort_order: Mapped[int] = mapped_column(Integer, nullable=False, default=1)

    fee_group = relationship("BillingFeeGroup", back_populates="services")
    service = relationship("ServiceCatalogue")
