| rev | line source | 
| bsw/jbe@0 | 1 Issue = mondelefant.new_class() | 
| bsw/jbe@0 | 2 Issue.table = 'issue' | 
| bsw/jbe@0 | 3 | 
| bsw@549 | 4 local new_selector = Issue.new_selector | 
| bsw@549 | 5 | 
| bsw@549 | 6 function Issue:new_selector() | 
| bsw@549 | 7   local selector = new_selector(self) | 
| bsw@549 | 8   selector:add_field("coalesce(issue.fully_frozen + issue.voting_time, issue.half_frozen + issue.verification_time, issue.accepted + issue.discussion_time, issue.created + issue.admission_time) - now()", "state_time_left") | 
| bsw@861 | 9   selector:add_field("now() - issue.closed", "closed_ago") | 
| bsw@549 | 10   return selector | 
| bsw@549 | 11 end | 
| bsw@549 | 12 | 
| bsw/jbe@0 | 13 Issue:add_reference{ | 
| bsw/jbe@0 | 14   mode          = 'm1', | 
| bsw/jbe@0 | 15   to            = "Area", | 
| bsw/jbe@0 | 16   this_key      = 'area_id', | 
| bsw/jbe@0 | 17   that_key      = 'id', | 
| bsw/jbe@0 | 18   ref           = 'area', | 
| bsw/jbe@0 | 19 } | 
| bsw/jbe@0 | 20 | 
| bsw/jbe@0 | 21 Issue:add_reference{ | 
| bsw/jbe@0 | 22   mode          = 'm1', | 
| bsw/jbe@0 | 23   to            = "Policy", | 
| bsw/jbe@0 | 24   this_key      = 'policy_id', | 
| bsw/jbe@0 | 25   that_key      = 'id', | 
| bsw/jbe@0 | 26   ref           = 'policy', | 
| bsw/jbe@0 | 27 } | 
| bsw/jbe@0 | 28 | 
| bsw/jbe@0 | 29 Issue:add_reference{ | 
| bsw/jbe@0 | 30   mode          = '1m', | 
| bsw/jbe@0 | 31   to            = "Initiative", | 
| bsw/jbe@0 | 32   this_key      = 'id', | 
| bsw/jbe@0 | 33   that_key      = 'issue_id', | 
| bsw/jbe@0 | 34   ref           = 'initiatives', | 
| bsw@551 | 35   back_ref      = 'issue', | 
| bsw@551 | 36   default_order = 'initiative.rank, initiative.supporter_count DESC, id' | 
| bsw/jbe@0 | 37 } | 
| bsw/jbe@0 | 38 | 
| bsw/jbe@0 | 39 Issue:add_reference{ | 
| bsw/jbe@0 | 40   mode          = '1m', | 
| bsw/jbe@0 | 41   to            = "Interest", | 
| bsw/jbe@0 | 42   this_key      = 'id', | 
| bsw/jbe@0 | 43   that_key      = 'issue_id', | 
| bsw/jbe@0 | 44   ref           = 'interests', | 
| bsw/jbe@0 | 45   back_ref      = 'issue', | 
| bsw/jbe@0 | 46   default_order = '"id"' | 
| bsw/jbe@0 | 47 } | 
| bsw/jbe@0 | 48 | 
| bsw/jbe@0 | 49 Issue:add_reference{ | 
| bsw/jbe@0 | 50   mode          = '1m', | 
| bsw/jbe@0 | 51   to            = "Supporter", | 
| bsw/jbe@0 | 52   this_key      = 'id', | 
| bsw/jbe@0 | 53   that_key      = 'issue_id', | 
| bsw/jbe@0 | 54   ref           = 'supporters', | 
| bsw/jbe@0 | 55   back_ref      = 'issue', | 
| bsw/jbe@0 | 56   default_order = '"id"' | 
| bsw/jbe@0 | 57 } | 
| bsw/jbe@0 | 58 | 
| bsw/jbe@0 | 59 Issue:add_reference{ | 
| bsw/jbe@0 | 60   mode          = '1m', | 
| bsw/jbe@0 | 61   to            = "DirectVoter", | 
| bsw/jbe@0 | 62   this_key      = 'id', | 
| bsw/jbe@0 | 63   that_key      = 'issue_id', | 
| bsw/jbe@0 | 64   ref           = 'direct_voters', | 
| bsw/jbe@0 | 65   back_ref      = 'issue', | 
| bsw/jbe@0 | 66   default_order = '"member_id"' | 
| bsw/jbe@0 | 67 } | 
| bsw/jbe@0 | 68 | 
| bsw/jbe@0 | 69 Issue:add_reference{ | 
| bsw/jbe@0 | 70   mode          = '1m', | 
| bsw/jbe@0 | 71   to            = "Vote", | 
| bsw/jbe@0 | 72   this_key      = 'id', | 
| bsw/jbe@0 | 73   that_key      = 'issue_id', | 
| bsw/jbe@0 | 74   ref           = 'votes', | 
| bsw/jbe@0 | 75   back_ref      = 'issue', | 
| bsw/jbe@0 | 76   default_order = '"member_id", "initiative_id"' | 
| bsw/jbe@0 | 77 } | 
| bsw/jbe@0 | 78 | 
| bsw/jbe@0 | 79 Issue:add_reference{ | 
| bsw@2 | 80   mode          = '1m', | 
| bsw@2 | 81   to            = "Delegation", | 
| bsw@2 | 82   this_key      = 'id', | 
| bsw@2 | 83   that_key      = 'issue_id', | 
| bsw@2 | 84   ref           = 'delegations', | 
| bsw@2 | 85   back_ref      = 'issue' | 
| bsw@2 | 86 } | 
| bsw@2 | 87 | 
| bsw@2 | 88 Issue:add_reference{ | 
| bsw/jbe@0 | 89   mode                  = 'mm', | 
| bsw/jbe@0 | 90   to                    = "Member", | 
| bsw/jbe@0 | 91   this_key              = 'id', | 
| bsw/jbe@0 | 92   that_key              = 'id', | 
| bsw/jbe@0 | 93   connected_by_table    = 'interest', | 
| bsw/jbe@0 | 94   connected_by_this_key = 'issue_id', | 
| bsw/jbe@0 | 95   connected_by_that_key = 'member_id', | 
| bsw/jbe@0 | 96   ref                   = 'members' | 
| bsw/jbe@0 | 97 } | 
| bsw/jbe@0 | 98 | 
| bsw@3 | 99 Issue:add_reference{ | 
| bsw@3 | 100   mode                  = 'mm', | 
| bsw@3 | 101   to                    = "Member", | 
| bsw@3 | 102   this_key              = 'id', | 
| bsw@3 | 103   that_key              = 'id', | 
| bsw@3 | 104   connected_by_table    = 'direct_interest_snapshot', | 
| bsw@3 | 105   connected_by_this_key = 'issue_id', | 
| bsw@3 | 106   connected_by_that_key = 'member_id', | 
| bsw@3 | 107   ref                   = 'interested_members_snapshot' | 
| bsw@3 | 108 } | 
| bsw@3 | 109 | 
| bsw/jbe@6 | 110 Issue:add_reference{ | 
| bsw/jbe@6 | 111   mode                  = 'mm', | 
| bsw/jbe@6 | 112   to                    = "Member", | 
| bsw/jbe@6 | 113   this_key              = 'id', | 
| bsw/jbe@6 | 114   that_key              = 'id', | 
| bsw/jbe@6 | 115   connected_by_table    = 'direct_voter', | 
| bsw/jbe@6 | 116   connected_by_this_key = 'issue_id', | 
| bsw/jbe@6 | 117   connected_by_that_key = 'member_id', | 
| bsw/jbe@6 | 118   ref                   = 'direct_voters' | 
| bsw/jbe@6 | 119 } | 
| bsw/jbe@6 | 120 | 
| bsw@525 | 121 Issue:add_reference{ | 
| bsw@525 | 122   mode               = "11", | 
| bsw@525 | 123   to                 = mondelefant.class_prototype, | 
| bsw@525 | 124   this_key           = "id", | 
| bsw@525 | 125   that_key           = "issue_id", | 
| bsw@547 | 126   ref                = "member_info", | 
| bsw@525 | 127   back_ref           = "issue", | 
| bsw@525 | 128   selector_generator = function(list, options) | 
| bsw@547 | 129     assert(options.member_id, "member_id mandatory for member_info") | 
| bsw@525 | 130     local ids = { sep = ", " } | 
| bsw@525 | 131     for i, object in ipairs(list) do | 
| bsw@525 | 132       local id = object.id | 
| bsw@525 | 133       if id ~= nil then | 
| bsw@525 | 134         ids[#ids+1] = {"?", id} | 
| bsw@525 | 135       end | 
| bsw@525 | 136     end | 
| bsw@525 | 137     local sub_selector = Issue:get_db_conn():new_selector() | 
| bsw@525 | 138     if #ids == 0 then | 
| bsw@525 | 139       return sub_selector:empty_list_mode() | 
| bsw@525 | 140     end | 
| bsw@525 | 141     sub_selector:from("issue") | 
| bsw@525 | 142     sub_selector:add_field("issue.id", "issue_id") | 
| bsw@529 | 143     sub_selector:add_field{ '(delegation_info(?, null, null, issue.id, ?)).*', options.member_id, options.trustee_id } | 
| bsw@525 | 144     sub_selector:add_where{ 'issue.id IN ($)', ids } | 
| bsw@525 | 145 | 
| bsw@525 | 146     local selector = Issue:get_db_conn():new_selector() | 
| bsw@547 | 147     selector:add_from("issue") | 
| bsw@547 | 148     selector:join(sub_selector, "delegation_info", "delegation_info.issue_id = issue.id") | 
| bsw@525 | 149     selector:left_join("member", "first_trustee", "first_trustee.id = delegation_info.first_trustee_id") | 
| bsw@525 | 150     selector:left_join("member", "other_trustee", "other_trustee.id = delegation_info.other_trustee_id") | 
| bsw@525 | 151     selector:add_field("delegation_info.*") | 
| bsw@525 | 152     selector:add_field("first_trustee.name", "first_trustee_name") | 
| bsw@525 | 153     selector:add_field("other_trustee.name", "other_trustee_name") | 
| bsw@547 | 154     selector:left_join("direct_voter", nil, { "direct_voter.issue_id = issue.id AND direct_voter.member_id = ?", options.member_id }) | 
| bsw@547 | 155     selector:add_field("direct_voter.member_id NOTNULL", "direct_voted") | 
| bsw@525 | 156     return selector | 
| bsw@525 | 157   end | 
| bsw@525 | 158 } | 
| bsw@525 | 159 | 
| bsw@547 | 160 function Issue.list:load_everything_for_member_id(member_id) | 
| bsw@547 | 161   local areas = self:load("area") | 
| bsw@547 | 162   areas:load("unit") | 
| bsw@547 | 163   self:load("policy") | 
| bsw@551 | 164   if member_id then | 
| bsw@551 | 165     self:load("member_info", { member_id = member_id }) | 
| bsw@551 | 166   end | 
| bsw@551 | 167   local initiatives = self:load("initiatives") | 
| bsw@551 | 168   initiatives:load_everything_for_member_id(member_id) | 
| bsw@525 | 169 end | 
| bsw@525 | 170 | 
| bsw@548 | 171 function Issue.object:load_everything_for_member_id(member_id) | 
| bsw@548 | 172   local areas = self:load("area") | 
| bsw@548 | 173   areas:load("unit") | 
| bsw@548 | 174   self:load("policy") | 
| bsw@551 | 175   if member_id then | 
| bsw@551 | 176     self:load("member_info", { member_id = member_id }) | 
| bsw@551 | 177   end | 
| bsw@551 | 178   local initiatives = self:load("initiatives") | 
| bsw@551 | 179   initiatives:load_everything_for_member_id(member_id) | 
| bsw@548 | 180 end | 
| bsw@548 | 181 | 
| bsw/jbe@0 | 182 function Issue:get_state_name_for_state(value) | 
| bsw@2 | 183   local state_name_table = { | 
| bsw@2 | 184     new          = _"New", | 
| bsw@3 | 185     accepted     = _"Discussion", | 
| bsw@2 | 186     frozen       = _"Frozen", | 
| bsw@2 | 187     voting       = _"Voting", | 
| bsw@2 | 188     finished     = _"Finished", | 
| bsw@2 | 189     cancelled    = _"Cancelled" | 
| bsw@2 | 190   } | 
| bsw@10 | 191   return state_name_table[value] or value or '' | 
| bsw/jbe@0 | 192 end | 
| bsw/jbe@0 | 193 | 
| bsw@2 | 194 function Issue:get_search_selector(search_string) | 
| bsw/jbe@0 | 195   return self:new_selector() | 
| bsw/jbe@0 | 196     :join('"initiative"', nil, '"initiative"."issue_id" = "issue"."id"') | 
| bsw/jbe@6 | 197     :join('"draft"', nil, '"draft"."initiative_id" = "initiative"."id"') | 
| bsw/jbe@6 | 198     :add_where{ '"initiative"."text_search_data" @@ "text_search_query"(?) OR "draft"."text_search_data" @@ "text_search_query"(?)', search_string, search_string } | 
| bsw/jbe@6 | 199     :add_group_by('"issue"."id"') | 
| bsw@481 | 200     :add_group_by('"issue"."state"') | 
| bsw/jbe@6 | 201     :add_group_by('"issue"."area_id"') | 
| bsw/jbe@6 | 202     :add_group_by('"issue"."policy_id"') | 
| bsw/jbe@6 | 203     :add_group_by('"issue"."created"') | 
| bsw/jbe@6 | 204     :add_group_by('"issue"."accepted"') | 
| bsw/jbe@6 | 205     :add_group_by('"issue"."half_frozen"') | 
| bsw/jbe@6 | 206     :add_group_by('"issue"."fully_frozen"') | 
| bsw/jbe@6 | 207     :add_group_by('"issue"."closed"') | 
| bsw/jbe@6 | 208     :add_group_by('"issue"."ranks_available"') | 
| bsw@483 | 209     :add_group_by('"issue"."status_quo_schulze_rank"') | 
| poelzi@140 | 210     :add_group_by('"issue"."cleaned"') | 
| bsw/jbe@6 | 211     :add_group_by('"issue"."snapshot"') | 
| bsw/jbe@6 | 212     :add_group_by('"issue"."latest_snapshot_event"') | 
| bsw/jbe@6 | 213     :add_group_by('"issue"."population"') | 
| bsw/jbe@6 | 214     :add_group_by('"issue"."voter_count"') | 
| bsw@75 | 215     :add_group_by('"issue"."admission_time"') | 
| bsw@75 | 216     :add_group_by('"issue"."discussion_time"') | 
| bsw@75 | 217     :add_group_by('"issue"."verification_time"') | 
| bsw@75 | 218     :add_group_by('"issue"."voting_time"') | 
| bsw/jbe@6 | 219     --:set_distinct() | 
| bsw/jbe@0 | 220 end | 
| bsw/jbe@0 | 221 | 
| bsw@75 | 222 function Issue:modify_selector_for_state(initiatives_selector, state) | 
| bsw@51 | 223   if state == "new" then | 
| bsw@75 | 224     initiatives_selector:add_where("issue.accepted ISNULL AND issue.closed ISNULL") | 
| bsw@51 | 225   elseif state == "accepted" then | 
| bsw@75 | 226     initiatives_selector:add_where("issue.accepted NOTNULL AND issue.half_frozen ISNULL AND issue.closed ISNULL") | 
| bsw@51 | 227   elseif state == "frozen" then | 
| bsw@75 | 228     initiatives_selector:add_where("issue.half_frozen NOTNULL AND issue.fully_frozen ISNULL AND issue.closed ISNULL") | 
| bsw@51 | 229   elseif state == "voting" then | 
| bsw@75 | 230     initiatives_selector:add_where("issue.fully_frozen NOTNULL AND issue.closed ISNULL") | 
| bsw@51 | 231   elseif state == "finished" then | 
| bsw@75 | 232     initiatives_selector:add_where("issue.fully_frozen NOTNULL AND issue.closed NOTNULL") | 
| bsw@51 | 233   elseif state == "cancelled" then | 
| bsw@75 | 234     initiatives_selector:add_where("issue.fully_frozen ISNULL AND issue.closed NOTNULL") | 
| bsw@75 | 235   else | 
| bsw@75 | 236     error("Invalid state") | 
| bsw@51 | 237   end | 
| bsw@51 | 238 end | 
| bsw@51 | 239 | 
| bsw/jbe@0 | 240 function Issue.object_get:state() | 
| bsw/jbe@52 | 241   if self.closed then | 
| bsw/jbe@52 | 242     if self.fully_frozen then | 
| bsw/jbe@5 | 243       return "finished" | 
| bsw/jbe@0 | 244     else | 
| bsw/jbe@52 | 245       return "cancelled" | 
| bsw/jbe@0 | 246     end | 
| bsw/jbe@52 | 247   elseif self.fully_frozen then | 
| bsw/jbe@52 | 248     return "voting" | 
| bsw/jbe@52 | 249   elseif self.half_frozen then | 
| bsw/jbe@52 | 250     return "frozen" | 
| bsw/jbe@52 | 251   elseif self.accepted then | 
| bsw/jbe@52 | 252     return "accepted" | 
| bsw/jbe@0 | 253   else | 
| bsw/jbe@52 | 254     return "new" | 
| bsw/jbe@0 | 255   end | 
| bsw/jbe@52 | 256 | 
| bsw@2 | 257 end | 
| bsw@2 | 258 | 
| bsw@2 | 259 function Issue.object_get:state_name() | 
| bsw@2 | 260   return Issue:get_state_name_for_state(self.state) | 
| bsw@2 | 261 end | 
| bsw@2 | 262 | 
| bsw@2 | 263 function Issue.object_get:next_states() | 
| bsw@2 | 264   local state = self.state | 
| bsw@2 | 265   local next_states | 
| bsw@2 | 266   if state == "new" then | 
| bsw@2 | 267     next_states = { "accepted", "cancelled" } | 
| bsw@2 | 268   elseif state == "accepted" then | 
| bsw@2 | 269     next_states = { "frozen" } | 
| bsw@2 | 270   elseif state == "frozen" then | 
| bsw@2 | 271     next_states = { "voting" } | 
| bsw@2 | 272   elseif state == "voting" then | 
| bsw@2 | 273     next_states = { "finished" } | 
| bsw@2 | 274   end | 
| bsw@2 | 275   return next_states | 
| bsw@2 | 276 end | 
| bsw@2 | 277 | 
| bsw@2 | 278 function Issue.object_get:next_states_names() | 
| bsw@2 | 279   local next_states = self.next_states | 
| bsw@2 | 280   if not next_states then | 
| bsw@2 | 281     return | 
| bsw@2 | 282   end | 
| bsw@2 | 283   local state_names = {} | 
| bsw@2 | 284   for i, state in ipairs(self.next_states) do | 
| bsw@2 | 285     state_names[#state_names+1] = Issue:get_state_name_for_state(state) | 
| bsw@2 | 286   end | 
| bsw@2 | 287   return table.concat(state_names, ", ") | 
| bsw@525 | 288 end | 
| bsw@525 | 289 | 
| bsw@525 | 290 function Issue.object_get:etherpad_url() | 
| bsw@525 | 291   return config.etherpad.base_url .. "p/" .. config.etherpad.group_id .. "$Issue" .. self.id | 
| bsw@551 | 292 end |