Initiative = mondelefant.new_class() Initiative.table = 'initiative' Initiative:add_reference{ mode = 'm1', to = "Issue", this_key = 'issue_id', that_key = 'id', ref = 'issue', } Initiative:add_reference{ mode = 'm1', to = "Member", this_key = 'revoked_by_member_id', that_key = 'id', ref = 'revoked_by_member', } Initiative:add_reference{ mode = '1m', to = "Draft", this_key = 'id', that_key = 'initiative_id', ref = 'drafts', back_ref = 'initiative', default_order = '"id" DESC' } Initiative:add_reference{ mode = '1m', to = "Suggestion", this_key = 'id', that_key = 'initiative_id', ref = 'suggestions', back_ref = 'initiative', default_order = '"proportional_order" NULLS LAST, id' } Initiative:add_reference{ mode = '1m', to = "Initiator", this_key = 'id', that_key = 'initiative_id', ref = 'initiators', back_ref = 'initiative' } Initiative:add_reference{ mode = '1m', to = "Supporter", this_key = 'id', that_key = 'initiative_id', ref = 'supporters', back_ref = 'initiative', default_order = '"id"' } Initiative:add_reference{ mode = '1m', to = "Opinion", this_key = 'id', that_key = 'initiative_id', ref = 'opinions', back_ref = 'initiative', default_order = '"id"' } Initiative:add_reference{ mode = '1m', to = "Vote", this_key = 'id', that_key = 'initiative_id', ref = 'votes', back_ref = 'initiative', default_order = '"member_id"' } Initiative:add_reference{ mode = 'm1', to = "Initiative", this_key = 'suggested_initiative_id', that_key = 'id', ref = 'suggested_initiative', } Initiative:add_reference{ mode = 'mm', to = "Member", this_key = 'id', that_key = 'id', connected_by_table = '"initiator"', connected_by_this_key = 'initiative_id', connected_by_that_key = 'member_id', ref = 'initiating_members' } Initiative:add_reference{ mode = 'mm', to = "Member", this_key = 'id', that_key = 'id', connected_by_table = '"supporter"', connected_by_this_key = 'initiative_id', connected_by_that_key = 'member_id', ref = 'supporting_members' } Initiative:add_reference{ mode = 'mm', to = "Member", this_key = 'id', that_key = 'id', connected_by_table = 'direct_supporter_snapshot', connected_by_this_key = 'initiative_id', connected_by_that_key = 'member_id', ref = 'supporting_members_snapshot' } Initiative:add_reference{ mode = "11", to = mondelefant.class_prototype, this_key = "id", that_key = "initiative_id", ref = "member_info", back_ref = "initiative", selector_generator = function(list, options) assert(options.member_id, "member_id mandatory for member_info") local ids = { sep = ", " } local issue_ids = { sep = ", " } for i, object in ipairs(list) do local id = object.id if id ~= nil then ids[#ids+1] = {"?", id} issue_ids[#issue_ids+1] = { "?", object.issue_id } end end local sub_selector = Issue:get_db_conn():new_selector() if #ids == 0 then return sub_selector:empty_list_mode() end sub_selector:from("issue") sub_selector:add_field("issue.id", "issue_id") sub_selector:add_field{ '(delegation_info(?, null, null, issue.id, ?)).*', options.member_id, options.trustee_id } sub_selector:add_where{ 'issue.id IN ($)', issue_ids } local selector = Initiative:get_db_conn():new_selector() selector:add_from("initiative") selector:add_field("initiative.id", "initiative_id") selector:join("issue", nil, "issue.id = initiative.issue_id") selector:join(sub_selector, "delegation_info", "delegation_info.issue_id = issue.id") selector:add_field("delegation_info.*") selector:left_join("supporter", nil, "supporter.initiative_id = initiative.id AND supporter.member_id = delegation_info.participating_member_id") selector:left_join("delegating_interest_snapshot", "delegating_interest_s", { "delegating_interest_s.snapshot_id = issue.latest_snapshot_id AND delegating_interest_s.issue_id = issue.id AND delegating_interest_s.member_id = ?", options.member_id }) selector:left_join("direct_supporter_snapshot", "supporter_s", { "supporter_s.snapshot_id = issue.latest_snapshot_id AND supporter_s.initiative_id = initiative.id AND (supporter_s.member_id = ? OR supporter_s.member_id = delegating_interest_s.delegate_member_ids[array_upper(delegating_interest_s.delegate_member_ids, 1)])", options.member_id }) selector:add_field("CASE WHEN issue.fully_frozen ISNULL AND issue.closed ISNULL THEN supporter.member_id NOTNULL ELSE supporter_s.member_id NOTNULL END", "supported") selector:add_field({ "CASE WHEN issue.fully_frozen ISNULL AND issue.closed ISNULL THEN delegation_info.own_participation AND supporter.member_id NOTNULL ELSE supporter_s.member_id = ? END", options.member_id }, "directly_supported") selector:add_field("CASE WHEN issue.fully_frozen ISNULL AND issue.closed ISNULL THEN supporter.member_id NOTNULL AND NOT EXISTS(SELECT 1 FROM critical_opinion WHERE critical_opinion.initiative_id = initiative.id AND critical_opinion.member_id = delegation_info.participating_member_id) ELSE supporter_s.satisfied NOTNULL END", "satisfied") --selector:add_field("", "informed") selector:left_join("initiator", nil, { "initiator.initiative_id = initiative.id AND initiator.member_id = ? AND initiator.accepted", options.member_id }) selector:add_field("initiator.member_id NOTNULL", "initiated") return selector end } function Initiative.list:load_everything_for_member_id(member_id) if member_id then self:load("member_info", { member_id = member_id }) end end function Initiative.object:load_everything_for_member_id(member_id) if member_id then self:load("member_info", { member_id = member_id }) end end function Initiative:selector_for_updated_drafts(member_id) return Initiative:new_selector() :join("issue", "_issue_state", "_issue_state.id = initiative.issue_id AND _issue_state.closed ISNULL AND _issue_state.fully_frozen ISNULL") :join("current_draft", "_current_draft", "_current_draft.initiative_id = initiative.id") :join("supporter", "supporter", { "supporter.member_id = ? AND supporter.initiative_id = initiative.id AND supporter.draft_id < _current_draft.id", member_id }) :add_where("initiative.revoked ISNULL") end function Initiative:getSpecialSelector( args ) local selector = Initiative:new_selector() selector:join( "issue", nil, "issue.id = initiative.issue_id" ) selector:join( "area", nil, "area.id = issue.area_id" ) if args.area_id then selector:add_where{ "area.id = ?", args.area_id } elseif args.unit_id then selector:add_where{ "area.unit_id = ?", args.unit_id } end selector:limit( 1 ) selector:optional_object_mode() return selector end function Initiative:getLastWinner( args ) local selector = Initiative:getSpecialSelector( args ) selector:add_where( "issue.state = 'finished_with_winner'" ) selector:add_order_by( "issue.closed DESC, id DESC" ) return selector:exec() end function Initiative:getLastLoser( args ) local selector = Initiative:getSpecialSelector( args ) selector:add_where( "issue.state = 'finished_without_winner'" ) selector:add_order_by( "issue.closed DESC, id DESC" ) return selector:exec() end function Initiative:getNextEndingVoting( args ) local selector = Initiative:getSpecialSelector( args ) selector:add_where( "issue.state = 'voting'" ) selector:add_order_by( "issue.fully_frozen + issue.verification_time DESC, id DESC" ) return selector:exec() end function Initiative:getNextEndingVerification( args ) local selector = Initiative:getSpecialSelector( args ) selector:add_where( "issue.state = 'verification'" ) selector:add_order_by( "issue.half_frozen + issue.verification_time DESC, id DESC" ) return selector:exec() end function Initiative:getNextEndingDiscussion( args ) local selector = Initiative:getSpecialSelector( args ) selector:add_where( "issue.state = 'discussion'" ) selector:add_order_by( "issue.accepted + issue.discussion_time DESC, id DESC" ) return selector:exec() end function Initiative:getBestInAdmission( args ) local selector = Initiative:getSpecialSelector( args ) selector:add_where( "issue.state = 'admission'" ) selector:add_order_by( "issue.created + issue.max_admission_time DESC, id DESC" ) return selector:exec() end function Initiative.object_get:current_draft() return Draft:new_selector() :add_where{ '"initiative_id" = ?', self.id } :add_order_by('"id" DESC') :single_object_mode() :exec() end function Initiative.object_get:shortened_name() local name = self.name if #name > 100 then name = name:sub(1,100) .. "..." end return name end function Initiative.object_get:display_name() return "i" .. self.id .. ": " .. self.name end function Initiative.object_get:initiator_names() local members = Member:new_selector() :join("initiator", nil, "initiator.member_id = member.id") :add_where{ "initiator.initiative_id = ?", self.id } :add_where{ "initiator.accepted" } :exec() local member_names = {} for i, member in ipairs(members) do member_names[#member_names+1] = member.name end return member_names end function Initiative.object_get:potential_supporter_count() if self.supporter_count and self.satisfied_supporter_count then return self.supporter_count - self.satisfied_supporter_count end end