This is an automated email from the ASF dual-hosted git repository.

gstein pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/steve.git

commit c4f7cd8fd41f955e2544f483daa4a16f8c418b8c
Author: Greg Stein <[email protected]>
AuthorDate: Fri Feb 20 02:03:55 2026 -0600

    feat: add upcoming_to_pid method and q_upcoming_to_me query
    
    Co-authored-by: aider (openrouter/x-ai/grok-code-fast-1) <[email protected]>
---
 v3/queries.yaml      | 23 +++++++++++++++++++++++
 v3/steve/election.py | 14 +++++++++++++-
 2 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/v3/queries.yaml b/v3/queries.yaml
index 363356e..01c831d 100644
--- a/v3/queries.yaml
+++ b/v3/queries.yaml
@@ -135,6 +135,29 @@ election:
                owner_pid, (opened_key IS NOT NULL) AS is_opened
         FROM election WHERE owner_pid = ?
 
+    # Returns all editable elections for voting by the specified person (PID).
+    # An election is included if:
+    #   - The person has mayvote entries for any issues in the election
+    #   - The election is editable (salt IS NULL)
+    # 
+    # Uses LEFT JOIN to person table to fetch the owner's name for display,
+    # ensuring elections are still returned even if the owner_pid does not
+    # exist in the person table (in which case owner_name will be NULL).
+    # 
+    # Returns: eid, title, open_at, close_at, issue_count, owner_name
+    q_upcoming_to_me: |
+        SELECT e.eid, e.title, e.open_at, e.close_at,
+               COUNT(i.iid) AS issue_count,
+               p.name AS owner_name
+        FROM mayvote m
+        JOIN issue i ON m.iid = i.iid
+        JOIN election e ON i.eid = e.eid
+        LEFT JOIN person p ON e.owner_pid = p.pid
+        WHERE m.pid = ?
+          AND e.salt IS NULL
+        GROUP BY e.eid
+        ORDER BY e._ROWID_
+
 
 person:
     c_add_person: |
diff --git a/v3/steve/election.py b/v3/steve/election.py
index 0b06f35..8d74d3f 100644
--- a/v3/steve/election.py
+++ b/v3/steve/election.py
@@ -484,6 +484,18 @@ class Election:
         )
         return [row for row in db.q_owned.fetchall()]
 
+    @classmethod
+    def upcoming_to_pid(cls, db_fname, pid):
+        "List of editable elections for PID to vote upon."
+
+        db = cls.open_database(db_fname)
+
+        # Run the generator to get all rows. Returned as EasyDicts.
+        db.q_upcoming_to_me.perform(
+            pid,
+        )
+        return [row for row in db.q_upcoming_to_me.fetchall()]
+
     def set_open_at(self, timestamp):
         "Set the open_at timestamp for this Election."
         self.c_set_open_at.perform(timestamp, self.eid)
@@ -527,4 +539,4 @@ class IssueNotFound(Exception):
         super().__init__(str(self))
 
     def __str__(self):
-        return f'Issue[I:{self.iid}] not found'
+        return f'Issue[I:{iid}] not found'

Reply via email to