base.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. """报销模块 Service 基类 — 租户隔离 + UUID + 软删除。"""
  2. from __future__ import annotations
  3. from typing import TYPE_CHECKING, Any, List, Optional, Sequence, Tuple, Type, TypeVar
  4. from sqlalchemy.orm import Session
  5. from app.core.utils import generate_uuid
  6. from app.core.delete_guard import assert_row_deletable_by_creator, user_info_from_context
  7. from app.services.bx_data_scope import apply_bx_scope, assert_bx_row_in_scope
  8. if TYPE_CHECKING:
  9. from app.core.bx_auth import BxUserContext
  10. M = TypeVar("M")
  11. class BxCrudService:
  12. @staticmethod
  13. def get_by_id(
  14. model: Type[M],
  15. db: Session,
  16. id: str,
  17. tenant_no: str,
  18. *,
  19. user: Optional["BxUserContext"] = None,
  20. skip_scope: bool = False,
  21. ) -> Optional[M]:
  22. query = db.query(model).filter(model.id == id, model.tenant_no == tenant_no)
  23. if hasattr(model, "del_flag"):
  24. query = query.filter(model.del_flag == 0)
  25. row = query.first()
  26. if row and user and not skip_scope:
  27. assert_bx_row_in_scope(db, row, model, user, tenant_no)
  28. return row
  29. @staticmethod
  30. def get_paged(
  31. model: Type[M],
  32. db: Session,
  33. tenant_no: str,
  34. page: int,
  35. page_size: int,
  36. filters: Optional[List[Any]] = None,
  37. *,
  38. user: Optional["BxUserContext"] = None,
  39. skip_scope: bool = False,
  40. ) -> Tuple[Sequence[M], int]:
  41. query = db.query(model).filter(model.tenant_no == tenant_no)
  42. if hasattr(model, "del_flag"):
  43. query = query.filter(model.del_flag == 0)
  44. if filters:
  45. query = query.filter(*filters)
  46. if user and not skip_scope:
  47. query = apply_bx_scope(query, model, user, db, tenant_no)
  48. total = query.count()
  49. if hasattr(model, "sort_order"):
  50. query = query.order_by(model.sort_order.asc(), model.create_time.desc())
  51. else:
  52. query = query.order_by(model.create_time.desc())
  53. rows = query.offset((page - 1) * page_size).limit(page_size).all()
  54. return rows, total
  55. @staticmethod
  56. def create(
  57. model: Type[M],
  58. db: Session,
  59. obj_in: dict,
  60. *,
  61. tenant_no: str,
  62. user_id: str,
  63. dept_id: str,
  64. ) -> M:
  65. data = dict(obj_in)
  66. data.setdefault("id", generate_uuid())
  67. data["tenant_no"] = tenant_no
  68. data["create_by"] = user_id
  69. data["create_dept_id"] = dept_id or ""
  70. obj = model(**data)
  71. db.add(obj)
  72. db.flush()
  73. return obj
  74. @staticmethod
  75. def update(
  76. model: Type[M],
  77. db: Session,
  78. id: str,
  79. tenant_no: str,
  80. obj_in: dict,
  81. *,
  82. user_id: str,
  83. user: Optional["BxUserContext"] = None,
  84. skip_scope: bool = False,
  85. ) -> Optional[M]:
  86. obj = BxCrudService.get_by_id(
  87. model, db, id, tenant_no, user=user, skip_scope=skip_scope
  88. )
  89. if not obj:
  90. return None
  91. for key, value in obj_in.items():
  92. setattr(obj, key, value)
  93. if hasattr(obj, "update_by"):
  94. obj.update_by = user_id
  95. db.flush()
  96. return obj
  97. @staticmethod
  98. def soft_delete(
  99. model: Type[M],
  100. db: Session,
  101. id: str,
  102. tenant_no: str,
  103. *,
  104. user_id: str = "",
  105. user: Optional["BxUserContext"] = None,
  106. skip_scope: bool = False,
  107. ) -> bool:
  108. obj = BxCrudService.get_by_id(
  109. model, db, id, tenant_no, user=user, skip_scope=skip_scope
  110. )
  111. if not obj:
  112. return False
  113. if user:
  114. assert_row_deletable_by_creator(obj, user_info_from_context(user))
  115. elif user_id:
  116. assert_row_deletable_by_creator(obj, {"user_id": user_id})
  117. obj.del_flag = 1
  118. if hasattr(obj, "update_by") and user_id:
  119. obj.update_by = user_id
  120. db.flush()
  121. return True