bsw/jbe@0: Issue = mondelefant.new_class() bsw/jbe@0: Issue.table = 'issue' bsw/jbe@0: bsw/jbe@0: Issue:add_reference{ bsw/jbe@0: mode = 'm1', bsw/jbe@0: to = "Area", bsw/jbe@0: this_key = 'area_id', bsw/jbe@0: that_key = 'id', bsw/jbe@0: ref = 'area', bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Issue:add_reference{ bsw/jbe@0: mode = 'm1', bsw/jbe@0: to = "Policy", bsw/jbe@0: this_key = 'policy_id', bsw/jbe@0: that_key = 'id', bsw/jbe@0: ref = 'policy', bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Issue:add_reference{ bsw/jbe@0: mode = '1m', bsw/jbe@0: to = "Initiative", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'issue_id', bsw/jbe@0: ref = 'initiatives', bsw@211: back_ref = 'issue', bsw@211: default_order = 'initiative.rank, initiative.admitted ISNULL, initiative.admitted DESC, initiative.positive_votes::float / initiative.negative_votes::float DESC, initiative.supporter_count DESC' bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Issue:add_reference{ bsw/jbe@0: mode = '1m', bsw/jbe@0: to = "Interest", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'issue_id', bsw/jbe@0: ref = 'interests', bsw/jbe@0: back_ref = 'issue', bsw/jbe@0: default_order = '"id"' bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Issue:add_reference{ bsw/jbe@0: mode = '1m', bsw/jbe@0: to = "Supporter", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'issue_id', bsw/jbe@0: ref = 'supporters', bsw/jbe@0: back_ref = 'issue', bsw/jbe@0: default_order = '"id"' bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Issue:add_reference{ bsw/jbe@0: mode = '1m', bsw/jbe@0: to = "DirectVoter", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'issue_id', bsw/jbe@0: ref = 'direct_voters', bsw/jbe@0: back_ref = 'issue', bsw/jbe@0: default_order = '"member_id"' bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Issue:add_reference{ bsw/jbe@0: mode = '1m', bsw/jbe@0: to = "Vote", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'issue_id', bsw/jbe@0: ref = 'votes', bsw/jbe@0: back_ref = 'issue', bsw/jbe@0: default_order = '"member_id", "initiative_id"' bsw/jbe@0: } bsw/jbe@0: bsw/jbe@0: Issue:add_reference{ bsw@2: mode = '1m', bsw@2: to = "Delegation", bsw@2: this_key = 'id', bsw@2: that_key = 'issue_id', bsw@2: ref = 'delegations', bsw@2: back_ref = 'issue' bsw@2: } bsw@2: bsw@2: Issue:add_reference{ bsw/jbe@0: mode = 'mm', bsw/jbe@0: to = "Member", bsw/jbe@0: this_key = 'id', bsw/jbe@0: that_key = 'id', bsw/jbe@0: connected_by_table = 'interest', bsw/jbe@0: connected_by_this_key = 'issue_id', bsw/jbe@0: connected_by_that_key = 'member_id', bsw/jbe@0: ref = 'members' bsw/jbe@0: } bsw@211: --[[ bsw@3: Issue:add_reference{ bsw@3: mode = 'mm', bsw@3: to = "Member", bsw@3: this_key = 'id', bsw@3: that_key = 'id', bsw@3: connected_by_table = 'direct_interest_snapshot', bsw@3: connected_by_this_key = 'issue_id', bsw@3: connected_by_that_key = 'member_id', bsw@3: ref = 'interested_members_snapshot' bsw@3: } bsw@211: --]] bsw/jbe@6: Issue:add_reference{ bsw/jbe@6: mode = 'mm', bsw/jbe@6: to = "Member", bsw/jbe@6: this_key = 'id', bsw/jbe@6: that_key = 'id', bsw/jbe@6: connected_by_table = 'direct_voter', bsw/jbe@6: connected_by_this_key = 'issue_id', bsw/jbe@6: connected_by_that_key = 'member_id', bsw/jbe@6: ref = 'direct_voters' bsw/jbe@6: } bsw/jbe@6: bsw@211: Issue:add_reference{ bsw@211: mode = 'mm', bsw@211: to = "Member", bsw@211: this_key = 'id', bsw@211: that_key = 'id', bsw@211: connected_by_table = 'direct_interest_snapshot', bsw@211: connected_by_this_key = 'issue_id', bsw@211: connected_by_that_key = 'member_id', bsw@211: ref = 'interested_members_snapshot', bsw@211: selector_generator = function(list, options) bsw@211: -- build list of issue ids bsw@211: local ids = { sep = ", " } bsw@211: for i, object in ipairs(list) do bsw@211: local id = object.id bsw@211: if id ~= nil then bsw@211: ids[#ids+1] = {"?", id} bsw@211: end bsw@211: end bsw@211: bsw@211: if #ids == 0 then bsw@211: return Member:new_selector():empty_list_mode() bsw@211: end bsw@211: bsw@211: local selector = Member:new_selector() bsw@211: selector:join("direct_interest_snapshot", nil, { "direct_interest_snapshot.member_id = member.id AND direct_interest_snapshot.issue_id IN ($)", ids }) bsw@211: selector:join("issue", nil, "direct_interest_snapshot.issue_id = issue.id AND direct_interest_snapshot.event = issue.latest_snapshot_event") bsw@211: selector:add_order_by('direct_interest_snapshot.weight DESC') bsw@211: return selector bsw@211: end bsw@211: } bsw@211: bsw@211: Issue:add_reference{ bsw@211: mode = '11', bsw@211: to = "DelegatingInterestSnapshot", bsw@211: this_key = 'id', bsw@211: that_key = 'issue_id', bsw@211: ref = 'delegating_interest_snapshot_for_member', bsw@211: back_ref = 'issue', bsw@211: selector_generator = function(list, options) bsw@211: local member_id = assert(options.member_id) bsw@211: bsw@211: -- build list of issue ids bsw@211: local ids = { sep = ", " } bsw@211: for i, object in ipairs(list) do bsw@211: local id = object.id bsw@211: if id ~= nil then bsw@211: ids[#ids+1] = {"?", id} bsw@211: end bsw@211: end bsw@211: bsw@211: if #ids == 0 then bsw@211: return DelegatingInterestSnapshot:new_selector():empty_list_mode() bsw@211: end bsw@211: bsw@211: local selector = DelegatingInterestSnapshot:new_selector() bsw@211: selector:join("issue", nil, "delegating_interest_snapshot.issue_id = issue.id AND delegating_interest_snapshot.event = issue.latest_snapshot_event") bsw@211: selector:add_where{ 'delegating_interest_snapshot.issue_id IN ($)', ids } bsw@212: selector:add_where{ 'delegating_interest_snapshot.member_id = ?', member_id } bsw@211: bsw@211: return selector bsw@211: end bsw@211: } bsw@211: bsw@211: Issue:add_reference{ bsw@211: mode = '11', bsw@211: to = "Interest", bsw@211: this_key = 'id', bsw@211: that_key = 'issue_id', bsw@211: ref = 'interest_for_member', bsw@211: back_ref = 'issue', bsw@211: selector_generator = function(list, options) bsw@211: bsw@211: local member_id = assert(options.member_id) bsw@211: bsw@211: -- build list of issue ids bsw@211: local ids = { sep = ", " } bsw@211: for i, object in ipairs(list) do bsw@211: local id = object.id bsw@211: if id ~= nil then bsw@211: ids[#ids+1] = {"?", id} bsw@211: end bsw@211: end bsw@211: bsw@211: if #ids == 0 then bsw@211: return Interest:new_selector():empty_list_mode() bsw@211: end bsw@211: bsw@211: local selector = Interest:new_selector() bsw@211: selector:add_where{ 'interest.issue_id IN ($)', ids } bsw@211: selector:add_where{ 'interest.member_id = ?', member_id } bsw@211: return selector bsw@211: bsw@211: end bsw@211: } bsw@211: bsw@211: Issue:add_reference{ bsw@211: mode = '1m', bsw@211: to = "Delegation", bsw@211: this_key = 'id', bsw@211: that_key = 'issue_id', bsw@211: ref = 'outgoing_delegations_for_member', bsw@211: back_ref = 'issue', bsw@211: selector_generator = function(list, options) bsw@211: bsw@211: local member_id = assert(options.member_id) bsw@211: bsw@211: -- build list of issue ids bsw@211: local ids = { sep = ", " } bsw@211: for i, object in ipairs(list) do bsw@211: local id = object.id bsw@211: if id ~= nil then bsw@211: ids[#ids+1] = {"?", id} bsw@211: end bsw@211: end bsw@211: bsw@211: if #ids == 0 then bsw@211: return Delegation:new_selector():empty_list_mode() bsw@211: end bsw@211: bsw@211: local selector = Delegation:new_selector() bsw@211: selector:add_where{ 'delegation.issue_id IN ($)', ids } bsw@211: selector:add_where{ 'delegation.truster_id = ?', member_id } bsw@211: return selector bsw@211: bsw@211: end bsw@211: } bsw@211: bsw@216: Issue:add_reference{ bsw@216: mode = 'mm', bsw@216: to = "Member", bsw@216: this_key = 'id', bsw@216: that_key = 'mm_ref_', bsw@216: ref = 'trusters_for_member', bsw@216: back_ref = 'issue', bsw@216: selector_generator = function(list, options) bsw@216: bsw@216: local member_id = assert(options.member_id) bsw@216: bsw@216: -- build list of issue ids bsw@216: local ids = { sep = ", " } bsw@216: for i, object in ipairs(list) do bsw@216: local id = object.id bsw@216: if id ~= nil then bsw@216: ids[#ids+1] = {"?", id} bsw@216: end bsw@216: end bsw@216: bsw@216: if #ids == 0 then bsw@216: return Delegation:new_selector():empty_list_mode() bsw@216: end bsw@216: bsw@216: local selector = Member:new_selector() bsw@216: selector:join("delegating_interest_snapshot", nil, { "delegating_interest_snapshot.delegate_member_ids[1] = ? AND delegating_interest_snapshot.member_id = member.id", member_id }) bsw@216: selector:join("issue", nil, "delegating_interest_snapshot.issue_id = issue.id AND delegating_interest_snapshot.event = issue.latest_snapshot_event") bsw@216: selector:add_where{ 'delegating_interest_snapshot.issue_id IN ($)', ids } bsw@216: selector:add_field("delegating_interest_snapshot.issue_id", "mm_ref_") bsw@216: selector:add_field("delegating_interest_snapshot.weight", "weight") bsw@216: selector:add_order_by("delegating_interest_snapshot.weight DESC, member.id") bsw@216: return selector bsw@216: bsw@216: end bsw@216: } bsw@216: bsw/jbe@6: bsw/jbe@6: bsw/jbe@0: function Issue:get_state_name_for_state(value) bsw@2: local state_name_table = { bsw@218: admission = _"New", bsw@3: accepted = _"Discussion", bsw@2: frozen = _"Frozen", bsw@2: voting = _"Voting", bsw@2: finished = _"Finished", bsw@218: cancelled = _"Cancelled", bsw@218: canceled_issue_not_accepted = _"Cancelled" bsw@2: } bsw@10: return state_name_table[value] or value or '' bsw/jbe@0: end bsw/jbe@0: bsw@2: function Issue:get_search_selector(search_string) bsw/jbe@0: return self:new_selector() bsw/jbe@0: :join('"initiative"', nil, '"initiative"."issue_id" = "issue"."id"') bsw/jbe@6: :join('"draft"', nil, '"draft"."initiative_id" = "initiative"."id"') bsw/jbe@6: :add_where{ '"initiative"."text_search_data" @@ "text_search_query"(?) OR "draft"."text_search_data" @@ "text_search_query"(?)', search_string, search_string } bsw/jbe@6: :add_group_by('"issue"."id"') bsw/jbe@6: :add_group_by('"issue"."area_id"') bsw/jbe@6: :add_group_by('"issue"."policy_id"') bsw/jbe@6: :add_group_by('"issue"."created"') bsw/jbe@6: :add_group_by('"issue"."accepted"') bsw/jbe@6: :add_group_by('"issue"."half_frozen"') bsw/jbe@6: :add_group_by('"issue"."fully_frozen"') bsw/jbe@6: :add_group_by('"issue"."closed"') bsw/jbe@6: :add_group_by('"issue"."ranks_available"') poelzi@140: :add_group_by('"issue"."cleaned"') bsw/jbe@6: :add_group_by('"issue"."snapshot"') bsw/jbe@6: :add_group_by('"issue"."latest_snapshot_event"') bsw/jbe@6: :add_group_by('"issue"."population"') bsw/jbe@6: :add_group_by('"issue"."vote_now"') bsw/jbe@6: :add_group_by('"issue"."vote_later"') bsw/jbe@6: :add_group_by('"issue"."voter_count"') bsw@75: :add_group_by('"issue"."admission_time"') bsw@75: :add_group_by('"issue"."discussion_time"') bsw@75: :add_group_by('"issue"."verification_time"') bsw@75: :add_group_by('"issue"."voting_time"') bsw/jbe@19: :add_group_by('"_interest"."member_id"') bsw/jbe@6: --:set_distinct() bsw/jbe@0: end bsw/jbe@0: bsw@75: function Issue:modify_selector_for_state(initiatives_selector, state) bsw@51: if state == "new" then bsw@75: initiatives_selector:add_where("issue.accepted ISNULL AND issue.closed ISNULL") bsw@51: elseif state == "accepted" then bsw@75: initiatives_selector:add_where("issue.accepted NOTNULL AND issue.half_frozen ISNULL AND issue.closed ISNULL") bsw@51: elseif state == "frozen" then bsw@75: initiatives_selector:add_where("issue.half_frozen NOTNULL AND issue.fully_frozen ISNULL AND issue.closed ISNULL") bsw@51: elseif state == "voting" then bsw@75: initiatives_selector:add_where("issue.fully_frozen NOTNULL AND issue.closed ISNULL") bsw@51: elseif state == "finished" then bsw@75: initiatives_selector:add_where("issue.fully_frozen NOTNULL AND issue.closed NOTNULL") bsw@51: elseif state == "cancelled" then bsw@75: initiatives_selector:add_where("issue.fully_frozen ISNULL AND issue.closed NOTNULL") bsw@75: else bsw@75: error("Invalid state") bsw@51: end bsw@51: end bsw@51: bsw@211: function Issue:build_selector(args) bsw@211: local selector = self:new_selector() bsw@217: if args.unit_id then bsw@217: selector:join("area", nil, "area.id = issue.area_id") bsw@217: selector:add_where{ "area.unit_id = ?", args.unit_id } bsw@217: end bsw@211: if args.area_id then bsw@211: selector:add_where{ "issue.area_id = ?", args.area_id } bsw@211: end bsw@215: if args.phase == "closed" then bsw@211: selector:add_where("issue.closed NOTNULL") bsw@215: elseif args.phase == "voting" then bsw@211: selector:add_where("issue.fully_frozen NOTNULL AND issue.closed ISNULL") bsw@215: elseif args.phase == "frozen" then bsw@211: selector:add_where("issue.half_frozen NOTNULL AND issue.fully_frozen ISNULL AND issue.closed ISNULL") bsw@215: elseif args.phase == "discussion" then bsw@211: selector:add_where("issue.accepted NOTNULL AND issue.half_frozen ISNULL AND issue.closed ISNULL") bsw@215: elseif args.phase == "new" then bsw@211: selector:add_where("issue.accepted ISNULL AND issue.closed ISNULL") bsw@211: end bsw@211: if args.order == "time_left" then bsw@211: selector:add_order_by("issue.closed DESC") bsw@211: elseif args.order == "last_change" then bsw@211: selector:add_order_by("issue.closed DESC") bsw@211: elseif args.order == "interest" then bsw@211: selector:add_order_by("issue.population DESC") bsw@211: end bsw@211: bsw@211: return selector bsw@211: end bsw@211: bsw@218: --[[ bsw/jbe@0: function Issue.object_get:state() bsw/jbe@52: if self.closed then bsw/jbe@52: if self.fully_frozen then bsw/jbe@5: return "finished" bsw/jbe@0: else bsw/jbe@52: return "cancelled" bsw/jbe@0: end bsw/jbe@52: elseif self.fully_frozen then bsw/jbe@52: return "voting" bsw/jbe@52: elseif self.half_frozen then bsw/jbe@52: return "frozen" bsw/jbe@52: elseif self.accepted then bsw/jbe@52: return "accepted" bsw/jbe@0: else bsw/jbe@52: return "new" bsw/jbe@0: end bsw/jbe@52: bsw@2: end bsw@218: --]] bsw@2: bsw@215: function Issue.object_get:phase() bsw@215: local state = self.state bsw@215: if state == "finished" or state == "cancelled" then bsw@215: return "closed" bsw@215: else bsw@215: return state bsw@215: end bsw@215: end bsw@215: bsw@2: function Issue.object_get:state_name() bsw@2: return Issue:get_state_name_for_state(self.state) bsw@2: end bsw@2: bsw@2: function Issue.object_get:state_time_left() bsw@2: local state = self.state bsw@2: local last_event_time bsw@2: local duration bsw@218: if state == "admission" then bsw@2: last_event_time = self.created bsw@25: duration = self.admission_time bsw@2: elseif state == "accepted" then bsw@2: last_event_time = self.accepted bsw@25: duration = self.discussion_time bsw@2: elseif state == "frozen" then bsw@2: last_event_time = self.half_frozen bsw@25: duration = self.verification_time bsw@2: elseif state == "voting" then bsw@2: last_event_time = self.fully_frozen bsw@25: duration = self.voting_time bsw@2: end poelzi@125: return db:query{ "SELECT ?::timestamp + ?::interval - CURRENT_TIMESTAMP(0) as time_left", last_event_time, duration }[1].time_left bsw@2: end bsw@2: bsw@2: function Issue.object_get:next_states() bsw@2: local state = self.state bsw@2: local next_states bsw@2: if state == "new" then bsw@2: next_states = { "accepted", "cancelled" } bsw@2: elseif state == "accepted" then bsw@2: next_states = { "frozen" } bsw@2: elseif state == "frozen" then bsw@2: next_states = { "voting" } bsw@2: elseif state == "voting" then bsw@2: next_states = { "finished" } bsw@2: end bsw@2: return next_states bsw@2: end bsw@2: bsw@2: function Issue.object_get:next_states_names() bsw@2: local next_states = self.next_states bsw@2: if not next_states then bsw@2: return bsw@2: end bsw@2: local state_names = {} bsw@2: for i, state in ipairs(self.next_states) do bsw@2: state_names[#state_names+1] = Issue:get_state_name_for_state(state) bsw@2: end bsw@2: return table.concat(state_names, ", ") bsw/jbe@0: end