hesabixArc/hesabixAPI/app/services/person_service.py

295 lines
10 KiB
Python
Raw Normal View History

2025-09-25 22:36:08 +03:30
from typing import List, Optional, Dict, Any
from sqlalchemy.orm import Session
from sqlalchemy import and_, or_, func
from adapters.db.models.person import Person, PersonBankAccount, PersonType
from adapters.api.v1.schema_models.person import (
PersonCreateRequest, PersonUpdateRequest, PersonBankAccountCreateRequest
)
from app.core.responses import success_response
def create_person(db: Session, business_id: int, person_data: PersonCreateRequest) -> Dict[str, Any]:
"""ایجاد شخص جدید"""
# ایجاد شخص
person = Person(
business_id=business_id,
alias_name=person_data.alias_name,
first_name=person_data.first_name,
last_name=person_data.last_name,
person_type=person_data.person_type,
company_name=person_data.company_name,
payment_id=person_data.payment_id,
national_id=person_data.national_id,
registration_number=person_data.registration_number,
economic_id=person_data.economic_id,
country=person_data.country,
province=person_data.province,
city=person_data.city,
address=person_data.address,
postal_code=person_data.postal_code,
phone=person_data.phone,
mobile=person_data.mobile,
fax=person_data.fax,
email=person_data.email,
website=person_data.website,
)
db.add(person)
db.flush() # برای دریافت ID
# ایجاد حساب‌های بانکی
if person_data.bank_accounts:
for bank_account_data in person_data.bank_accounts:
bank_account = PersonBankAccount(
person_id=person.id,
bank_name=bank_account_data.bank_name,
account_number=bank_account_data.account_number,
card_number=bank_account_data.card_number,
sheba_number=bank_account_data.sheba_number,
)
db.add(bank_account)
db.commit()
db.refresh(person)
return success_response(
message="شخص با موفقیت ایجاد شد",
data=_person_to_dict(person)
)
def get_person_by_id(db: Session, person_id: int, business_id: int) -> Optional[Dict[str, Any]]:
"""دریافت شخص بر اساس شناسه"""
person = db.query(Person).filter(
and_(Person.id == person_id, Person.business_id == business_id)
).first()
if not person:
return None
return _person_to_dict(person)
def get_persons_by_business(
db: Session,
business_id: int,
query_info: Dict[str, Any]
) -> Dict[str, Any]:
"""دریافت لیست اشخاص با جستجو و فیلتر"""
query = db.query(Person).filter(Person.business_id == business_id)
# اعمال جستجو
if query_info.get('search') and query_info.get('search_fields'):
search_term = f"%{query_info['search']}%"
search_conditions = []
for field in query_info['search_fields']:
if field == 'alias_name':
search_conditions.append(Person.alias_name.ilike(search_term))
elif field == 'first_name':
search_conditions.append(Person.first_name.ilike(search_term))
elif field == 'last_name':
search_conditions.append(Person.last_name.ilike(search_term))
elif field == 'company_name':
search_conditions.append(Person.company_name.ilike(search_term))
elif field == 'mobile':
search_conditions.append(Person.mobile.ilike(search_term))
elif field == 'email':
search_conditions.append(Person.email.ilike(search_term))
elif field == 'national_id':
search_conditions.append(Person.national_id.ilike(search_term))
if search_conditions:
query = query.filter(or_(*search_conditions))
# اعمال فیلترها
if query_info.get('filters'):
for filter_item in query_info['filters']:
field = filter_item.get('property')
operator = filter_item.get('operator')
value = filter_item.get('value')
if field == 'person_type':
if operator == '=':
query = query.filter(Person.person_type == value)
elif operator == 'in':
query = query.filter(Person.person_type.in_(value))
elif field == 'is_active':
if operator == '=':
query = query.filter(Person.is_active == value)
elif field == 'country':
if operator == '=':
query = query.filter(Person.country == value)
elif operator == 'like':
query = query.filter(Person.country.ilike(f"%{value}%"))
elif field == 'province':
if operator == '=':
query = query.filter(Person.province == value)
elif operator == 'like':
query = query.filter(Person.province.ilike(f"%{value}%"))
# شمارش کل رکوردها
total = query.count()
# اعمال مرتب‌سازی
sort_by = query_info.get('sort_by', 'created_at')
sort_desc = query_info.get('sort_desc', True)
if sort_by == 'alias_name':
query = query.order_by(Person.alias_name.desc() if sort_desc else Person.alias_name.asc())
elif sort_by == 'first_name':
query = query.order_by(Person.first_name.desc() if sort_desc else Person.first_name.asc())
elif sort_by == 'last_name':
query = query.order_by(Person.last_name.desc() if sort_desc else Person.last_name.asc())
elif sort_by == 'person_type':
query = query.order_by(Person.person_type.desc() if sort_desc else Person.person_type.asc())
elif sort_by == 'created_at':
query = query.order_by(Person.created_at.desc() if sort_desc else Person.created_at.asc())
elif sort_by == 'updated_at':
query = query.order_by(Person.updated_at.desc() if sort_desc else Person.updated_at.asc())
else:
query = query.order_by(Person.created_at.desc())
# اعمال صفحه‌بندی
skip = query_info.get('skip', 0)
take = query_info.get('take', 20)
persons = query.offset(skip).limit(take).all()
# تبدیل به دیکشنری
items = [_person_to_dict(person) for person in persons]
# محاسبه اطلاعات صفحه‌بندی
total_pages = (total + take - 1) // take
current_page = (skip // take) + 1
pagination = {
'total': total,
'page': current_page,
'per_page': take,
'total_pages': total_pages,
'has_next': current_page < total_pages,
'has_prev': current_page > 1
}
return {
'items': items,
'pagination': pagination,
'query_info': query_info
}
def update_person(
db: Session,
person_id: int,
business_id: int,
person_data: PersonUpdateRequest
) -> Optional[Dict[str, Any]]:
"""ویرایش شخص"""
person = db.query(Person).filter(
and_(Person.id == person_id, Person.business_id == business_id)
).first()
if not person:
return None
# به‌روزرسانی فیلدها
update_data = person_data.dict(exclude_unset=True)
for field, value in update_data.items():
setattr(person, field, value)
db.commit()
db.refresh(person)
return success_response(
message="شخص با موفقیت ویرایش شد",
data=_person_to_dict(person)
)
def delete_person(db: Session, person_id: int, business_id: int) -> bool:
"""حذف شخص"""
person = db.query(Person).filter(
and_(Person.id == person_id, Person.business_id == business_id)
).first()
if not person:
return False
db.delete(person)
db.commit()
return True
def get_person_summary(db: Session, business_id: int) -> Dict[str, Any]:
"""دریافت خلاصه اشخاص"""
# تعداد کل اشخاص
total_persons = db.query(Person).filter(Person.business_id == business_id).count()
# تعداد اشخاص فعال و غیرفعال
active_persons = db.query(Person).filter(
and_(Person.business_id == business_id, Person.is_active == True)
).count()
inactive_persons = total_persons - active_persons
# تعداد بر اساس نوع
by_type = {}
for person_type in PersonType:
count = db.query(Person).filter(
and_(Person.business_id == business_id, Person.person_type == person_type)
).count()
by_type[person_type.value] = count
return {
'total_persons': total_persons,
'by_type': by_type,
'active_persons': active_persons,
'inactive_persons': inactive_persons
}
def _person_to_dict(person: Person) -> Dict[str, Any]:
"""تبدیل مدل Person به دیکشنری"""
return {
'id': person.id,
'business_id': person.business_id,
'alias_name': person.alias_name,
'first_name': person.first_name,
'last_name': person.last_name,
'person_type': person.person_type.value,
'company_name': person.company_name,
'payment_id': person.payment_id,
'national_id': person.national_id,
'registration_number': person.registration_number,
'economic_id': person.economic_id,
'country': person.country,
'province': person.province,
'city': person.city,
'address': person.address,
'postal_code': person.postal_code,
'phone': person.phone,
'mobile': person.mobile,
'fax': person.fax,
'email': person.email,
'website': person.website,
'is_active': person.is_active,
'created_at': person.created_at.isoformat(),
'updated_at': person.updated_at.isoformat(),
'bank_accounts': [
{
'id': ba.id,
'person_id': ba.person_id,
'bank_name': ba.bank_name,
'account_number': ba.account_number,
'card_number': ba.card_number,
'sheba_number': ba.sheba_number,
'is_active': ba.is_active,
'created_at': ba.created_at.isoformat(),
'updated_at': ba.updated_at.isoformat(),
}
for ba in person.bank_accounts
]
}