| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- from sqlalchemy import select
- from app.domains.enrollment.models import (
- AsyncTask,
- EnrollmentDraft,
- EnrollmentOrder,
- OutboxEvent,
- PaymentTransaction,
- Policy,
- Quote,
- UserConfirmation,
- )
- from app.domains.enrollment.repository import EnrollmentRepository
- from app.infrastructure.mysql.core_models import (
- AsyncTaskRecord,
- EnrollmentDraftRecord,
- EnrollmentOrderRecord,
- OutboxEventRecord,
- PaymentTransactionRecord,
- PolicyRecord,
- QuoteRecord,
- UserConfirmationRecord,
- )
- from app.infrastructure.mysql.repositories import SessionFactory
- class SqlAlchemyEnrollmentRepository(EnrollmentRepository):
- def __init__(self, session_factory: SessionFactory) -> None:
- self._session_factory = session_factory
- def save_quote(self, quote: Quote) -> None:
- with self._session_factory() as session:
- session.merge(
- QuoteRecord(
- id=quote.id,
- h5_user_id=quote.user_id,
- product_id=quote.product_id,
- product_version_id=quote.product_version_id,
- plan_id=quote.plan_id,
- insured_age=quote.insured_age,
- insured_region_code=quote.insured_region_code,
- occupation_code=quote.occupation_code,
- relationship=quote.relationship,
- premium_cents=quote.premium_cents,
- currency=quote.currency,
- rule_version=quote.rule_version,
- rate_version=quote.rate_version,
- status=quote.status,
- expires_at=quote.expires_at,
- created_at=quote.created_at,
- )
- )
- session.commit()
- def get_quote(self, quote_id: str) -> Quote | None:
- with self._session_factory() as session:
- record = session.get(QuoteRecord, quote_id)
- return self._quote(record) if record else None
- def save_draft(self, draft: EnrollmentDraft) -> None:
- with self._session_factory() as session:
- session.merge(
- EnrollmentDraftRecord(
- id=draft.id,
- h5_user_id=draft.user_id,
- quote_id=draft.quote_id,
- applicant_json=draft.applicant,
- insured_json=draft.insured,
- contact_json=draft.contact,
- status=draft.status,
- expires_at=draft.expires_at,
- created_at=draft.created_at,
- )
- )
- session.commit()
- def get_draft(self, draft_id: str) -> EnrollmentDraft | None:
- with self._session_factory() as session:
- record = session.get(EnrollmentDraftRecord, draft_id)
- return self._draft(record) if record else None
- def save_confirmation(self, confirmation: UserConfirmation) -> None:
- with self._session_factory() as session:
- session.merge(
- UserConfirmationRecord(
- id=confirmation.id,
- h5_user_id=confirmation.user_id,
- draft_id=confirmation.draft_id,
- token_hash=confirmation.token_hash,
- status=confirmation.status,
- expires_at=confirmation.expires_at,
- created_at=confirmation.created_at,
- )
- )
- session.commit()
- def get_confirmation_by_token_hash(self, token_hash: str) -> UserConfirmation | None:
- with self._session_factory() as session:
- record = session.scalar(
- select(UserConfirmationRecord).where(
- UserConfirmationRecord.token_hash == token_hash
- )
- )
- return self._confirmation(record) if record else None
- def save_order(self, order: EnrollmentOrder) -> None:
- with self._session_factory() as session:
- session.merge(
- EnrollmentOrderRecord(
- id=order.id,
- order_no=order.order_no,
- h5_user_id=order.user_id,
- quote_id=order.quote_id,
- draft_id=order.draft_id,
- confirmation_id=order.confirmation_id,
- idempotency_key=order.idempotency_key,
- product_id=order.product_id,
- product_version_id=order.product_version_id,
- plan_id=order.plan_id,
- applicant_snapshot_json=order.applicant_snapshot,
- insured_snapshot_json=order.insured_snapshot,
- amount_cents=order.amount_cents,
- currency=order.currency,
- status=order.status,
- created_at=order.created_at,
- )
- )
- session.commit()
- def get_order(self, order_id: str) -> EnrollmentOrder | None:
- with self._session_factory() as session:
- record = session.get(EnrollmentOrderRecord, order_id)
- return self._order(record) if record else None
- def find_order_by_idempotency(
- self, user_id: str, idempotency_key: str
- ) -> EnrollmentOrder | None:
- with self._session_factory() as session:
- record = session.scalar(
- select(EnrollmentOrderRecord).where(
- EnrollmentOrderRecord.h5_user_id == user_id,
- EnrollmentOrderRecord.idempotency_key == idempotency_key,
- )
- )
- return self._order(record) if record else None
- def list_orders(self, user_id: str | None = None) -> list[EnrollmentOrder]:
- with self._session_factory() as session:
- statement = select(EnrollmentOrderRecord).order_by(
- EnrollmentOrderRecord.created_at.desc()
- )
- if user_id is not None:
- statement = statement.where(EnrollmentOrderRecord.h5_user_id == user_id)
- return [self._order(record) for record in session.scalars(statement)]
- def save_payment(self, payment: PaymentTransaction) -> None:
- with self._session_factory() as session:
- session.merge(
- PaymentTransactionRecord(
- id=payment.id,
- payment_no=payment.payment_no,
- order_id=payment.order_id,
- h5_user_id=payment.user_id,
- transaction_type=payment.transaction_type,
- provider=payment.provider,
- idempotency_key=payment.idempotency_key,
- amount_cents=payment.amount_cents,
- currency=payment.currency,
- status=payment.status,
- provider_transaction_no=payment.provider_transaction_no,
- succeeded_at=payment.succeeded_at,
- created_at=payment.created_at,
- )
- )
- session.commit()
- def get_payment(self, payment_id: str) -> PaymentTransaction | None:
- with self._session_factory() as session:
- record = session.get(PaymentTransactionRecord, payment_id)
- return self._payment(record) if record else None
- def get_payment_by_no(self, payment_no: str) -> PaymentTransaction | None:
- with self._session_factory() as session:
- record = session.scalar(
- select(PaymentTransactionRecord).where(
- PaymentTransactionRecord.payment_no == payment_no
- )
- )
- return self._payment(record) if record else None
- def get_payment_by_order(self, order_id: str) -> PaymentTransaction | None:
- with self._session_factory() as session:
- record = session.scalar(
- select(PaymentTransactionRecord).where(
- PaymentTransactionRecord.order_id == order_id
- )
- )
- return self._payment(record) if record else None
- def find_payment_by_idempotency(
- self, order_id: str, idempotency_key: str
- ) -> PaymentTransaction | None:
- with self._session_factory() as session:
- record = session.scalar(
- select(PaymentTransactionRecord).where(
- PaymentTransactionRecord.order_id == order_id,
- PaymentTransactionRecord.idempotency_key == idempotency_key,
- )
- )
- return self._payment(record) if record else None
- def save_policy(self, policy: Policy) -> None:
- with self._session_factory() as session:
- session.merge(
- PolicyRecord(
- id=policy.id,
- policy_no=policy.policy_no,
- order_id=policy.order_id,
- h5_user_id=policy.user_id,
- product_id=policy.product_id,
- product_version_id=policy.product_version_id,
- plan_id=policy.plan_id,
- premium_cents=policy.premium_cents,
- currency=policy.currency,
- coverage_start=policy.coverage_start,
- coverage_end=policy.coverage_end,
- status=policy.status,
- issued_at=policy.issued_at,
- )
- )
- session.commit()
- def get_policy_by_order(self, order_id: str) -> Policy | None:
- with self._session_factory() as session:
- record = session.scalar(select(PolicyRecord).where(PolicyRecord.order_id == order_id))
- return self._policy(record) if record else None
- def list_policies(self, user_id: str | None = None) -> list[Policy]:
- with self._session_factory() as session:
- statement = select(PolicyRecord).order_by(PolicyRecord.issued_at.desc())
- if user_id is not None:
- statement = statement.where(PolicyRecord.h5_user_id == user_id)
- return [self._policy(record) for record in session.scalars(statement)]
- def save_outbox_event(self, event: OutboxEvent) -> None:
- with self._session_factory() as session:
- session.merge(
- OutboxEventRecord(
- id=event.id,
- aggregate_type=event.aggregate_type,
- aggregate_id=event.aggregate_id,
- event_type=event.event_type,
- payload_json=event.payload,
- status=event.status,
- created_at=event.created_at,
- )
- )
- session.commit()
- def save_task(self, task: AsyncTask) -> None:
- with self._session_factory() as session:
- session.merge(
- AsyncTaskRecord(
- id=task.id,
- task_type=task.task_type,
- business_key=task.business_key,
- idempotency_key=task.idempotency_key,
- payload_json=task.payload,
- status=task.status,
- attempt_count=task.attempt_count,
- created_at=task.created_at,
- )
- )
- session.commit()
- def get_task_by_idempotency(self, idempotency_key: str) -> AsyncTask | None:
- with self._session_factory() as session:
- record = session.scalar(
- select(AsyncTaskRecord).where(AsyncTaskRecord.idempotency_key == idempotency_key)
- )
- if record is None:
- return None
- return AsyncTask(
- id=record.id,
- task_type=record.task_type,
- business_key=record.business_key,
- idempotency_key=record.idempotency_key,
- payload=dict(record.payload_json),
- status=record.status,
- attempt_count=record.attempt_count,
- created_at=record.created_at,
- )
- @staticmethod
- def _quote(record: QuoteRecord) -> Quote:
- return Quote(
- id=record.id,
- user_id=record.h5_user_id,
- product_id=record.product_id,
- product_version_id=record.product_version_id,
- plan_id=record.plan_id,
- insured_age=record.insured_age,
- insured_region_code=record.insured_region_code,
- occupation_code=record.occupation_code,
- relationship=record.relationship,
- premium_cents=record.premium_cents,
- currency=record.currency,
- rule_version=record.rule_version,
- rate_version=record.rate_version,
- status=record.status,
- expires_at=record.expires_at,
- created_at=record.created_at,
- )
- @staticmethod
- def _draft(record: EnrollmentDraftRecord) -> EnrollmentDraft:
- return EnrollmentDraft(
- id=record.id,
- user_id=record.h5_user_id,
- quote_id=record.quote_id,
- applicant=dict(record.applicant_json),
- insured=dict(record.insured_json),
- contact=dict(record.contact_json),
- status=record.status,
- expires_at=record.expires_at,
- created_at=record.created_at,
- )
- @staticmethod
- def _confirmation(record: UserConfirmationRecord) -> UserConfirmation:
- return UserConfirmation(
- id=record.id,
- user_id=record.h5_user_id,
- draft_id=record.draft_id,
- token_hash=record.token_hash,
- status=record.status,
- expires_at=record.expires_at,
- created_at=record.created_at,
- )
- @staticmethod
- def _order(record: EnrollmentOrderRecord) -> EnrollmentOrder:
- return EnrollmentOrder(
- id=record.id,
- order_no=record.order_no,
- user_id=record.h5_user_id,
- quote_id=record.quote_id,
- draft_id=record.draft_id,
- confirmation_id=record.confirmation_id,
- idempotency_key=record.idempotency_key,
- product_id=record.product_id,
- product_version_id=record.product_version_id,
- plan_id=record.plan_id,
- applicant_snapshot=dict(record.applicant_snapshot_json),
- insured_snapshot=dict(record.insured_snapshot_json),
- amount_cents=record.amount_cents,
- currency=record.currency,
- status=record.status,
- created_at=record.created_at,
- )
- @staticmethod
- def _payment(record: PaymentTransactionRecord) -> PaymentTransaction:
- return PaymentTransaction(
- id=record.id,
- payment_no=record.payment_no,
- order_id=record.order_id,
- user_id=record.h5_user_id,
- transaction_type=record.transaction_type,
- provider=record.provider,
- idempotency_key=record.idempotency_key,
- amount_cents=record.amount_cents,
- currency=record.currency,
- status=record.status,
- provider_transaction_no=record.provider_transaction_no,
- succeeded_at=record.succeeded_at,
- created_at=record.created_at,
- )
- @staticmethod
- def _policy(record: PolicyRecord) -> Policy:
- return Policy(
- id=record.id,
- policy_no=record.policy_no,
- order_id=record.order_id,
- user_id=record.h5_user_id,
- product_id=record.product_id,
- product_version_id=record.product_version_id,
- plan_id=record.plan_id,
- premium_cents=record.premium_cents,
- currency=record.currency,
- coverage_start=record.coverage_start,
- coverage_end=record.coverage_end,
- status=record.status,
- issued_at=record.issued_at,
- )
|