Complete refactoring of messaging module. From now messages are saved only once and send afterwards via a the 'send_emails'-rake-task.

This commit is contained in:
Benjamin Meichsner 2009-01-15 18:26:37 +01:00
parent 6ce6c2c75a
commit e8d55e50c0
30 changed files with 220 additions and 349 deletions

1
.gitignore vendored
View File

@ -3,4 +3,5 @@ tmp/**/*
config/*.yml config/*.yml
db/*.sqlite3 db/*.sqlite3
nbproject/ nbproject/
config/environments/development.rb

View File

@ -12,6 +12,15 @@ class ApplicationController < ActionController::Base
def self.current def self.current
Thread.current[:application_controller] Thread.current[:application_controller]
end end
# Use this method to call a rake task,,
# e.g. to deliver mails after there are created.
def call_rake(task, options = {})
options[:rails_env] ||= Rails.env
args = options.map { |n, v| "#{n.to_s.upcase}='#{v}'" }
system "/usr/bin/rake #{task} #{args.join(' ')} --trace 2>&1 >> #{Rails.root}/log/rake.log &"
end
protected protected
@ -139,7 +148,7 @@ class ApplicationController < ActionController::Base
# Sends any pending emails that were created during this request. # Sends any pending emails that were created during this request.
def send_email_messages def send_email_messages
Message.send_emails if Message.pending? call_rake :send_emails unless Message.pending.empty?
end end
end end

View File

@ -6,8 +6,6 @@ class HomeController < ApplicationController
if @orderGroup if @orderGroup
@financial_transactions = @orderGroup.financial_transactions.find(:all, :order => 'created_on desc', :limit => 3) @financial_transactions = @orderGroup.financial_transactions.find(:all, :order => 'created_on desc', :limit => 3)
end end
# unread messages
@messages = Message.find_all_by_recipient_id_and_read(@current_user.id, false, :order => 'messages.created_on desc', :include => :sender)
# unaccepted tasks # unaccepted tasks
@unaccepted_tasks = @current_user.unaccepted_tasks @unaccepted_tasks = @current_user.unaccepted_tasks
# task in next week # task in next week

View File

@ -1,27 +1,10 @@
class MessagesController < ApplicationController class MessagesController < ApplicationController
verify :method => :post, :only => [:create, :destroy], :redirect_to => { :action => :index }
MESSAGE_SEND_SUCCESS = 'Nachricht erfolgreich abgeschickt.'
MESSAGE_DELETE_SUCCESS = 'Nachricht gelöscht.'
MESSAGES_DELETE_SUCCESS = 'Nachrichten gelöscht.'
ERROR_SEND_FAILED = 'Nachricht konnte nicht verschickt werden.'
ERROR_CANNOT_DELETE = 'Nachricht kann nicht gelöscht werden.'
ERROR_CANNOT_REPLY = 'Auf diese Nachricht kann nicht geantwortet werden.'
ERROR_UNKNOWN_USER = 'Unbekannte_r Empfänger_in.'
ERROR_INVALID_GROUP = 'Empfängergruppe ist unbekannt oder hat keine Mitglieder.'
ERROR_NO_RECIPIENTS = 'Es sind keine Empfänger_innen ausgewählt.'
# Renders the "inbox" action. # Renders the "inbox" action.
def index def index
inbox @messages = Message.user
render :action => 'inbox'
end end
# Shows the user's message inbox.
def inbox
@messages = Message.find_all_by_recipient_id(@current_user.id, :order => 'messages.created_on desc', :include => :sender)
end
# Creates a new message object. # Creates a new message object.
def new def new
@message = Message.new @message = Message.new
@ -29,136 +12,58 @@ class MessagesController < ApplicationController
# Creates a new message. # Creates a new message.
def create def create
# Determine recipient(s)... @message = @current_user.send_messages.new(params[:message])
@recipient_nicks = '' if @message.save
if (params[:everyone] == 'yes') flash[:notice] = "Nachricht ist gespeichert und wird versendet."
@everyone = true redirect_to messages_path
recipients = User.find(:all)
else else
recipients = Array.new
# users
for nick in params[:recipient][:nicks].split(%r{,\s*})
if (user = User.find_by_nick(nick))
recipients << user
@recipient_nicks += "#{nick}, "
end
end
@recipient_nicks = @recipient_nicks[0..-3] unless @recipient_nicks.empty?
# group
group = Group.find_by_id(params[:recipient][:group_id]) if params[:recipient][:group_id]
recipients = recipients | group.users if group
end
# Construct message(s) and save them...
if recipients.empty?
@message = Message.new(params[:message])
@message.sender = @current_user
@group = group
flash[:error] = ERROR_NO_RECIPIENTS
render :action => 'new' render :action => 'new'
else
begin
if (@everyone)
recipients_text = 'alle'
else
recipients_text = @recipient_nicks
recipients_text += (group.nil? ? '' : (recipients_text.empty? ? group.name : ", #{group.name}"))
end
Message.transaction do
for recipient in recipients
@message = Message.new(
:subject => params[:message][:subject],
:body => params[:message][:body],
:recipient => recipient,
:recipients => recipients_text
)
@message.sender = @current_user
@message.save!
end
end
flash[:notice] = MESSAGE_SEND_SUCCESS
redirect_to :action=> 'index'
rescue
@group = group
flash[:error] = ERROR_SEND_FAILED
render :action => 'new'
end
end end
end end
# Deletes the message(s) specified by the id/ids param if the current user is the recipient.
def destroy
ids = Array.new
ids << params[:id] if params[:id]
ids = ids + params[:ids] if (params[:ids] && params[:ids].is_a?(Array))
for id in ids
message = Message.find(id)
if (message && message.recipient && message.recipient == @current_user)
message.destroy
else
flash[:error] = ERROR_CANNOT_DELETE
break
end
end
flash[:notice] = MESSAGE_DELETE_SUCCESS if (flash[:error].blank? && ids.size == 1)
flash[:notice] = "#{ids.size} #{MESSAGES_DELETE_SUCCESS}" if (flash[:error].blank? && ids.size > 1)
redirect_to :action=> 'index'
end
# Shows a single message. # Shows a single message.
def show def show
@message = Message.find_by_id_and_recipient_id(params[:id], @current_user.id) @message = Message.find(params[:id])
@message.update_attribute('read', true) if (@message && !@message.read?)
end end
# Replys to the message specified through :id. # Replys to the message specified through :id.
def reply def reply
message = Message.find(params[:id]) message = Message.find(params[:id])
if (message && message.recipient && message.recipient == @current_user && message.sender && message.sender.nick) @message = Message.new(:recipient => message.sender, :subject => "Re: #{message.subject}")
@message = Message.new( @message.body = "#{message.sender.nick} schrieb am #{I18n.l(message.created_at.to_date)} um #{I18n.l(message.created_at, :format => :time)}:\n"
:recipient => message.sender, message.body.each_line{|l| @message.body += "> #{l}"}
:subject => "Re: #{message.subject}", render :action => 'new'
:body => "#{message.sender.nick} schrieb am #{I18n.l(message.created_on.to_date)} um #{I18n.l(message.created_on, :format => :time)}:\n"
)
if (message.body)
message.body.each_line{|l| @message.body += "> #{l}"}
end
@recipient_nicks = message.sender.nick
render :action => 'new'
else
flash[:error] = ERROR_CANNOT_REPLY
redirect_to :action=> 'index'
end
end end
# Shows new-message form with the recipient user specified through :id. # Shows new-message form with the recipient user specified through :id.
def user def user
if (recipient = User.find(params[:id])) if (recipient = User.find(params[:id]))
@recipient_nicks = recipient.nick @message = Message.new(:recipient => recipient)
@message = Message.new
render :action => 'new' render :action => 'new'
else else
flash[:error] = ERROR_UNKNOWN_USER flash[:error] = 'Unbekannte_r EmpfängerIn.'
redirect_to :action=> 'index' redirect_to :action=> 'index'
end end
end end
# Shows new-message form with the recipient user specified through :id. # Shows new-message form with the recipient user specified through :id.
def group def group
recipient = Group.find(params[:id], :include => :memberships) group = Group.find(params[:id], :include => :memberships)
if (recipient && !recipient.memberships.empty?) if (group && !group.memberships.empty?)
@message = Message.new @message = Message.new(:group_id => group.id)
@group = recipient
render :action => 'new' render :action => 'new'
else else
flash[:error] = ERROR_INVALID_GROUP flash[:error] = 'Empfängergruppe ist unbekannt oder hat keine Mitglieder.'
redirect_to :action=> 'index' redirect_to :action=> 'index'
end end
end end
# Auto-complete for recipient user list. # Auto-complete for recipient user list.
def auto_complete_for_recipient_nicks def auto_complete_for_message_recipients_nicks
@users = User.find(:all, :conditions => ['LOWER(nick) LIKE ?', '%' + params[:recipient][:nicks].downcase + '%'], :order => :nick, :limit => 8) @users = User.find(:all,
:conditions => ['LOWER(nick) LIKE ?', '%' + params[:message][:recipients_nicks].downcase + '%'],
:order => :nick, :limit => 8)
render :partial => '/shared/auto_complete_users' render :partial => '/shared/auto_complete_users'
end end

View File

@ -0,0 +1,17 @@
module MessagesHelper
def groups_for_select
groups = [[" -- Arbeitsgruppen -- ", ""]]
groups += Workgroup.find(:all, :order => 'name', :include => :memberships).reject{ |g| g.memberships.empty? }.collect do |g|
[g.name, g.id]
end
groups += [[" -- Bestellgruppen -- ", ""]]
groups += Ordergroup.find(:all, :order => 'name', :include => :memberships).reject{ |g| g.memberships.empty? }.collect do |g|
[g.name, g.id]
end
groups
end
def format_subject(message)
truncate "<b>#{link_to(h(message.subject), message)}</b> <span style='color:grey'>#{h(message.body)}</span>", :length => 200
end
end

View File

@ -21,9 +21,9 @@ class Mailer < ActionMailer::Base
from (message.system_message? ? "FoodSoft <#{APP_CONFIG[:email_sender]}>" : "#{message.sender.nick} <#{message.sender.email}>") from (message.system_message? ? "FoodSoft <#{APP_CONFIG[:email_sender]}>" : "#{message.sender.nick} <#{message.sender.email}>")
body :body => message.body, :sender => (message.system_message? ? 'Foodsoft' : message.sender.nick), body :body => message.body, :sender => (message.system_message? ? 'Foodsoft' : message.sender.nick),
:recipients => message.recipients, :recipients => message.recipients,
:reply => url_for(:host => request.host, :controller => "messages", :action => "reply", :id => message), :reply => url_for(:host => request.host, reply_message_path(message),
:profile => url_for(:host => request.host, :controller => "index", :action => "myProfile", :id => message.recipient), :profile => url_for(:host => request.host, my_profile_path),
:link => url_for(:host => request.host, :controller => "messages", :action => "show", :id => message), :link => url_for(:host => request.host, message_path(message),
:foodsoftUrl => url_for(:host => request.host, :controller => "index") :foodsoftUrl => url_for(:host => request.host, :controller => "index")
end end

View File

@ -1,88 +1,88 @@
# == Schema Information # == Schema Information
# Schema version: 20090102171850 # Schema version: 20090115123421
# #
# Table name: messages # Table name: messages
# #
# id :integer(4) not null, primary key # id :integer(4) not null, primary key
# sender_id :integer(4) # sender_id :integer(4)
# recipient_id :integer(4) default(0), not null # recipients_ids :text default(""), not null
# recipients :string(255) default(""), not null # subject :string(255) not null
# subject :string(255) default(""), not null # body :text
# body :text default(""), not null # email_state :integer(4) default(0), not null
# read :boolean(1) not null # private :boolean(1)
# email_state :integer(4) default(0), not null # created_at :datetime
# created_on :datetime not null
# #
class Message < ActiveRecord::Base class Message < ActiveRecord::Base
belongs_to :sender, :class_name => "User", :foreign_key => "sender_id" belongs_to :sender, :class_name => "User", :foreign_key => "sender_id"
belongs_to :recipient, :class_name => "User", :foreign_key => "recipient_id"
attr_accessible :recipient_id, :recipient, :subject, :body, :recipients
serialize :recipients_ids, Array
attr_accessor :sent_to_all, :group_id, :recipients_nicks
named_scope :pending, :conditions => { :email_state => 0 }
named_scope :sent, :conditions => { :email_state => 1 }
named_scope :user, :conditions => "sender_id IS NOT NULL", :order => 'created_at DESC', :include => :sender
# Values for the email_state attribute: :none, :pending, :sent, :failed # Values for the email_state attribute: :none, :pending, :sent, :failed
EMAIL_STATE = { EMAIL_STATE = {
:none => 0, :pending => 0,
:pending => 1, :sent => 1,
:sent => 2, :failed => 2
:failed => 3
} }
validates_presence_of :recipient_id validates_presence_of :recipients_ids, :subject, :body
validates_length_of :subject, :in => 1..255 validates_length_of :subject, :in => 1..255
validates_presence_of :recipients
validates_presence_of :body
validates_inclusion_of :email_state, :in => EMAIL_STATE.values validates_inclusion_of :email_state, :in => EMAIL_STATE.values
@@pending = false
# clean up the recipients_ids
# Automatically determine if this message should be send as an email.
def before_validation_on_create def before_validation_on_create
if (recipient && recipient.settings["messages.sendAsEmail"] == '1') self.recipients_ids = recipients_ids.uniq.reject { |id| id.blank? } unless recipients_ids.nil?
self.email_state = EMAIL_STATE[:pending] self.recipients_ids = User.all.collect(&:id) if sent_to_all == 1
else
self.email_state = EMAIL_STATE[:none]
end
end end
# Determines if this new message is a pending email. def add_recipients(users)
def after_create self.recipients_ids = [] if recipients_ids.blank?
@@pending = @@pending || self.email_state == EMAIL_STATE[:pending] self.recipients_ids += users.collect(&:id) unless users.blank?
end end
# Returns true if there might be pending emails. def group_id=(group_id)
def self.pending? @group_id = group_id
@@pending add_recipients Group.find(group_id).users unless group_id.blank?
end
def recipients_nicks=(nicks)
@recipients_nicks = nicks
add_recipients nicks.split(",").collect { |nick| User.find_by_nick(nick) }
end
def recipient=(user)
@recipients_nicks = user.nick
end end
# Returns true if this message is a system message, i.e. was sent automatically by the FoodSoft itself. # Returns true if this message is a system message, i.e. was sent automatically by the FoodSoft itself.
def system_message? def system_message?
self.sender_id.nil? self.sender_id.nil?
end end
def sender_name
system_message? ? 'Foodsoft' : sender.nick
end
def recipients
User.find(recipients_ids)
end
# Sends all pending messages that are to be send as emails. # Sends all pending messages that are to be send as emails.
def self.send_emails def self.send_emails
transaction do messages = Message.pending
messages = find(:all, :conditions => ["email_state = ?", EMAIL_STATE[:pending]], :lock => true) for message in messages
logger.debug("Sending #{messages.size} pending messages as emails...") unless messages.empty? for recipient in message.recipients
for message in messages if recipient.settings['messages.sendAsEmail'] == 1 && !recipient.email.blank?
if (message.recipient && message.recipient.email && !message.recipient.email.empty?) Mailer.deliver_message(message)
begin
Mailer.deliver_message(message)
message.update_attribute(:email_state, EMAIL_STATE[:sent])
logger.debug("Delivered message as email: id = #{message.id}, recipient = #{message.recipient.nick}, subject = \"#{message.subject}\"")
rescue => exception
message.update_attribute(:email_state, EMAIL_STATE[:failed])
logger.warn("Failed to deliver message as email: id = #{message.id}, recipient = #{message.recipient.nick}, subject = \"#{message.subject}\", exception = #{exception.message}")
end
else
message.update_attribute(:email_state, EMAIL_STATE[:failed])
logger.warn("Cannot deliver message as email (no user email): id = #{message.id}, recipient = #{message.recipient.nick}, subject = \"#{message.subject}\"")
end end
end end
logger.debug("Done sending emails.") unless messages.empty? message.update_attribute(:email_state, 1)
@@pending = false
end end
end end

View File

@ -322,18 +322,15 @@ class Order < ActiveRecord::Base
ordergroup = Ordergroup.find_by_name(group_order.group_name) ordergroup = Ordergroup.find_by_name(group_order.group_name)
# Determine group users that want a notification message: # Determine group users that want a notification message:
users = ordergroup.users.reject{|u| u.settings["notify.orderFinished"] != '1'} users = ordergroup.users.reject{|u| u.settings["notify.orderFinished"] != '1'}
unless (users.empty?) unless users.empty?
# Assemble the order message text: # Assemble the order message text:
results = group_order.group_order_article_results.find(:all, :include => [:order_article_result]) results = group_order.group_order_article_results.find(:all, :include => [:order_article_result])
# Create user notification messages: # Create user notification messages:
recipients = users.collect{|u| u.nick}.join(', ') Message.from_template(
for user in users 'order_finished',
Message.from_template( {:group => ordergroup, :order => self, :results => results, :total => group_order.price},
'order_finished', {:recipients_ids => users.collect(&:id), :subject => "Bestellung beendet: #{self.name}"}
{:user => user, :group => ordergroup, :order => self, :results => results, :total => group_order.price}, ).save!
{:recipient_id => user.id, :recipients => recipients, :subject => "Bestellung beendet: #{self.name}"}
).save!
end
end end
end end
end end

View File

@ -118,15 +118,13 @@ class Ordergroup < Group
def notifyNegativeBalance(transaction) def notifyNegativeBalance(transaction)
# Notify only when order group had a positive balance before the last transaction: # Notify only when order group had a positive balance before the last transaction:
if (transaction.amount < 0 && self.account_balance < 0 && self.account_balance - transaction.amount >= 0) if (transaction.amount < 0 && self.account_balance < 0 && self.account_balance - transaction.amount >= 0)
users = self.users.reject{|u| u.settings["notify.negativeBalance"] != '1'} users = self.users.reject { |u| u.settings["notify.negativeBalance"] != '1' }
unless (users.empty?) unless users.empty?
recipients = users.collect{|u| u.nick}.join(', ') Message.from_template(
for user in users 'negative_balance',
Message.from_template( {:group => self, :transaction => transaction},
'negative_balance', {:recipients_ids => users.collect(&:id), :subject => "Gruppenkonto im Minus"}
{:user => user, :group => self, :transaction => transaction}, ).save!
{:recipient_id => user.id, :recipients => recipients, :subject => "Gruppenkonto im Minus"}
).save!
end end
end end
end end

View File

@ -26,6 +26,7 @@ class User < ActiveRecord::Base
has_many :ordergroups, :through => :memberships, :source => :group has_many :ordergroups, :through => :memberships, :source => :group
has_many :assignments, :dependent => :destroy has_many :assignments, :dependent => :destroy
has_many :tasks, :through => :assignments has_many :tasks, :through => :assignments
has_many :send_messages, :class_name => "Message", :foreign_key => "sender_id"
attr_accessor :password, :setting_attributes attr_accessor :password, :setting_attributes

View File

@ -27,13 +27,6 @@
= _("There are") + " #{@unassigned_tasks_number} " + link_to(_("unassigned task(s)"), :controller => "tasks") = _("There are") + " #{@unassigned_tasks_number} " + link_to(_("unassigned task(s)"), :controller => "tasks")
%p{:style => "clear:both"}= link_to _("My tasks"), :controller => "tasks", :action => "myTasks" %p{:style => "clear:both"}= link_to _("My tasks"), :controller => "tasks", :action => "myTasks"
- unless @messages.empty?
.box_title
%h2=_ "Unread messages"
.column_content
= render :partial => 'messages/unread'
%p= link_to _("All messages"), :controller => 'messages', :action => 'inbox'
- if @orderGroup - if @orderGroup
// Current orders // Current orders
= render :partial => 'ordering/currentOrders' = render :partial => 'ordering/currentOrders'

View File

@ -3,7 +3,7 @@
tabs = [ tabs = [
{ :name => "Start", :url => root_path, :active => ["index", "messages", "home"], { :name => "Start", :url => root_path, :active => ["index", "messages", "home"],
:subnav => [ :subnav => [
{ :name => "Messages", :url => "/messages/inbox"}, { :name => "Messages", :url => "/messages"},
{ :name => "My tasks", :url => "/home/tasks" }, { :name => "My tasks", :url => "/home/tasks" },
{ :name => "My ordergroup", :url => "/home/ordergroup"}, { :name => "My ordergroup", :url => "/home/ordergroup"},
{ :name => "My profile", :url => "/home/profile"} { :name => "My profile", :url => "/home/profile"}

View File

@ -1,26 +0,0 @@
- unless @messages.empty?
- form_tag :action => 'destroy' do
%table.list
%thead
%tr
%th
%input{:type => 'checkbox', :name => 'checkall', :id => 'checkall', :onclick => 'checkUncheckAll(this)'}
%th Betreff
%th Absender
%th Datum
%th
%tbody
- for message in @messages
- style = message.read? ? '' : 'font-weight:bold'
%tr{:class => cycle('even','odd', :name => 'inbox'), :style => style, :id => message.id, :onclick => "checkRow('#{message.id}')"}
%td
%input{:type => 'checkbox', :name => 'ids[]', :id => "checkbox_#{message.id}", :value => message.id, :onclick => "checkRow('#{message.id}')"}
%td= link_to(h(message.subject), {:controller => 'messages', :action => 'show', :id => message})
%td= message.sender ? h(message.sender.nick) : 'FoodSoft'
%td= format_time(message.created_on)
%td
= link_to(image_tag('b_drop.png', :size => "16x16", :border => 0, :alt => 'löschen'), {:controller => 'messages', :action => 'destroy', :id => message}, :method => "post")
= link_to('Antworten', :controller => 'messages', :action => 'reply', :id => message) unless message.system_message?
%tr
%td{:colspan => 5}= submit_tag 'Löschen'

View File

@ -0,0 +1,12 @@
- unless @messages.empty?
- form_tag :action => 'destroy' do
%table.list
%tbody
- for message in @messages
%tr{:class => cycle('even','odd', :name => 'messages')}
%td
%b= h(message.sender_name)
%td= format_subject(message)
%td= format_time(message.created_at)
%td= link_to('Antworten', reply_message_path(message))

View File

@ -1,15 +0,0 @@
- unless @messages.empty?
%table.list
%thead
%tr
%th Betreff
%th Absender
%th Datum
%tbody
- for message in @messages
%tr{:class => cycle('even','odd', :name => 'inbox')}
%td= link_to(h(message.subject), {:controller => 'messages', :action => 'show', :id => message})
%td= message.sender ? h(message.sender.nick) : 'FoodSoft'
%td= format_time(message.created_on)

View File

@ -1,5 +0,0 @@
%h1 Nachrichten - Eingang
%p= link_to('Neue Nachricht', :action => 'new')
= render :partial => 'list'

View File

@ -0,0 +1,6 @@
- title "Nachrichten im Überblick"
%p= link_to('Neue Nachricht', :action => 'new')
#messages
= render :partial => 'messages'

View File

@ -1,6 +1,6 @@
Hallo <%= user.nick %>! Liebe <%= group.name %>,
Der Kontostand deiner Bestellgruppe <%= group.name %> ist durch eine Buchung am <%= transaction.created_on.strftime('%d.%m.%Y um %H:%M') %> ins Minus gerutscht: <%= group.account_balance %> euer Kontostand ist durch eine Buchung am <%= transaction.created_on.strftime('%d.%m.%Y um %H:%M') %> ins Minus gerutscht: <%= group.account_balance %>
Es wurden <%= transaction.amount %> für "<%= transaction.note %>" abgebucht, die Buchung wurde von <%= transaction.user.nick %> erstellt. Es wurden <%= transaction.amount %> für "<%= transaction.note %>" abgebucht, die Buchung wurde von <%= transaction.user.nick %> erstellt.

View File

@ -1,23 +1,20 @@
%h1 Neue Nachricht %h1 Neue Nachricht
- form_tag(:action => 'create') do - form_for @message do |f|
= error_messages_for 'message' = f.error_messages
%p %p
%label{:for => "message_recipient"} An
%fieldset %fieldset
<input type="checkbox" name="everyone" value="yes" = f.check_box :sent_to_all, :onchange => "Element.toggle('recipients')"
= "checked='checked'" if @everyone
onchange="Element.toggle('recipients')" />
gesamte Foodcoop gesamte Foodcoop
%table{:id => 'recipients', :style => (@everyone ? 'display:none;' : '')} %table#recipients
%tr %tr
%td %td
%b BenutzerInnen: %b BenutzerInnen:
%br/ %br/
%small{:style => "color:grey"} (Mehrere Benutzerinnen mit Komma trennen) %small{:style => "color:grey"} (Mehrere Benutzerinnen mit Komma trennen)
%br/ %br/
= text_field_with_auto_complete(:recipient, :nicks, {:value => @recipient_nicks}, {:tokens => ","}) = text_field_with_auto_complete(:message, :recipients_nicks, {:value => @message.recipients_nicks}, {:tokens => ","})
:javascript :javascript
var userListLoaded = false; var userListLoaded = false;
function checkUserList() { function checkUserList() {
@ -27,23 +24,21 @@
return !userListLoaded; return !userListLoaded;
} }
= link_to_remote('Liste', :update => 'user-list', :url => {:action => 'user_list'}, :complete => 'userListLoaded = true', :condition => 'checkUserList()') = link_to_remote('Liste', :update => 'user-list', :url => {:action => 'user_list'}, :complete => 'userListLoaded = true', :condition => 'checkUserList()')
%div{:id => 'user-list', :class => 'auto_complete'} #user-list.auto_complete
%tr %tr
%td %td
%b Gruppe: %b Gruppe:
%br/ %br/
%select{:name => 'recipient[group_id]'} = f.select :group_id, groups_for_select, :prompt => " -- Gruppe auswählen --"
%option{:value => '-1'} -- Gruppe --
= options_from_collection_for_select(Group.find(:all, :order => 'name', :include => :memberships).reject{|g| g.memberships.empty?}, "id", "name", (@group ? @group.id : nil))
%p %p
%label{:for => "message_subject"} Betreff = f.label :subject, "Betreff"
%br/ %br/
= text_field 'message', 'subject' = f.text_field :subject
%p %p
%label{:for => "message_body"} Nachricht = f.label :body, "Nachricht"
%br/ %br/
= preserve(text_area 'message', 'body', :cols => '80', :rows => '20') ~ f.text_area :body, :cols => '80', :rows => '20'
= submit_tag "Senden" = submit_tag "Senden"

View File

@ -1,8 +1,8 @@
Hallo <%= user.nick %>! Liebe <%= group.name %>,
Die Bestellung "<%= order.name %>" wurde am <%= order.ends.strftime('%d.%m.%Y um %H:%M') %> von <%= order.updated_by.nick %> beendet. die Bestellung "<%= order.name %>" wurde am <%= order.ends.strftime('%d.%m.%Y um %H:%M') %> von <%= order.updated_by.nick %> beendet.
Für deine Bestellgruppe <%= group.name %> wurden die folgenden Artikel bestellt: Für Euch wurden die folgenden Artikel bestellt:
<% for result in results <% for result in results
article = result.order_article_result -%> article = result.order_article_result -%>
<%= article.name %>: <%= result.quantity %> x <%= article.unit %> = <%= result.quantity * article.gross_price %> <%= article.name %>: <%= result.quantity %> x <%= article.unit %> = <%= result.quantity * article.gross_price %>

View File

@ -1,28 +1,21 @@
%h1 Nachricht anzeigen - title "Nachricht anzeigen"
%div{:style => "width:40em"} %div{:style => "width:40em"}
- if @message %table{:style => "width:25em"}
%table{:style => "width:25em"} %tr
%tr %td Von:
%td Von: %td=h @message.sender_name
%td=h @message.system_message? ? 'FoodSoft' : @message.sender.nick %tr
%tr %td Betreff:
%td An: %td
%td=h @message.recipients %b=h @message.subject
%tr %tr
%td Betreff: %td Gesendet:
%td %td= format_time(@message.created_at)
%b=h @message.subject %hr/
%tr %p= simple_format(h(@message.body))
%td Gesendet: %hr/
%td= format_time(@message.created_on) %p
%hr/ = link_to('Antworten', reply_message_path(@message))
%p= simple_format(h(@message.body)) |
%hr/ = link_to 'Nachricht im Überblick', messages_path
%p
= link_to('Antworten', :action => 'reply', :id => @message) + ' | ' unless @message.system_message?
= link_to('Löschen', {:action => 'destroy', :id => @message}, :method => "post")
|
= link_to 'Nachrichteneingang', :action => 'inbox'
- else
%p Nachricht kann nicht angezeigt werden.

View File

@ -1,29 +0,0 @@
# Settings specified here will take precedence over those in config/environment.rb
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the webserver when you make code changes.
config.cache_classes = false
# Log error messages when you accidentally call methods on nil.
config.whiny_nils = true
# Show full error reports and disable caching
config.action_controller.consider_all_requests_local = true
config.action_controller.perform_caching = false
config.action_view.debug_rjs = true
# Don't care if the mailer can't send
config.action_mailer.raise_delivery_errors = false
# Configure an SMTP server for email sending in development mode:
# (cf. http://rails.rubyonrails.com/classes/ActionMailer/Base.html for info on options)
#config.action_mailer.smtp_settings = {
# :address => "smtp.dresdener27.de",
# :port => 25,
# :domain => "dresdener27",
# :authentication => :login,
# :user_name => "benni@dresdener27.de",
# :password => "ben234go"
#}

View File

@ -2,6 +2,9 @@ ActionController::Routing::Routes.draw do |map|
map.my_profile '/home/profile', :controller => 'home', :action => 'profile' map.my_profile '/home/profile', :controller => 'home', :action => 'profile'
map.my_tasks '/home/tasks', :controller => 'tasks', :action => 'myTasks' map.my_tasks '/home/tasks', :controller => 'tasks', :action => 'myTasks'
map.resources :messages, :only => [:index, :show, :new, :create],
:member => { :reply => :get, :user => :get, :group => :get }
map.namespace :admin do |admin| map.namespace :admin do |admin|
admin.resources :users admin.resources :users
admin.resources :workgroups, :member => { :memberships => :get } admin.resources :workgroups, :member => { :memberships => :get }

View File

@ -0,0 +1,20 @@
class RefactorMessaging < ActiveRecord::Migration
def self.up
drop_table :messages
create_table :messages do |t|
t.references :sender
t.text :recipients_ids
t.string :subject, :null => false
t.text :body
t.integer :email_state, :default => 0, :null => false
t.boolean :private, :default => false
t.datetime :created_at
end
end
def self.down
end
end

View File

@ -9,7 +9,7 @@
# #
# It's strongly recommended to check this file into your version control system. # It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20090113111624) do ActiveRecord::Schema.define(:version => 20090114101610) do
create_table "article_categories", :force => true do |t| create_table "article_categories", :force => true do |t|
t.string "name", :default => "", :null => false t.string "name", :default => "", :null => false
@ -184,18 +184,14 @@ ActiveRecord::Schema.define(:version => 20090113111624) do
create_table "messages", :force => true do |t| create_table "messages", :force => true do |t|
t.integer "sender_id" t.integer "sender_id"
t.integer "recipient_id", :default => 0, :null => false t.text "recipients_ids", :null => false
t.string "recipients", :default => "", :null => false t.string "subject", :null => false
t.string "subject", :default => "", :null => false t.text "body"
t.text "body", :null => false t.integer "email_state", :default => 0, :null => false
t.boolean "read", :default => false, :null => false t.boolean "private", :default => false
t.integer "email_state", :default => 0, :null => false t.datetime "created_at"
t.datetime "created_on", :null => false
end end
add_index "messages", ["recipient_id"], :name => "index_messages_on_recipient_id"
add_index "messages", ["sender_id"], :name => "index_messages_on_sender_id"
create_table "order_article_results", :force => true do |t| create_table "order_article_results", :force => true do |t|
t.integer "order_id", :default => 0, :null => false t.integer "order_id", :default => 0, :null => false
t.string "name", :default => "", :null => false t.string "name", :default => "", :null => false

4
lib/tasks/messages.rake Normal file
View File

@ -0,0 +1,4 @@
desc "Deliver messages as emails"
task :send_emails => :environment do
Message.send_emails
end

View File

@ -239,7 +239,6 @@ table tfoot tr
:background-color #fff :background-color #fff
td td
:padding-top 0.8em :padding-top 0.8em
tr.edit_inline tr.edit_inline
:background-color = !hover_yellow :background-color = !hover_yellow

View File

@ -1,5 +1,5 @@
# == Schema Information # == Schema Information
# Schema version: 20090114101610 # Schema version: 20090115123421
# #
# Table name: articles # Table name: articles
# #

View File

@ -1,17 +1,16 @@
# == Schema Information # == Schema Information
# Schema version: 20090102171850 # Schema version: 20090115123421
# #
# Table name: messages # Table name: messages
# #
# id :integer(4) not null, primary key # id :integer(4) not null, primary key
# sender_id :integer(4) # sender_id :integer(4)
# recipient_id :integer(4) default(0), not null # recipients_ids :text default(""), not null
# recipients :string(255) default(""), not null # subject :string(255) not null
# subject :string(255) default(""), not null # body :text
# body :text default(""), not null # email_state :integer(4) default(0), not null
# read :boolean(1) not null # private :boolean(1)
# email_state :integer(4) default(0), not null # created_at :datetime
# created_on :datetime not null
# #
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html

View File

@ -1,5 +1,5 @@
# == Schema Information # == Schema Information
# Schema version: 20090114101610 # Schema version: 20090115123421
# #
# Table name: suppliers # Table name: suppliers
# #