73 lines
4.1 KiB
Python
73 lines
4.1 KiB
Python
from __future__ import annotations
|
|
|
|
from sqlalchemy import select
|
|
|
|
from app.modules.accounting.taxonomy_models import AccountingNature
|
|
|
|
|
|
SALES_INCOME_NATURES = [
|
|
# code, name, parent, group, cap/revenue, posting, sort, description
|
|
("SALES_INCOME", "Sales & Income", None, "income", "revenue", False, 1100, "Sales and income classification root."),
|
|
("TRADING_SALES", "Trading / Stock Sales", "SALES_INCOME", "income", "revenue", True, 1110, "Sale of goods principally held for resale."),
|
|
("MANUFACTURED_GOODS_SALES", "Manufactured Goods Sales", "SALES_INCOME", "income", "revenue", True, 1120, "Sale of goods manufactured or produced by the entity."),
|
|
("SERVICE_INCOME", "Service / Professional Income", "SALES_INCOME", "income", "revenue", True, 1130, "Revenue from services, professional work or contractual services."),
|
|
("EXPORT_SALES", "Export Sales / Services", "SALES_INCOME", "income", "revenue", True, 1140, "Export of goods or services."),
|
|
("EXEMPT_NIL_SALES", "Exempt / Nil-Rated Sales", "SALES_INCOME", "income", "revenue", True, 1150, "Sales or supplies treated as exempt or nil-rated."),
|
|
("SCRAP_SALES", "Scrap / Waste Sales", "SALES_INCOME", "income", "revenue", True, 1160, "Sale of scrap, waste or residual materials."),
|
|
("JOB_WORK_INCOME", "Job Work / Processing Income", "SALES_INCOME", "income", "revenue", True, 1170, "Income from job work, processing or conversion activity."),
|
|
("COMMISSION_INCOME", "Commission / Brokerage Income", "SALES_INCOME", "income", "revenue", True, 1180, "Commission, brokerage or intermediary income."),
|
|
("RENTAL_INCOME", "Rental / Hire Income", "SALES_INCOME", "income", "revenue", True, 1190, "Business rental, lease or hire income."),
|
|
("INTEREST_INCOME", "Interest Income", "SALES_INCOME", "income", "revenue", True, 1200, "Interest earned and accounted as income."),
|
|
("OTHER_OPERATING_INCOME", "Other Operating Income", "SALES_INCOME", "income", "revenue", True, 1210, "Other income arising from normal operations."),
|
|
("OTHER_INCOME", "Other Income", "SALES_INCOME", "income", "revenue", True, 1220, "Non-operating income not represented by a more specific nature."),
|
|
("ASSET_SALE", "Sale of Capital Asset", "SALES_INCOME", "income", "capital", True, 1230, "Disposal proceeds relating to capital assets; reviewer must determine final accounting treatment."),
|
|
("SALES_REVIEW_REQUIRED", "Sales / Income Review Required", "SALES_INCOME", "income", "review", True, 1290, "Fallback for outward transactions with insufficient evidence."),
|
|
]
|
|
|
|
|
|
def ensure_sales_income_taxonomy(db, tenant_id: int, actor_user_id: int | None = None) -> int:
|
|
existing = set(
|
|
db.execute(
|
|
select(AccountingNature.code).where(AccountingNature.tenant_id == int(tenant_id))
|
|
).scalars().all()
|
|
)
|
|
inserted = 0
|
|
for code, name, parent_code, group, cap_rev, posting, sort_order, description in SALES_INCOME_NATURES:
|
|
if code in existing:
|
|
continue
|
|
db.add(
|
|
AccountingNature(
|
|
tenant_id=int(tenant_id),
|
|
code=code,
|
|
name=name,
|
|
parent_code=parent_code,
|
|
classification_group=group,
|
|
capital_revenue=cap_rev,
|
|
description=description,
|
|
sort_order=sort_order,
|
|
is_posting_nature=bool(posting),
|
|
is_active=True,
|
|
is_system_defined=True,
|
|
created_by_user_id=actor_user_id,
|
|
updated_by_user_id=actor_user_id,
|
|
)
|
|
)
|
|
inserted += 1
|
|
if inserted:
|
|
db.commit()
|
|
return inserted
|
|
|
|
|
|
def sales_income_natures(db, tenant_id: int):
|
|
ensure_sales_income_taxonomy(db, tenant_id)
|
|
return list(
|
|
db.execute(
|
|
select(AccountingNature).where(
|
|
AccountingNature.tenant_id == int(tenant_id),
|
|
AccountingNature.classification_group == "income",
|
|
AccountingNature.is_posting_nature.is_(True),
|
|
AccountingNature.is_active.is_(True),
|
|
).order_by(AccountingNature.sort_order, AccountingNature.name)
|
|
).scalars().all()
|
|
)
|