codegen.py 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. """Generate business codes like BYJ20260424001 / BX20260424001."""
  2. from datetime import datetime
  3. from sqlalchemy.orm import Session
  4. from sqlalchemy import text
  5. def _date_yyyymmdd(apply_date: str | None = None) -> str:
  6. if apply_date and str(apply_date).strip():
  7. try:
  8. return datetime.strptime(str(apply_date).strip(), "%Y-%m-%d").strftime("%Y%m%d")
  9. except ValueError:
  10. pass
  11. return datetime.now().strftime("%Y%m%d")
  12. def generate_apply_code(db: Session, prefix: str, apply_date: str | None = None) -> str:
  13. """
  14. Generate a sequential code: {prefix}{YYYYMMDD}{3-digit-sequence}.
  15. prefix examples: 'BYJ' for advance, 'BX' for reimburse.
  16. Thread-safe via DB-level auto-increment fallback.
  17. """
  18. today = _date_yyyymmdd(apply_date)
  19. like_pattern = f"{prefix}{today}%"
  20. # Find the max sequence number for today
  21. result = db.execute(
  22. text("SELECT MAX(CAST(SUBSTRING(apply_code, -3) AS UNSIGNED)) FROM ("
  23. "SELECT apply_code FROM bx_advance_apply WHERE apply_code LIKE :p1 "
  24. "UNION ALL "
  25. "SELECT apply_code FROM bx_reimburse_apply WHERE apply_code LIKE :p2"
  26. ") t"),
  27. {"p1": like_pattern, "p2": like_pattern}
  28. ).scalar()
  29. seq = (result or 0) + 1
  30. return f"{prefix}{today}{seq:03d}"
  31. def generate_title(db: Session, applicant_name: str, apply_date: str | None = None) -> str:
  32. date_str = _date_yyyymmdd(apply_date)
  33. like_pattern = f"%报销单{date_str}%"
  34. result = db.execute(
  35. text(
  36. "SELECT MAX(CAST(RIGHT(title, 3) AS UNSIGNED)) FROM bx_reimburse_apply "
  37. "WHERE del_flag = 0 AND title LIKE :p"
  38. ),
  39. {"p": like_pattern},
  40. ).scalar()
  41. seq = (result or 0) + 1
  42. return f"{applicant_name}报销单{date_str}{seq:03d}"