hesabixArc/hesabixAPI/adapters/api/v1/business_dashboard.py

369 lines
16 KiB
Python
Raw Normal View History

# Removed __future__ annotations to fix OpenAPI schema generation
from fastapi import APIRouter, Depends, Request, HTTPException
from sqlalchemy.orm import Session
from adapters.db.session import get_db
from adapters.api.v1.schemas import SuccessResponse
from app.core.responses import success_response, format_datetime_fields
from app.core.auth_dependency import get_current_user, AuthContext
from app.core.permissions import require_business_access
from app.services.business_dashboard_service import (
get_business_dashboard_data, get_business_members, get_business_statistics
)
router = APIRouter(prefix="/business", tags=["business-dashboard"])
@router.post("/{business_id}/dashboard",
summary="دریافت داشبورد کسب و کار",
description="دریافت اطلاعات کلی و آمار کسب و کار",
response_model=SuccessResponse,
responses={
200: {
"description": "داشبورد کسب و کار با موفقیت دریافت شد",
"content": {
"application/json": {
"example": {
"success": True,
"message": "داشبورد کسب و کار دریافت شد",
"data": {
"business_info": {
"id": 1,
"name": "شرکت نمونه",
"business_type": "شرکت",
"business_field": "تولیدی",
"owner_id": 1,
"created_at": "1403/01/01 00:00:00",
"member_count": 5
},
"statistics": {
"total_sales": 1000000.0,
"total_purchases": 500000.0,
"active_members": 5,
"recent_transactions": 25
},
"recent_activities": [
{
"id": 1,
"title": "فروش جدید",
"description": "فروش محصول A به مبلغ 100,000 تومان",
"icon": "sell",
"time_ago": "2 ساعت پیش"
}
]
}
}
}
}
},
401: {
"description": "کاربر احراز هویت نشده است"
},
403: {
"description": "دسترسی غیرمجاز به کسب و کار"
},
404: {
"description": "کسب و کار یافت نشد"
}
}
)
@require_business_access("business_id")
def get_business_dashboard(
request: Request,
business_id: int,
ctx: AuthContext = Depends(get_current_user),
db: Session = Depends(get_db)
) -> dict:
"""دریافت داشبورد کسب و کار"""
dashboard_data = get_business_dashboard_data(db, business_id, ctx)
formatted_data = format_datetime_fields(dashboard_data, request)
return success_response(formatted_data, request)
@router.post("/{business_id}/members",
summary="لیست اعضای کسب و کار",
description="دریافت لیست اعضای کسب و کار",
response_model=SuccessResponse,
responses={
200: {
"description": "لیست اعضا با موفقیت دریافت شد",
"content": {
"application/json": {
"example": {
"success": True,
"message": "لیست اعضا دریافت شد",
"data": {
"items": [
{
"id": 1,
"user_id": 2,
"first_name": "احمد",
"last_name": "احمدی",
"email": "ahmad@example.com",
"role": "مدیر فروش",
"permissions": {
"sales": {"write": True, "delete": True},
"reports": {"export": True}
},
"joined_at": "1403/01/01 00:00:00"
}
],
"pagination": {
"total": 1,
"page": 1,
"per_page": 10,
"total_pages": 1,
"has_next": False,
"has_prev": False
}
}
}
}
}
},
401: {
"description": "کاربر احراز هویت نشده است"
},
403: {
"description": "دسترسی غیرمجاز به کسب و کار"
}
}
)
@require_business_access("business_id")
def get_business_members(
request: Request,
business_id: int,
ctx: AuthContext = Depends(get_current_user),
db: Session = Depends(get_db)
) -> dict:
"""لیست اعضای کسب و کار"""
members_data = get_business_members(db, business_id, ctx)
formatted_data = format_datetime_fields(members_data, request)
return success_response(formatted_data, request)
@router.post("/{business_id}/statistics",
summary="آمار کسب و کار",
description="دریافت آمار تفصیلی کسب و کار",
response_model=SuccessResponse,
responses={
200: {
"description": "آمار با موفقیت دریافت شد",
"content": {
"application/json": {
"example": {
"success": True,
"message": "آمار دریافت شد",
"data": {
"sales_by_month": [
{"month": "1403/01", "amount": 500000},
{"month": "1403/02", "amount": 750000}
],
"top_products": [
{"name": "محصول A", "sales_count": 100, "revenue": 500000}
],
"member_activity": {
"active_today": 3,
"active_this_week": 5,
"total_members": 8
}
}
}
}
}
},
401: {
"description": "کاربر احراز هویت نشده است"
},
403: {
"description": "دسترسی غیرمجاز به کسب و کار"
}
}
)
@require_business_access("business_id")
def get_business_statistics(
request: Request,
business_id: int,
ctx: AuthContext = Depends(get_current_user),
db: Session = Depends(get_db)
) -> dict:
"""آمار کسب و کار"""
stats_data = get_business_statistics(db, business_id, ctx)
formatted_data = format_datetime_fields(stats_data, request)
return success_response(formatted_data, request)
2025-09-25 22:36:08 +03:30
@router.post("/{business_id}/info-with-permissions",
summary="دریافت اطلاعات کسب و کار و دسترسی‌ها",
description="دریافت اطلاعات کسب و کار همراه با دسترسی‌های کاربر",
response_model=SuccessResponse,
responses={
200: {
"description": "اطلاعات کسب و کار و دسترسی‌ها با موفقیت دریافت شد",
"content": {
"application/json": {
"example": {
"success": True,
"message": "اطلاعات کسب و کار و دسترسی‌ها دریافت شد",
"data": {
"business_info": {
"id": 1,
"name": "شرکت نمونه",
"business_type": "شرکت",
"business_field": "تولیدی",
"owner_id": 1,
"address": "تهران، خیابان ولیعصر",
"phone": "02112345678",
"mobile": "09123456789",
"created_at": "1403/01/01 00:00:00"
},
"user_permissions": {
"people": {"add": True, "view": True, "edit": True, "delete": False},
"products": {"add": True, "view": True, "edit": False, "delete": False},
"invoices": {"add": True, "view": True, "edit": True, "delete": True}
},
"is_owner": False,
"role": "عضو",
"has_access": True
}
}
}
}
},
401: {
"description": "کاربر احراز هویت نشده است"
},
403: {
"description": "دسترسی غیرمجاز به کسب و کار"
},
404: {
"description": "کسب و کار یافت نشد"
}
}
)
@require_business_access("business_id")
def get_business_info_with_permissions(
request: Request,
business_id: int,
ctx: AuthContext = Depends(get_current_user),
db: Session = Depends(get_db)
) -> dict:
"""دریافت اطلاعات کسب و کار همراه با دسترسی‌های کاربر"""
2025-10-03 17:02:07 +03:30
import logging
logger = logging.getLogger(__name__)
logger.info(f"=== get_business_info_with_permissions START ===")
logger.info(f"Business ID: {business_id}")
logger.info(f"User ID: {ctx.get_user_id()}")
logger.info(f"User context business_id: {ctx.business_id}")
logger.info(f"Is superadmin: {ctx.is_superadmin()}")
logger.info(f"Is business owner: {ctx.is_business_owner(business_id)}")
2025-09-25 22:36:08 +03:30
from adapters.db.models.business import Business
from adapters.db.repositories.business_permission_repo import BusinessPermissionRepository
# دریافت اطلاعات کسب و کار
business = db.get(Business, business_id)
if not business:
2025-10-03 17:02:07 +03:30
logger.error(f"Business {business_id} not found")
2025-09-25 22:36:08 +03:30
from app.core.responses import ApiError
raise ApiError("NOT_FOUND", "Business not found", http_status=404)
2025-10-03 17:02:07 +03:30
logger.info(f"Business found: {business.name} (Owner ID: {business.owner_id})")
2025-09-25 22:36:08 +03:30
# دریافت دسترسی‌های کاربر
permissions = {}
2025-10-03 17:02:07 +03:30
# Debug logging
logger.info(f"Checking permissions for user {ctx.get_user_id()}")
logger.info(f"Is superadmin: {ctx.is_superadmin()}")
logger.info(f"Is business owner of {business_id}: {ctx.is_business_owner(business_id)}")
logger.info(f"Context business_id: {ctx.business_id}")
if ctx.is_superadmin():
logger.info("User is superadmin, but superadmin permissions don't apply to business operations")
# SuperAdmin فقط برای مدیریت سیستم است، نه برای کسب و کارهای خاص
# باید دسترسی‌های کسب و کار را از جدول business_permissions دریافت کند
permission_repo = BusinessPermissionRepository(db)
business_permission = permission_repo.get_by_user_and_business(ctx.get_user_id(), business_id)
logger.info(f"Business permission object for superadmin: {business_permission}")
if business_permission:
permissions = business_permission.business_permissions or {}
logger.info(f"Superadmin business permissions: {permissions}")
else:
logger.info("No business permission found for superadmin user")
permissions = {}
elif ctx.is_business_owner(business_id):
logger.info("User is business owner, granting full permissions")
# مالک کسب و کار تمام دسترسی‌ها را دارد
permissions = {
"people": {"add": True, "edit": True, "view": True, "delete": True},
"products": {"add": True, "edit": True, "view": True, "delete": True},
"bank_accounts": {"add": True, "edit": True, "view": True, "delete": True},
"invoices": {"add": True, "edit": True, "view": True, "draft": True, "delete": True},
"people_transactions": {"add": True, "edit": True, "view": True, "draft": True, "delete": True},
"expenses_income": {"add": True, "edit": True, "view": True, "draft": True, "delete": True},
"transfers": {"add": True, "edit": True, "view": True, "draft": True, "delete": True},
"checks": {"add": True, "edit": True, "view": True, "delete": True, "return": True, "collect": True, "transfer": True},
"accounting_documents": {"add": True, "edit": True, "view": True, "draft": True, "delete": True},
"chart_of_accounts": {"add": True, "edit": True, "view": True, "delete": True},
"opening_balance": {"edit": True, "view": True},
"settings": {"print": True, "users": True, "history": True, "business": True},
"categories": {"add": True, "edit": True, "view": True, "delete": True},
"product_attributes": {"add": True, "edit": True, "view": True, "delete": True},
"warehouses": {"add": True, "edit": True, "view": True, "delete": True},
"warehouse_transfers": {"add": True, "edit": True, "view": True, "draft": True, "delete": True},
"cash": {"add": True, "edit": True, "view": True, "delete": True},
"petty_cash": {"add": True, "edit": True, "view": True, "delete": True},
"wallet": {"view": True, "charge": True},
"storage": {"view": True, "delete": True},
"marketplace": {"buy": True, "view": True, "invoices": True},
"price_lists": {"add": True, "edit": True, "view": True, "delete": True},
"sms": {"history": True, "templates": True},
"join": True
}
else:
logger.info("User is not superadmin and not business owner, checking permissions")
2025-09-25 22:36:08 +03:30
# دریافت دسترسی‌های کسب و کار از business_permissions
permission_repo = BusinessPermissionRepository(db)
2025-09-26 01:51:43 +03:30
# ترتیب آرگومان‌ها: (user_id, business_id)
business_permission = permission_repo.get_by_user_and_business(ctx.get_user_id(), business_id)
2025-10-03 17:02:07 +03:30
logger.info(f"Business permission object: {business_permission}")
2025-09-25 22:36:08 +03:30
if business_permission:
permissions = business_permission.business_permissions or {}
2025-10-03 17:02:07 +03:30
logger.info(f"User permissions: {permissions}")
else:
logger.info("No business permission found for user")
2025-09-25 22:36:08 +03:30
business_info = {
"id": business.id,
"name": business.name,
"business_type": business.business_type.value,
"business_field": business.business_field.value,
"owner_id": business.owner_id,
"address": business.address,
"phone": business.phone,
"mobile": business.mobile,
"created_at": business.created_at.isoformat(),
}
2025-10-03 17:02:07 +03:30
is_owner = ctx.is_business_owner(business_id)
has_access = ctx.can_access_business(business_id)
2025-09-25 22:36:08 +03:30
response_data = {
"business_info": business_info,
"user_permissions": permissions,
2025-10-03 17:02:07 +03:30
"is_owner": is_owner,
"role": "مالک" if is_owner else "عضو",
"has_access": has_access
2025-09-25 22:36:08 +03:30
}
2025-10-03 17:02:07 +03:30
logger.info(f"Response data: {response_data}")
logger.info(f"=== get_business_info_with_permissions END ===")
2025-09-25 22:36:08 +03:30
formatted_data = format_datetime_fields(response_data, request)
return success_response(formatted_data, request)