Improve the frontend and repository layer
This commit is contained in:
76
services/pos/app/services/pos_config_service.py
Normal file
76
services/pos/app/services/pos_config_service.py
Normal file
@@ -0,0 +1,76 @@
|
||||
"""
|
||||
POS Configuration Service - Business Logic Layer
|
||||
"""
|
||||
|
||||
from typing import List, Optional
|
||||
from uuid import UUID
|
||||
import structlog
|
||||
|
||||
from app.repositories.pos_config_repository import POSConfigurationRepository
|
||||
from app.schemas.pos_config import POSConfigurationResponse
|
||||
from app.core.database import get_db_transaction
|
||||
|
||||
logger = structlog.get_logger()
|
||||
|
||||
|
||||
class POSConfigurationService:
|
||||
"""Service layer for POS configuration operations"""
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
async def get_configurations_by_tenant(
|
||||
self,
|
||||
tenant_id: UUID,
|
||||
pos_system: Optional[str] = None,
|
||||
is_active: Optional[bool] = None,
|
||||
skip: int = 0,
|
||||
limit: int = 100
|
||||
) -> List[POSConfigurationResponse]:
|
||||
"""Get POS configurations for a tenant with filtering"""
|
||||
try:
|
||||
async with get_db_transaction() as db:
|
||||
repository = POSConfigurationRepository(db)
|
||||
|
||||
configurations = await repository.get_configurations_by_tenant(
|
||||
tenant_id=tenant_id,
|
||||
pos_system=pos_system,
|
||||
is_active=is_active,
|
||||
skip=skip,
|
||||
limit=limit
|
||||
)
|
||||
|
||||
# Convert to response schemas using from_orm
|
||||
responses = []
|
||||
for config in configurations:
|
||||
response = POSConfigurationResponse.from_orm(config)
|
||||
responses.append(response)
|
||||
|
||||
return responses
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Failed to get configurations by tenant", error=str(e), tenant_id=tenant_id)
|
||||
raise
|
||||
|
||||
async def count_configurations_by_tenant(
|
||||
self,
|
||||
tenant_id: UUID,
|
||||
pos_system: Optional[str] = None,
|
||||
is_active: Optional[bool] = None
|
||||
) -> int:
|
||||
"""Count POS configurations for a tenant with filtering"""
|
||||
try:
|
||||
async with get_db_transaction() as db:
|
||||
repository = POSConfigurationRepository(db)
|
||||
|
||||
count = await repository.count_configurations_by_tenant(
|
||||
tenant_id=tenant_id,
|
||||
pos_system=pos_system,
|
||||
is_active=is_active
|
||||
)
|
||||
|
||||
return count
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Failed to count configurations by tenant", error=str(e), tenant_id=tenant_id)
|
||||
raise
|
||||
239
services/pos/app/services/pos_transaction_service.py
Normal file
239
services/pos/app/services/pos_transaction_service.py
Normal file
@@ -0,0 +1,239 @@
|
||||
"""
|
||||
POS Transaction Service - Business Logic Layer
|
||||
"""
|
||||
|
||||
from typing import List, Optional, Dict, Any
|
||||
from uuid import UUID
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
import structlog
|
||||
|
||||
from app.repositories.pos_transaction_repository import POSTransactionRepository
|
||||
from app.repositories.pos_transaction_item_repository import POSTransactionItemRepository
|
||||
from app.schemas.pos_transaction import (
|
||||
POSTransactionResponse,
|
||||
POSTransactionDashboardSummary
|
||||
)
|
||||
from app.core.database import get_db_transaction
|
||||
|
||||
logger = structlog.get_logger()
|
||||
|
||||
|
||||
class POSTransactionService:
|
||||
"""Service layer for POS transaction operations"""
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
async def get_transactions_by_tenant(
|
||||
self,
|
||||
tenant_id: UUID,
|
||||
pos_system: Optional[str] = None,
|
||||
start_date: Optional[datetime] = None,
|
||||
end_date: Optional[datetime] = None,
|
||||
status: Optional[str] = None,
|
||||
is_synced: Optional[bool] = None,
|
||||
skip: int = 0,
|
||||
limit: int = 50
|
||||
) -> List[POSTransactionResponse]:
|
||||
"""Get POS transactions for a tenant with filtering"""
|
||||
try:
|
||||
async with get_db_transaction() as db:
|
||||
repository = POSTransactionRepository(db)
|
||||
|
||||
transactions = await repository.get_transactions_by_tenant(
|
||||
tenant_id=tenant_id,
|
||||
pos_system=pos_system,
|
||||
start_date=start_date,
|
||||
end_date=end_date,
|
||||
status=status,
|
||||
is_synced=is_synced,
|
||||
skip=skip,
|
||||
limit=limit
|
||||
)
|
||||
|
||||
# Convert to response schemas
|
||||
responses = []
|
||||
for transaction in transactions:
|
||||
response = POSTransactionResponse.from_orm(transaction)
|
||||
responses.append(response)
|
||||
|
||||
return responses
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Failed to get transactions by tenant", error=str(e), tenant_id=tenant_id)
|
||||
raise
|
||||
|
||||
async def count_transactions_by_tenant(
|
||||
self,
|
||||
tenant_id: UUID,
|
||||
pos_system: Optional[str] = None,
|
||||
start_date: Optional[datetime] = None,
|
||||
end_date: Optional[datetime] = None,
|
||||
status: Optional[str] = None,
|
||||
is_synced: Optional[bool] = None
|
||||
) -> int:
|
||||
"""Count POS transactions for a tenant with filtering"""
|
||||
try:
|
||||
async with get_db_transaction() as db:
|
||||
repository = POSTransactionRepository(db)
|
||||
|
||||
count = await repository.count_transactions_by_tenant(
|
||||
tenant_id=tenant_id,
|
||||
pos_system=pos_system,
|
||||
start_date=start_date,
|
||||
end_date=end_date,
|
||||
status=status,
|
||||
is_synced=is_synced
|
||||
)
|
||||
|
||||
return count
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Failed to count transactions by tenant", error=str(e), tenant_id=tenant_id)
|
||||
raise
|
||||
|
||||
async def get_transaction_with_items(
|
||||
self,
|
||||
transaction_id: UUID,
|
||||
tenant_id: UUID
|
||||
) -> Optional[POSTransactionResponse]:
|
||||
"""Get transaction with all its items"""
|
||||
try:
|
||||
async with get_db_transaction() as db:
|
||||
repository = POSTransactionRepository(db)
|
||||
|
||||
transaction = await repository.get_transaction_with_items(
|
||||
transaction_id=transaction_id,
|
||||
tenant_id=tenant_id
|
||||
)
|
||||
|
||||
if not transaction:
|
||||
return None
|
||||
|
||||
return POSTransactionResponse.from_orm(transaction)
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Failed to get transaction with items",
|
||||
transaction_id=str(transaction_id),
|
||||
error=str(e))
|
||||
raise
|
||||
|
||||
async def get_dashboard_summary(
|
||||
self,
|
||||
tenant_id: UUID
|
||||
) -> POSTransactionDashboardSummary:
|
||||
"""Get dashboard summary for POS transactions"""
|
||||
try:
|
||||
async with get_db_transaction() as db:
|
||||
repository = POSTransactionRepository(db)
|
||||
|
||||
# Get metrics from repository
|
||||
metrics = await repository.get_dashboard_metrics(tenant_id)
|
||||
|
||||
# Get sync status
|
||||
sync_status = await repository.get_sync_status_summary(tenant_id)
|
||||
|
||||
# Construct dashboard summary
|
||||
return POSTransactionDashboardSummary(
|
||||
total_transactions_today=metrics["total_transactions_today"],
|
||||
total_transactions_this_week=metrics["total_transactions_this_week"],
|
||||
total_transactions_this_month=metrics["total_transactions_this_month"],
|
||||
revenue_today=Decimal(str(metrics["revenue_today"])),
|
||||
revenue_this_week=Decimal(str(metrics["revenue_this_week"])),
|
||||
revenue_this_month=Decimal(str(metrics["revenue_this_month"])),
|
||||
average_transaction_value=Decimal(str(metrics["average_transaction_value"])),
|
||||
status_breakdown=metrics["status_breakdown"],
|
||||
payment_method_breakdown=metrics["payment_method_breakdown"],
|
||||
sync_status=sync_status
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Failed to get dashboard summary", error=str(e), tenant_id=tenant_id)
|
||||
raise
|
||||
|
||||
async def get_sync_metrics(
|
||||
self,
|
||||
tenant_id: UUID
|
||||
) -> Dict[str, Any]:
|
||||
"""Get sync metrics for transactions"""
|
||||
try:
|
||||
async with get_db_transaction() as db:
|
||||
repository = POSTransactionRepository(db)
|
||||
|
||||
sync_status = await repository.get_sync_status_summary(tenant_id)
|
||||
|
||||
# Calculate sync rate
|
||||
total = sync_status["synced"] + sync_status["pending"] + sync_status["failed"]
|
||||
sync_rate = (sync_status["synced"] / total * 100) if total > 0 else 0
|
||||
|
||||
return {
|
||||
"sync_status": sync_status,
|
||||
"sync_rate_percentage": round(sync_rate, 2),
|
||||
"total_transactions": total
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Failed to get sync metrics", error=str(e), tenant_id=tenant_id)
|
||||
raise
|
||||
|
||||
async def calculate_transaction_analytics(
|
||||
self,
|
||||
tenant_id: UUID,
|
||||
start_date: datetime,
|
||||
end_date: datetime
|
||||
) -> Dict[str, Any]:
|
||||
"""Calculate analytics for transactions within a date range"""
|
||||
try:
|
||||
async with get_db_transaction() as db:
|
||||
repository = POSTransactionRepository(db)
|
||||
|
||||
transactions = await repository.get_transactions_by_date_range(
|
||||
tenant_id=tenant_id,
|
||||
start_date=start_date.date(),
|
||||
end_date=end_date.date(),
|
||||
skip=0,
|
||||
limit=10000 # Large limit for analytics
|
||||
)
|
||||
|
||||
# Calculate analytics
|
||||
total_revenue = Decimal("0")
|
||||
total_transactions = len(transactions)
|
||||
payment_methods = {}
|
||||
order_types = {}
|
||||
hourly_distribution = {}
|
||||
|
||||
for transaction in transactions:
|
||||
if transaction.status == "completed":
|
||||
total_revenue += transaction.total_amount
|
||||
|
||||
# Payment method breakdown
|
||||
pm = transaction.payment_method or "unknown"
|
||||
payment_methods[pm] = payment_methods.get(pm, 0) + 1
|
||||
|
||||
# Order type breakdown
|
||||
ot = transaction.order_type or "unknown"
|
||||
order_types[ot] = order_types.get(ot, 0) + 1
|
||||
|
||||
# Hourly distribution
|
||||
hour = transaction.transaction_date.hour
|
||||
hourly_distribution[hour] = hourly_distribution.get(hour, 0) + 1
|
||||
|
||||
avg_transaction_value = (total_revenue / total_transactions) if total_transactions > 0 else Decimal("0")
|
||||
|
||||
return {
|
||||
"period": {
|
||||
"start_date": start_date.isoformat(),
|
||||
"end_date": end_date.isoformat()
|
||||
},
|
||||
"total_revenue": float(total_revenue),
|
||||
"total_transactions": total_transactions,
|
||||
"average_transaction_value": float(avg_transaction_value),
|
||||
"payment_methods": payment_methods,
|
||||
"order_types": order_types,
|
||||
"hourly_distribution": hourly_distribution
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Failed to calculate transaction analytics", error=str(e), tenant_id=tenant_id)
|
||||
raise
|
||||
Reference in New Issue
Block a user