<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>features/projects/settings_member.feature</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -35,6 +35,15 @@ module Settings
         render :new
       end
     end
+
+    def update_all(member_function={})
+      if Member.change_functions(member_function)
+        notice = &quot;All members was updated&quot;
+      else
+        notice = &quot;You can't have no admin in a project&quot;
+      end
+      redirect url(:project_settings_members, @project), :message =&gt; {:notice =&gt; notice}
+    end
   
     private
 </diff>
      <filename>app/controllers/settings/members.rb</filename>
    </modified>
    <modified>
      <diff>@@ -22,4 +22,27 @@ class Member
     user.login
   end
 
+  def self.change_functions(member_function)
+    return true if member_function.empty?
+    transaction do |txn|
+      project = nil
+      member_function.keys.each do |member_id|
+        member = Member.get!(member_id.to_i)
+        if project != member.project &amp;&amp; !project.nil?
+          txn.rollback
+          return false
+        end
+        project = member.project
+        member.function = Function.get!(member_function[member_id].to_i)
+        member.save
+      end
+      project_have_admin = project.have_one_admin
+      if project_have_admin.is_a?(Array) &amp;&amp; !project_have_admin.first
+        txn.rollback
+        return false
+      end
+    end
+    true
+  end
+
 end</diff>
      <filename>app/models/member.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,14 +4,21 @@
     = @project.name
 
   .inner
