| rev | line source | 
| bsw@1496 | 1 local initiative | 
| bsw@1496 | 2 local new_initiative | 
| bsw@1496 | 3 local draft_id | 
| bsw@1496 | 4 local status | 
| bsw@1496 | 5 | 
| bsw@1496 | 6 if param.get("initiative_id", atom.integer) then | 
| bsw@1496 | 7 | 
| bsw@1496 | 8   local function donew() | 
| bsw@1496 | 9     local draft_text = param.get("content") | 
| bsw@1496 | 10 | 
| bsw@1496 | 11     if not draft_text then | 
| bsw@1496 | 12       return false | 
| bsw@1496 | 13     end | 
| bsw@1496 | 14 | 
| bsw@1496 | 15     local draft_text = util.wysihtml_preproc(draft_text) | 
| bsw@1496 | 16 | 
| bsw@1496 | 17     local valid_html, error_message = util.html_is_safe(draft_text) | 
| bsw@1496 | 18     if not valid_html then | 
| bsw@1496 | 19       slot.put_into("error", _("Draft contains invalid formatting or character sequence: #{error_message}", { error_message = error_message }) ) | 
| bsw@1496 | 20       return false | 
| bsw@1496 | 21     end | 
| bsw@1496 | 22 | 
| bsw@1496 | 23     if config.initiative_abstract then | 
| bsw@1496 | 24       local abstract = param.get("abstract") | 
| bsw@1496 | 25       if not abstract then | 
| bsw@1496 | 26         return false | 
| bsw@1496 | 27       end | 
| bsw@1496 | 28       abstract = encode.html(abstract) | 
| bsw@1496 | 29       draft_text = abstract .. "<!--END_OF_ABSTRACT-->" .. draft_text | 
| bsw@1496 | 30     end | 
| bsw@1496 | 31 | 
| bsw@1496 | 32     draft_id = Draft:update_content( | 
| bsw@1496 | 33       app.session.member.id, | 
| bsw@1496 | 34       param.get("initiative_id", atom.integer), | 
| bsw@1496 | 35       param.get("formatting_engine"), | 
| bsw@1496 | 36       draft_text, | 
| bsw@1496 | 37       nil, | 
| bsw@1496 | 38       param.get("preview") or param.get("edit") | 
| bsw@1496 | 39     ) | 
| bsw@1496 | 40     return draft_id and true or false | 
| bsw@1496 | 41   end | 
| bsw@1496 | 42 | 
| bsw@1496 | 43   status = donew() | 
| bsw@1496 | 44 | 
| bsw@1496 | 45 else | 
| bsw@1496 | 46 | 
| bsw@1496 | 47   local function donew() | 
| bsw@1496 | 48     local issue | 
| bsw@1496 | 49     local area | 
| bsw/jbe@1309 | 50 | 
| bsw@1496 | 51     local issue_id = param.get("issue_id", atom.integer) | 
| bsw@1496 | 52     if issue_id then | 
| bsw@1496 | 53       issue = Issue:new_selector():add_where{"id=?",issue_id}:for_share():single_object_mode():exec() | 
| bsw@1496 | 54       if issue.closed then | 
| bsw@1496 | 55         slot.put_into("error", _"This issue is already closed.") | 
| bsw@1496 | 56         return false | 
| bsw@1496 | 57       elseif issue.fully_frozen then | 
| bsw@1496 | 58         slot.put_into("error", _"Voting for this issue has already begun.") | 
| bsw@1496 | 59         return false | 
| bsw@1496 | 60       elseif issue.phase_finished then | 
| bsw@1496 | 61         slot.put_into("error", _"Current phase is already closed.") | 
| bsw@1496 | 62         return false | 
| bsw@1496 | 63       end | 
| bsw@1496 | 64       area = issue.area | 
| bsw@1496 | 65     else | 
| bsw@1496 | 66       local area_id = param.get("area_id", atom.integer) | 
| bsw@1496 | 67       area = Area:new_selector():add_where{"id=?",area_id}:single_object_mode():exec() | 
| bsw@1496 | 68       if not area.active then | 
| bsw@1496 | 69         slot.put_into("error", "Invalid area.") | 
| bsw@1496 | 70         return false | 
| bsw@1496 | 71       end | 
| bsw@1496 | 72     end | 
| bsw@1496 | 73 | 
| bsw@1496 | 74     if not app.session.member:has_voting_right_for_unit_id(area.unit_id) then | 
| bsw@1496 | 75       return execute.view { module = "index", view = "403" } | 
| bsw@1496 | 76     end | 
| bsw@1496 | 77 | 
| bsw@1496 | 78     local policy_id = param.get("policy_id", atom.integer) | 
| bsw@1496 | 79     local policy | 
| bsw@1496 | 80     if policy_id then | 
| bsw@1496 | 81       policy = Policy:by_id(policy_id) | 
| bsw@1496 | 82     end | 
| bsw/jbe@1309 | 83 | 
| bsw@1496 | 84     if not issue then | 
| bsw@1496 | 85       if policy_id == -1 then | 
| bsw@1496 | 86         slot.put_into("error", _"Please choose a policy") | 
| bsw@1496 | 87         return false | 
| bsw@1496 | 88       end | 
| bsw@1496 | 89       if not policy.active then | 
| bsw@1496 | 90         slot.put_into("error", "Invalid policy.") | 
| bsw@1496 | 91         return false | 
| bsw@1496 | 92       end | 
| bsw@1496 | 93       if policy.polling and not app.session.member:has_polling_right_for_unit_id(area.unit_id) then | 
| bsw@1496 | 94         return execute.view { module = "index", view = "403" } | 
| bsw@1496 | 95       end | 
| bsw@1496 | 96       if not area:get_reference_selector("allowed_policies") | 
| bsw@1496 | 97         :add_where{ "policy.id = ?", policy_id } | 
| bsw@1496 | 98         :optional_object_mode() | 
| bsw@1496 | 99         :exec() | 
| bsw@1496 | 100       then | 
| bsw@1496 | 101         slot.put_into("error", "policy not allowed") | 
| bsw@1496 | 102         return false | 
| bsw@1496 | 103       end | 
| bsw@1496 | 104     end | 
| bsw@1496 | 105 | 
| bsw@1496 | 106     local is_polling = (issue and param.get("polling", atom.boolean)) or (policy and policy.polling) or false | 
| bsw@1496 | 107 | 
| bsw@1496 | 108     local tmp = db:query({ "SELECT text_entries_left, initiatives_left FROM member_contingent_left WHERE member_id = ? AND polling = ?", app.session.member.id, is_polling }, "opt_object") | 
| bsw@1496 | 109     if not tmp or tmp.initiatives_left < 1 then | 
| bsw@1496 | 110       slot.put_into("error", _"Sorry, your contingent for creating initiatives has been used up. Please try again later.") | 
| bsw@1496 | 111       return false | 
| bsw@1496 | 112     end | 
| bsw@1496 | 113     if tmp and tmp.text_entries_left < 1 then | 
| bsw@1496 | 114       slot.put_into("error", _"Sorry, you have reached your personal flood limit. Please be slower...") | 
| bsw@1496 | 115       return false | 
| bsw@1496 | 116     end | 
| bsw@1496 | 117 | 
| bsw@1496 | 118     local name = param.get("name") | 
| bsw@1496 | 119 | 
| bsw@1496 | 120     local name = util.trim(name) | 
| bsw@1496 | 121 | 
| bsw@1496 | 122     if #name < 3 then | 
| bsw@1496 | 123       slot.put_into("error", _"Please enter a meaningful title for your initiative!") | 
| bsw@1496 | 124       return false | 
| bsw@1496 | 125     end | 
| bsw@1496 | 126 | 
| bsw@1496 | 127     if #name > 140 then | 
| bsw@1496 | 128       slot.put_into("error", _"This title is too long!") | 
| bsw@1496 | 129       return false | 
| bsw@1496 | 130     end | 
| bsw/jbe@1309 | 131 | 
| bsw@1496 | 132     local timing | 
| bsw@1496 | 133     if not issue and policy.free_timeable then | 
| bsw@1496 | 134       local free_timing_string = util.trim(param.get("free_timing")) | 
| bsw@1496 | 135       if not free_timing_string or #free_timing_string < 1 then | 
| bsw@1496 | 136         slot.put_into("error", _"Choose timing") | 
| bsw@1496 | 137         return false | 
| bsw@1496 | 138       end | 
| bsw@1496 | 139       local available_timings | 
| bsw@1496 | 140       if config.free_timing and config.free_timing.available_func then | 
| bsw@1496 | 141         available_timings = config.free_timing.available_func(policy) | 
| bsw@1496 | 142         if available_timings == false then | 
| bsw@1496 | 143           slot.put_into("error", "error in free timing config") | 
| bsw@1496 | 144           return false | 
| bsw@1496 | 145         end | 
| bsw@1496 | 146       end | 
| bsw@1496 | 147       if available_timings then | 
| bsw@1496 | 148         local timing_available = false | 
| bsw@1496 | 149         for i, available_timing in ipairs(available_timings) do | 
| bsw@1496 | 150           if available_timing.id == free_timing_string then | 
| bsw@1496 | 151       	    timing_available = true | 
| bsw@1496 | 152           end | 
| bsw@1496 | 153         end | 
| bsw@1496 | 154         if not timing_available then | 
| bsw@1496 | 155           slot.put_into("error", _"Invalid timing") | 
| bsw@1496 | 156           return false | 
| bsw@1496 | 157         end | 
| bsw@1496 | 158       end | 
| bsw@1496 | 159       timing = config.free_timing.calculate_func(policy, free_timing_string) | 
| bsw@1496 | 160       if not timing then | 
| bsw@1496 | 161         slot.put_into("error", "error in free timing config") | 
| bsw@1496 | 162         return false | 
| bsw@1496 | 163       end | 
| bsw@1496 | 164     end | 
| bsw@1496 | 165 | 
| bsw@1496 | 166     local draft_text = param.get("content") | 
| bsw@1496 | 167 | 
| bsw@1496 | 168     if not draft_text then | 
| bsw@1496 | 169       slot.put_into("error", "no draft text") | 
| bsw@1496 | 170       return false | 
| bsw@1496 | 171     end | 
| bsw@1496 | 172 | 
| bsw@1496 | 173     local draft_text = util.wysihtml_preproc(draft_text) | 
| bsw@1496 | 174 | 
| bsw@1496 | 175     local valid_html, error_message = util.html_is_safe(draft_text) | 
| bsw@1496 | 176     if not valid_html then | 
| bsw@1496 | 177       slot.put_into("error", _("Draft contains invalid formatting or character sequence: #{error_message}", { error_message = error_message }) ) | 
| bsw@1496 | 178       return false | 
| bsw@1496 | 179     end | 
| bsw@1496 | 180 | 
| bsw@1496 | 181     if config.initiative_abstract then | 
| bsw@1496 | 182       local abstract = param.get("abstract") | 
| bsw@1496 | 183       if not abstract then | 
| bsw@1496 | 184         slot.put_into("error", "no abstract") | 
| bsw@1496 | 185         return false | 
| bsw@1496 | 186       end | 
| bsw@1496 | 187       abstract = encode.html(abstract) | 
| bsw@1496 | 188       draft_text = abstract .. "<!--END_OF_ABSTRACT-->" .. draft_text | 
| bsw@1496 | 189     end | 
| bsw@1496 | 190 | 
| bsw@1496 | 191     local location = param.get("location") | 
| bsw@1496 | 192     if location == "" then | 
| bsw@1496 | 193       location = nil | 
| bsw@1496 | 194     end | 
| bsw@1550 | 195 | 
| bsw@1550 | 196     local external_reference | 
| bsw@1550 | 197     if config.firstlife then | 
| bsw@1550 | 198       external_reference = param.get("external_reference") | 
| bsw@1550 | 199     end | 
| bsw@1496 | 200 | 
| bsw@1496 | 201     if param.get("preview") or param.get("edit") then | 
| bsw@1496 | 202       return false | 
| bsw@1496 | 203     end | 
| bsw/jbe@1309 | 204 | 
| bsw@1496 | 205     initiative = Initiative:new() | 
| bsw@1496 | 206 | 
| bsw@1496 | 207     if not issue then | 
| bsw@1496 | 208       issue = Issue:new() | 
| bsw@1496 | 209       issue.area_id = area.id | 
| bsw@1496 | 210       issue.policy_id = policy_id | 
| bsw@1496 | 211 | 
| bsw@1496 | 212       if policy.polling then | 
| bsw@1496 | 213         issue.accepted = 'now' | 
| bsw@1496 | 214         issue.state = 'discussion' | 
| bsw@1496 | 215         initiative.polling = true | 
| bsw@1496 | 216 | 
| bsw@1496 | 217         if policy.free_timeable then | 
| bsw@1496 | 218           issue.discussion_time = timing.discussion | 
| bsw@1496 | 219           issue.verification_time = timing.verification | 
| bsw@1496 | 220           issue.voting_time = timing.voting | 
| bsw@1496 | 221         end | 
| bsw@1496 | 222 | 
| bsw@1496 | 223       end | 
| bsw@1496 | 224 | 
| bsw@1496 | 225       issue:save() | 
| bsw@1496 | 226 | 
| bsw@1496 | 227       if config.etherpad then | 
| bsw@1496 | 228         local result = net.curl( | 
| bsw@1496 | 229           config.etherpad.api_base | 
| bsw@1496 | 230           .. "api/1/createGroupPad?apikey=" .. config.etherpad.api_key | 
| bsw@1496 | 231           .. "&groupID=" .. config.etherpad.group_id | 
| bsw@1496 | 232           .. "&padName=Issue" .. tostring(issue.id) | 
| bsw@1496 | 233           .. "&text=" .. request.get_absolute_baseurl() .. "issue/show/" .. tostring(issue.id) .. ".html" | 
| bsw@1496 | 234         ) | 
| bsw@1496 | 235       end | 
| bsw@1496 | 236     end | 
| bsw@1496 | 237 | 
| bsw@1496 | 238     if param.get("polling", atom.boolean) and app.session.member:has_polling_right_for_unit_id(area.unit_id) then | 
| bsw@1496 | 239       initiative.polling = true | 
| bsw@1496 | 240     end | 
| bsw@1496 | 241     initiative.issue_id = issue.id | 
| bsw@1496 | 242     initiative.name = name | 
| bsw@1550 | 243     initiative.external_reference = external_reference | 
| bsw@1496 | 244     initiative:save() | 
| bsw@1496 | 245 | 
| bsw@1496 | 246     new_initiative = initiative | 
| bsw@1496 | 247 | 
| bsw@1496 | 248     local draft = Draft:new() | 
| bsw@1496 | 249     draft.initiative_id = initiative.id | 
| bsw@1496 | 250     draft.formatting_engine = formatting_engine | 
| bsw@1496 | 251     draft.content = draft_text | 
| bsw@1496 | 252     draft.location = location | 
| bsw@1496 | 253     draft.author_id = app.session.member.id | 
| bsw@1496 | 254     draft:save() | 
| bsw@1496 | 255 | 
| bsw@1496 | 256     draft_id = draft.id | 
| bsw@1496 | 257 | 
| bsw@1496 | 258     local initiator = Initiator:new() | 
| bsw@1496 | 259     initiator.initiative_id = initiative.id | 
| bsw@1496 | 260     initiator.member_id = app.session.member.id | 
| bsw@1496 | 261     initiator.accepted = true | 
| bsw@1496 | 262     initiator:save() | 
| bsw@1496 | 263 | 
| bsw@1496 | 264     if not is_polling then | 
| bsw@1496 | 265       local supporter = Supporter:new() | 
| bsw@1496 | 266       supporter.initiative_id = initiative.id | 
| bsw@1496 | 267       supporter.member_id = app.session.member.id | 
| bsw@1496 | 268       supporter.draft_id = draft.id | 
| bsw@1496 | 269       supporter:save() | 
| bsw@1496 | 270     end | 
| bsw@1496 | 271 | 
| bsw/jbe@1309 | 272   end | 
| bsw@1496 | 273   status = donew() | 
| bsw/jbe@1309 | 274 end | 
| bsw/jbe@1309 | 275 | 
| bsw@1495 | 276 if config.attachments then | 
| bsw@1495 | 277   local file_upload_session = param.get("file_upload_session") | 
| bsw@1495 | 278   file_upload_session = string.gsub(file_upload_session, "[^A-Za-z0-9]", "") | 
| bsw@1495 | 279   local file_uploads = json.array() | 
| bsw@1495 | 280   local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. ".json") | 
| bsw@1495 | 281   local fh = io.open(filename, "r") | 
| bsw@1495 | 282   if fh then | 
| bsw@1495 | 283     file_uploads = json.import(fh:read("*a")) | 
| bsw@1495 | 284   end | 
| bsw@1495 | 285   for i, file_upload in ipairs(file_uploads) do | 
| bsw@1495 | 286     if param.get("file_upload_delete_" .. file_upload.id, atom.boolean) then | 
| bsw@1495 | 287       for j = i, #file_uploads - 1 do | 
| bsw@1495 | 288         file_uploads[j] = file_uploads[j+1] | 
| bsw@1495 | 289       end | 
| bsw@1495 | 290       file_uploads[#file_uploads] = nil | 
| bsw@1495 | 291     end | 
| bsw@1495 | 292   end | 
| bsw@1495 | 293   local convert_func = config.attachments.convert_func | 
| bsw@1495 | 294   local last_id = param.get("file_upload_last_id", atom.number) | 
| bsw@1495 | 295   if last_id and last_id > 0 then | 
| bsw@1495 | 296     if last_id > 1024 then | 
| bsw@1495 | 297       last_id = 1024 | 
| bsw@1495 | 298     end | 
| bsw@1495 | 299     for i = 1, last_id do | 
| bsw@1495 | 300       local file = param.get("file_" .. i) | 
| bsw@1495 | 301       if file and #file > 0 then | 
| bsw@1495 | 302         local id = multirand.string( | 
| bsw@1495 | 303           32, | 
| bsw@1495 | 304           '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' | 
| bsw@1495 | 305         ) | 
| bsw@1495 | 306         local data, err, status = convert_func(file) | 
| bsw@1495 | 307         if status ~= 0 or data == nil then | 
| bsw@1495 | 308           slot.put_into("error", _"Error while converting image. Please note, that only JPG files are supported!") | 
| bsw@1495 | 309           return false | 
| bsw@1495 | 310         end | 
| bsw@1495 | 311         local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. "-" .. id .. ".jpg") | 
| bsw@1495 | 312         local fh = assert(io.open(filename, "w")) | 
| bsw@1495 | 313         fh:write(file) | 
| bsw@1495 | 314         fh:write("\n") | 
| bsw@1495 | 315         fh:close() | 
| bsw@1495 | 316         local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. "-" .. id .. ".preview.jpg") | 
| bsw@1495 | 317         local fh = assert(io.open(filename, "w")) | 
| bsw@1495 | 318         fh:write(data) | 
| bsw@1495 | 319         fh:write("\n") | 
| bsw@1495 | 320         fh:close() | 
| bsw@1495 | 321         table.insert(file_uploads, json.object{ | 
| bsw@1495 | 322           id = id, | 
| bsw@1495 | 323           filename = filename, | 
| bsw@1495 | 324           title = param.get("title_" .. i), | 
| bsw@1495 | 325           description = param.get("description_" .. i) | 
| bsw@1495 | 326         }) | 
| bsw@1495 | 327       end | 
| bsw@1495 | 328     end | 
| bsw@1495 | 329   end | 
| bsw@1495 | 330   local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. ".json") | 
| bsw@1495 | 331   local fh = assert(io.open(filename, "w")) | 
| bsw@1495 | 332   fh:write(json.export(file_uploads)) | 
| bsw@1495 | 333   fh:write("\n") | 
| bsw@1495 | 334   fh:close() | 
| bsw@1496 | 335 | 
| bsw@1496 | 336   if draft_id then | 
| bsw@1496 | 337     local file_upload_session = param.get("file_upload_session") | 
| bsw@1496 | 338     file_upload_session = string.gsub(file_upload_session, "[^A-Za-z0-9]", "") | 
| bsw@1495 | 339 | 
| bsw@1496 | 340     local draft_attachments = DraftAttachment:new_selector() | 
| bsw@1496 | 341       :add_where{ "draft_attachment.draft_id = ?", draft_id } | 
| bsw@1496 | 342       :exec() | 
| bsw@1496 | 343 | 
| bsw@1496 | 344     for i, draft_attachment in ipairs(draft_attachments) do | 
| bsw@1496 | 345       if param.get("file_delete_" .. draft_attachment.file_id, atom.boolean) then | 
| bsw@1496 | 346         draft_attachment:destroy() | 
| bsw@1496 | 347       end | 
| bsw@1496 | 348     end | 
| bsw@1495 | 349 | 
| bsw@1496 | 350     local file_uploads = json.array() | 
| bsw@1496 | 351     local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. ".json") | 
| bsw@1496 | 352     local fh = io.open(filename, "r") | 
| bsw@1496 | 353     if fh then | 
| bsw@1496 | 354       file_uploads = json.import(fh:read("*a")) | 
| bsw@1496 | 355     end | 
| bsw@1496 | 356     for i, file_upload in ipairs(file_uploads) do | 
| bsw@1496 | 357       local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. "-" .. file_upload.id .. ".jpg") | 
| bsw@1496 | 358       local data | 
| bsw@1496 | 359       local fh = io.open(filename, "r") | 
| bsw@1496 | 360       if fh then | 
| bsw@1496 | 361         data = fh:read("*a") | 
| bsw@1496 | 362       end | 
| bsw@1496 | 363       local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. "-" .. file_upload.id .. ".preview.jpg") | 
| bsw@1496 | 364       local data_preview | 
| bsw@1496 | 365       local fh = io.open(filename, "r") | 
| bsw@1496 | 366       if fh then | 
| bsw@1496 | 367         data_preview = fh:read("*a") | 
| bsw@1496 | 368       end | 
| bsw@1496 | 369 | 
| bsw@1496 | 370       local hash = moonhash.sha3_512(data) | 
| bsw@1495 | 371 | 
| bsw@1496 | 372       local file = File:new_selector() | 
| bsw@1496 | 373         :add_where{ "hash = ?", hash } | 
| bsw@1496 | 374         :add_where{ "content_type = ?", "image/jpeg" } | 
| bsw@1496 | 375         :optional_object_mode() | 
| bsw@1496 | 376         :exec() | 
| bsw@1495 | 377 | 
| bsw@1496 | 378       if not file then | 
| bsw@1496 | 379         file = File:new() | 
| bsw@1496 | 380         file.content_type = "image/jpeg" | 
| bsw@1496 | 381         file.hash = hash | 
| bsw@1496 | 382         file.data = data | 
| bsw@1496 | 383         file.preview_content_type = "image/jpeg" | 
| bsw@1496 | 384         file.preview_data = data_preview | 
| bsw@1496 | 385         file:save() | 
| bsw@1496 | 386       end | 
| bsw@1496 | 387 | 
| bsw@1496 | 388       local draft_attachment = DraftAttachment:new() | 
| bsw@1496 | 389       draft_attachment.draft_id = draft_id | 
| bsw@1496 | 390       draft_attachment.file_id = file.id | 
| bsw@1496 | 391       draft_attachment.title = file_upload.title | 
| bsw@1496 | 392       draft_attachment.description = file_upload.description | 
| bsw@1496 | 393       draft_attachment:save() | 
| bsw@1495 | 394     end | 
| bsw@1495 | 395   end | 
| bsw@1495 | 396 | 
| bsw@1495 | 397 end | 
| bsw@1495 | 398 | 
| bsw@1496 | 399 if new_initiative and status ~= false then | 
| bsw@1535 | 400   local callback = param.get("callback") | 
| bsw@1535 | 401   if config.allow_new_draft_callback and callback then | 
| bsw@1535 | 402     request.redirect{ external = callback } | 
| bsw@1535 | 403   else | 
| bsw@1535 | 404     request.redirect{ | 
| bsw@1535 | 405       module = "initiative", | 
| bsw@1535 | 406       view = "show", | 
| bsw@1535 | 407       id = new_initiative.id | 
| bsw@1535 | 408     } | 
| bsw@1535 | 409   end | 
| bsw@1496 | 410 end | 
| bsw@1496 | 411 | 
| bsw@1496 | 412 return status | 
| bsw@1496 | 413 |