Coverage for functions \ flipdare \ firestore \ issue_db.py: 92%
39 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-05-08 12:22 +1000
« prev ^ index » next coverage.py v7.13.0, created at 2026-05-08 12:22 +1000
1#!/usr/bin/env python
2# Copyright (c) 2026 Flipdare Pty Ltd. All rights reserved.
3#
4# This file is part of Flipdare's proprietary software and contains
5# confidential and copyrighted material. Unauthorised copying,
6# modification, distribution, or use of this file is strictly
7# prohibited without prior written permission from Flipdare Pty Ltd.
8#
9# This software includes third-party components licensed under MIT,
10# BSD, and Apache 2.0 licences. See THIRD_PARTY_NOTICES for details.
11#
14from google.cloud.firestore import Client as FirestoreClient
15from flipdare.app_log import LOG
16from flipdare.constants import IS_DEBUG
17from flipdare.error.app_error import DatabaseError
18from flipdare.firestore._app_db import AppDb
19from flipdare.firestore._app_sub_db import AppSubDb
20from flipdare.firestore.core.db_query import DbQuery, FieldOp, OrderByField, WhereField
21from flipdare.generated import AppErrorCode, IssueKeys, IssueProgress
22from flipdare.generated.model.issue.issue_comment_model import IssueCommentModel
23from flipdare.generated.model.issue.issue_model import IssueModel
24from flipdare.generated.shared.firestore_collections import FirestoreCollections
25from flipdare.util.time_util import TimeUtil
26from flipdare.wrapper import IssueCommentWrapper, IssueWrapper
28_ISSUE: str = FirestoreCollections.ISSUE.value
30__all__ = ["IssueDb"]
32_K = IssueKeys
33_OP = FieldOp
36class IssueDb(AppDb[IssueWrapper, IssueModel]):
37 """Class for managing issue-related database operations."""
39 def __init__(self, client: FirestoreClient) -> None:
40 super().__init__(
41 client=client,
42 collection_name=FirestoreCollections.ISSUE,
43 model_class=IssueModel,
44 wrapper_class=IssueWrapper,
45 )
47 self.comments = AppSubDb[IssueCommentWrapper, IssueCommentModel](
48 client=client,
49 collection_name=FirestoreCollections.ISSUE,
50 sub_collection_name=FirestoreCollections.ISSUE_COMMENTS,
51 wrapper_class=IssueCommentWrapper,
52 model_class=IssueCommentModel,
53 )
55 def get_recent_waiting_admin(self, hours: int = 4) -> list[IssueWrapper]:
56 """
57 Get issues that are waiting for admin review in the last 4 hours
58 """
59 hours_ago = TimeUtil.get_utc_time_hours_ago(hours)
60 debug_str = (
61 f"Getting issues waiting for admin review within last "
62 f"{TimeUtil.formatted_dt(hours_ago)}"
63 )
64 LOG().info(debug_str)
66 progresses = [IssueProgress.OPEN.value, IssueProgress.WAITING_ADMIN.value]
67 progresses_str = list(progresses)
69 try:
70 where_fields = [
71 WhereField[_K](_K.CREATED_AT, _OP.GREATER_THAN_OR_EQUAL, hours_ago),
72 WhereField[_K](_K.PROGRESS, _OP.IN, progresses_str),
73 ]
74 order_by = OrderByField.created_at(descending=False)
75 query = DbQuery.and_(where_fields, order_by=order_by)
77 results = query.get_query(self.client, _ISSUE).stream()
78 issues = [
79 issue for doc in results if (issue := self._cvt_snap_to_model(doc)) is not None
80 ]
81 if IS_DEBUG:
82 LOG().debug(f"Retrieved {len(issues)} issues waiting for admin review.")
84 return issues
85 except Exception as e:
86 msg = f"Failed to get issues waiting for admin review: {e}"
87 raise DatabaseError(
88 message=msg,
89 error_code=AppErrorCode.DATABASE,
90 collection_name=self.collection_name,
91 ) from e