-    %table.table
-      %thead
-        %tr
-          %th.first User
-          %th.last Role
-      %tbody
-        - for member in @members
-          %tr{:class =&gt; cycle('odd', 'even')}
-            %td=link_to(member.user.login, url(:project_settings_member, @project, member))
-            %td=member.function.name
-    %p=link_to 'Add member', url(:new_project_settings_member, @project)
+
+    = form :action =&gt; resource(@project, :settings, :members, :update_all), :method =&gt; 'PUT', :class =&gt; 'form' do
+
+      %table.table
+        %thead
+          %tr
+            %th.first User
+            %th.last Role
+        %tbody
+          - for member in @members
+            %tr{:class =&gt; cycle('odd', 'even')}
+              %td=link_to(member.user.login, url(:project_settings_member, @project, member))
+              %td=select :name =&gt; &quot;member_function[#{member.id}]&quot;, :collection =&gt; Function.all, :text_method =&gt; 'name', :value_method =&gt; 'id', :selected =&gt; member.function_id.to_s
+      .actions-bar
+        .actions
+          =link_to 'Add member', url(:new_project_settings_member, @project)
+          =submit &quot;Update all&quot;, :class=&gt; 'button'
+        .clear</diff>
      <filename>app/views/settings/members/index.html.haml</filename>
    </modified>
    <modified>
      <diff>@@ -52,7 +52,9 @@ Merb::Router.prepare do
     end
     namespace(:settings) do
       match('/').to(:controller =&gt; 'members', :action =&gt; 'index')
-      resources :members
+      resources :members do
+        collection :update_all, :method =&gt; :put
+      end
     end
   end
   # RESTful routes</diff>
      <filename>config/router.rb</filename>
    </modified>
    <modified>
      <diff>@@ -22,6 +22,24 @@ projects and tickets but can't update them.
 
 # Project settings
 
+## Member of project
+
+In each project, you can choose all member.
+
+### Add member
+
+You can add several members to your project. A member add to this project, can 
+create and update all tickets. All functions are define by global administration.
+There are only 2 differents roles. An admin role and a basic role. An admin can change
+all settings of this projects and create/update milestone.
+
+### Change function to members
+
+in list of member, you can change all functions to members. If you change the select
+and click on update all, all members are updated. The limitation is only to have
+just one admin in each project. If you change all member's function to have no admin
+the changement is rollback.
+
 ## Delete project
 
 Since Oupsnow-0.4.0, you can delete a project. If you delete a project all</diff>
      <filename>doc/manual.markdown</filename>
    </modified>
    <modified>
      <diff>@@ -10,6 +10,10 @@ Then /^I should see an? (\w+) message$/ do |message_type|
   webrat_session.response.should have_xpath(&quot;//*[@class='#{message_type}']&quot;)
 end
 
+Then /^I should see id (\w+)$/ do |id_txt|
+  webrat_session.response.should have_xpath(&quot;//*[@id='#{id_txt}']&quot;)
+end
+
 Then /^I should see (\d+) &quot;(\w+)&quot; tag with content &quot;(\w+)&quot;$/ do |num, tag_name, content|
   webrat_session.response.should have_selector(tag_name, :content =&gt; content, :count =&gt; num.to_i)
 end
@@ -47,7 +51,7 @@ Given /^(\d+) tickets with state &quot;([^\&quot;]*)&quot; on project &quot;(.*)&quot;$/ do |num, state_n
   project = Project.first(:name =&gt; project_name)
   project = Project.gen(:name =&gt; project_name) unless project
   num.to_i.times {
-    Ticket.gen(:state =&gt; state,
+     Ticket.gen(:state_id =&gt; state.id,
                :project_id =&gt; project.id)
   }
 end
@@ -58,8 +62,54 @@ Given /^(\d+) tickets with state &quot;([^\&quot;]*)&quot; and tag &quot;([^\&quot;]*)&quot; on project &quot;([^\&quot;
   project = Project.first(:name =&gt; project_name)
   project = Project.gen(:name =&gt; project_name) unless project
   num.to_i.times {
-    Ticket.gen(:state =&gt; state,
+    Ticket.gen(:state_id =&gt; state.id,
                :project_id =&gt; project.id,
                :tag_list =&gt; tag_name)
   }
 end
+
+def user_with_name(name)
+  user = User.first(:login =&gt; name)
+  user = User.gen(:login =&gt; name) unless user
+  user
+end
+
+def project_with_name(name)
+  project = Project.first(:name =&gt; name)
+  project = Project.gen(:name =&gt; name) unless project
+  project
+end
+
+def function_with_name(name)
+  function = Function.first(:name =&gt; name)
+  function = Function.gen(:name =&gt; name,
+                         :project_admin =&gt; (name == 'admin')) unless function
+  function
+end
+
+Given /^I have user &quot;([^\&quot;]*)&quot; with function &quot;([^\&quot;]*)&quot; on project &quot;([^\&quot;]*)&quot;$/ do |user_name, function_name, project_name|
+  user = user_with_name(user_name)
+  project = project_with_name(project_name)
+  function = function_with_name(function_name)
+  member = project.members.build(:user =&gt; user, :function =&gt; function)
+  member.save
+end
+
+Given /^I have user &quot;([^\&quot;]*)&quot; with function &quot;([^\&quot;]*)&quot; on project &quot;([^\&quot;]*)&quot; and no other user$/ do |user_name, function_name, project_name|
+  Given %{I have user &quot;#{user_name}&quot; with function &quot;#{function_name}&quot; on project &quot;#{project_name}&quot;}
+
+  user = user_with_name(user_name)
+  project = project_with_name(project_name)
+  project.members.all(:user_id.not =&gt; user.id).each { |m| m.destroy }
+end
+
+Then /^the member &quot;([^\&quot;]*)&quot; has function &quot;([^\&quot;]*)&quot; in project &quot;([^\&quot;]*)&quot;$/ do |user_name, function_name, project_name|
+  User.first(:login =&gt; user_name).members.first(:project_id =&gt; Project.first(:name =&gt; project_name).id).function.name.should == function_name
+end
+
+When /transaction commit/ do
+  transaction = DataMapper.repository(:default).adapter.pop_transaction
+  transaction.commit
+end
+
+</diff>
      <filename>features/steps/result_steps.rb</filename>
    </modified>
    <modified>
      <diff>@@ -17,7 +17,12 @@ When /^I fill in &quot;(.*)&quot; with &quot;(.*)&quot;$/ do |field, value|
   @response = fill_in(field, :with =&gt; value) 
 end
 
-When /^I select &quot;(.*)&quot; from &quot;(.*)&quot;$/ do |value, field|
+When /^I select &quot;([^\&quot;]*)&quot; from &quot;([^\&quot;]*)&quot;$/ do |value, field|
+  @response = select(value, :from =&gt; field) 
+end
+
+When /^I select &quot;([^\&quot;]*)&quot; from &quot;member_function&quot; of &quot;([^\&quot;]*)&quot; from &quot;([^\&quot;]*)&quot; project$/ do |value, user_name, project_name|
+  field = &quot;member_function[#{User.first(:login =&gt; user_name).members.first(:project_id =&gt; Project.first(:name =&gt; project_name).id).id}]&quot;
   @response = select(value, :from =&gt; field) 
 end
 </diff>
      <filename>features/steps/webrat_steps.rb</filename>
    </modified>
    <modified>
      <diff>@@ -29,22 +29,23 @@ Function.fixture(:admin) {{
 Project.fixture {{
   :name =&gt; /\w+/.gen,
   :description =&gt; (0..3).of { /[:paragraph:]/.generate }.join(&quot;\n&quot;),
-  :members =&gt; [:function =&gt; (Function.admin ? Function.admin : Function.gen(:admin)), 
-    :user =&gt; (User.first(:login =&gt; 'admin') ? User.first(:login =&gt; 'admin') : User.gen(:admin))]
+  :members =&gt; [:function_id =&gt; (Function.admin ? Function.admin.id : Function.gen(:admin).id), 
+    :user_id =&gt; (User.first(:login =&gt; 'admin') ? User.first(:login =&gt; 'admin').id : User.gen(:admin).id)]
 }}
 
 Member.fixture {{
-  :user_id =&gt; User.first ? User.gen.id : User.first.id,
-  :project_id =&gt; (Project.first ? Project.gen.id : Project.first.id),
-  :function_id =&gt; (Function.first ? Function.gen.id : Function.first.id),
+  :user_id =&gt; (User.first ? User.first.id : User.gen!.id),
+  :project_id =&gt; (Project.first ? Project.first.id : Project.gen!.id),
+  :function_id =&gt; (Function.first ? Function.first.id : Function.gen.id),
 }}
 
 Ticket.fixture {{
   :title =&gt; /\w+/.gen,
   :description =&gt; (0..3).of { /[:paragraph:]/.generate }.join(&quot;\n&quot;),
   :tag_list =&gt; (1..2).of { /\w+/.generate }.join(','),
-  :project_id =&gt; (Project.first ? Project.gen.id : Project.first.id),
-  :member_create_id =&gt; User.first ? User.gen.id : User.first.id,
+  :project_id =&gt; (Project.first ? Project.first.id : Project.gen.id),
+  :member_create_id =&gt; User.first ? User.first.id : User.gen.id,
+  :state_id =&gt; State.first ? State.first.id : State.gen.id,
 }}
 
 State.fixture {{
@@ -63,8 +64,8 @@ Milestone.fixture {{
 
 Event.fixture {{
   :eventable_class =&gt; 'Ticket',
-  :eventable_id =&gt; (Ticket.first ? Ticket.gen.id : Ticket.first.id),
+  :eventable_id =&gt; (Ticket.first ? Ticket.first.id : Ticket.gen.id),
   :event_type =&gt; :created,
-  :user_id =&gt; User.first ? User.gen.id : User.first.id,
-  :project_id =&gt; (Project.first ? Project.gen.id : Project.first.id)
+  :user_id =&gt; User.first ? User.first.id : User.gen.id,
+  :project_id =&gt; (Project.first ? Project.first.id : Project.gen.id)
 }}</diff>
      <filename>spec/fixtures.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,7 +3,43 @@ require File.join( File.dirname(__FILE__), '..', &quot;spec_helper&quot; )
 describe Member do
 
   it &quot;should have dm-sweatshop valid&quot; do
-    Member.make.should be_valid
+    Member.gen.should be_valid
+  end
+
+  describe &quot;self#change_functions&quot; do
+
+    it &quot;should render true if no member_function send&quot; do
+      Member.change_functions({}).should be_true
+    end
+
+    it &quot;should change member function&quot; do
+      project = Project.gen
+      member = Member.gen!(:project_id =&gt; project.id)
+      transaction = DataMapper.repository(:default).adapter.pop_transaction
+      transaction.commit
+      Member.change_functions({member.id =&gt; Function.admin.id}).should be_true
+      member.reload.function.should == Function.admin
+    end
+
+    it &quot;should not change member function if this no admin in project&quot; do
+      project = Project.gen
+      member_admin = project.members.first
+      member_admin.function.should be_project_admin
+      member = Member.gen!(:project_id =&gt; project.id, :user_id =&gt; User.gen.id)
+      project.reload
+      Function.gen! unless Function.not_admin # Need a function not admin
+      transaction = DataMapper.repository(:default).adapter.pop_transaction
+      transaction.commit
+      Member.change_functions({member_admin.id =&gt; Function.not_admin.id,
+                               member.id =&gt; Function.not_admin.id}).should be_false
+      member_admin.reload.function.should be_project_admin
+      # Need delete all add before commit
+      Project.all.each {|pr| pr.destroy}
+      Member.all.each {|pr| pr.destroy}
+      project.destroy
+      member_admin.destroy
+      member.destroy
+    end
   end
 
 end</diff>
      <filename>spec/models/member_spec.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>f856336c92860cc24de18e980b4b6b5d132edc52</id>
    </parent>
  </parents>
  <author>
    <name>Cyril Mougel</name>
    <email>cyril.mougel@gmail.com</email>
  </author>
  <url>http://github.com/shingara/oupsnow/commit/2ede3e12e483ba82394a8d8acb406274613e4bef</url>
  <id>2ede3e12e483ba82394a8d8acb406274613e4bef</id>
  <committed-date>2009-06-11T00:36:35-07:00</committed-date>
  <authored-date>2009-06-11T00:36:35-07:00</authored-date>
  <message>add availability to change function to each member of project see #17</message>
  <tree>cc32909eb898784593f57942d6e1fc9441a2c4f8</tree>
  <committer>
    <name>Cyril Mougel</name>
    <email>cyril.mougel@gmail.com</email>
  </committer>
</commit>
