summaryrefslogtreecommitdiff
path: root/engines/support/app/models
diff options
context:
space:
mode:
Diffstat (limited to 'engines/support/app/models')
-rw-r--r--engines/support/app/models/account_extension/tickets.rb13
-rw-r--r--engines/support/app/models/ticket.rb105
-rw-r--r--engines/support/app/models/ticket_comment.rb43
-rw-r--r--engines/support/app/models/ticket_selection.rb71
4 files changed, 232 insertions, 0 deletions
diff --git a/engines/support/app/models/account_extension/tickets.rb b/engines/support/app/models/account_extension/tickets.rb
new file mode 100644
index 0000000..f898b56
--- /dev/null
+++ b/engines/support/app/models/account_extension/tickets.rb
@@ -0,0 +1,13 @@
+module AccountExtension::Tickets
+ extend ActiveSupport::Concern
+
+ def destroy_with_tickets
+ Ticket.destroy_all_from(self.user)
+ destroy_without_tickets
+ end
+
+ included do
+ alias_method_chain :destroy, :tickets
+ end
+
+end
diff --git a/engines/support/app/models/ticket.rb b/engines/support/app/models/ticket.rb
new file mode 100644
index 0000000..cd22758
--- /dev/null
+++ b/engines/support/app/models/ticket.rb
@@ -0,0 +1,105 @@
+#
+# TODO: thought i should reverse keys for descending, but that didn't work.
+# look into whether that should be tweaked, and whether it works okay with
+# pagination (seems to now...)
+#
+# TODO: better validation of email
+#
+# TODO: don't hardcode strings 'unknown user' and 'unauthenticated user'
+#
+class Ticket < CouchRest::Model::Base
+ use_database "tickets"
+
+ property :created_by, String, :protected => true # nil for anonymous tickets, should never be changed
+ property :regarding_user, String # may be nil or valid username
+ property :subject, String
+ property :email, String
+ property :is_open, TrueClass, :default => true
+ property :comments, [TicketComment]
+
+ timestamps!
+
+ before_validation :set_email, :set_regarding_user, :on => :create
+
+ design do
+ view :by_updated_at
+ view :by_created_at
+ view :by_created_by
+
+ view :by_is_open_and_created_at
+ view :by_is_open_and_updated_at
+
+ own_path = Pathname.new(File.dirname(__FILE__))
+ load_views(own_path.join('..', 'designs', 'ticket'))
+ end
+
+ validates :subject, :presence => true
+ validates :email, :allow_blank => true, :format => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/
+
+ def self.search(options = {})
+ @selection = TicketSelection.new(options)
+ @selection.tickets
+ end
+
+ def self.destroy_all_from(user)
+ self.by_created_by.key(user.id).each do |ticket|
+ ticket.destroy
+ end
+ end
+
+ def is_creator_validated?
+ !!created_by
+ end
+
+ def set_email
+ self.email = nil if self.email == ""
+ end
+
+ def set_regarding_user
+ self.regarding_user = nil if self.regarding_user == ""
+ end
+
+ def close
+ self.is_open = false
+ end
+
+ def reopen
+ self.is_open = true
+ end
+
+ def commenters
+ commenters = []
+ self.comments.each do |comment|
+ if comment.posted_by
+ if user = User.find(comment.posted_by)
+ commenters << user.login if user and !commenters.include?(user.login)
+ else
+ commenters << 'unknown user' if !commenters.include?('unknown user')
+ end
+ else
+ commenters << 'unauthenticated user' if !commenters.include?('unauthenticated user')
+ end
+ end
+ commenters.join(', ')
+ end
+
+ #
+ # update comments. User should be set by controller.
+ #
+ def comments_attributes=(attributes)
+ if attributes
+ comment = TicketComment.new(attributes.values.first)
+ comment.posted_at = Time.now
+ comments << comment
+ end
+ end
+
+ def created_by_user
+ User.find(self.created_by)
+ end
+
+ def regarding_user_actual_user
+ User.find_by_login(self.regarding_user)
+ end
+
+end
diff --git a/engines/support/app/models/ticket_comment.rb b/engines/support/app/models/ticket_comment.rb
new file mode 100644
index 0000000..bed5237
--- /dev/null
+++ b/engines/support/app/models/ticket_comment.rb
@@ -0,0 +1,43 @@
+class TicketComment
+ include CouchRest::Model::Embeddable
+
+ #belongs_to :ticket #is this best way to do it? will want to access all of a tickets comments, so maybe this isn't the way?
+ property :posted_by, String#, :protected => true #Integer#this should be current_user if that is set, meaning the user is logged in #cannot have it be protected and set via comments_attributes=. also, if it is protected and we set in the tickets_controller, it gets unset. TODO---is this okay to have it not protected and manually check it? We do not users to be able to set this.
+ # if the current user is not set, then we could just say the comment comes from an 'unauthenticated user', which would be somebody with the secret URL
+ property :posted_at, Time#, :protected => true
+ #property :posted_verified, TrueClass, :protected => true #should be true if current_user is set when the comment is created
+ property :body, String
+ property :private, TrueClass # private comments are only viewable by admins #this is checked when set, to make sure it was set by an admin
+
+ # ? timestamps!
+ validates :body, :presence => true
+ #before_validation :set_time#, :set_posted_by
+
+ #design do
+ # view :by_posted_at
+ # view :by_body
+ #end
+
+ def is_comment_validated?
+ !!posted_by
+ end
+
+ def posted_by_user
+ User.find(posted_by) if posted_by
+ end
+
+=begin
+ #TODO.
+ #this is resetting all comments associated with the ticket:
+ def set_time
+ self.posted_at = Time.now
+ end
+=end
+
+=begin
+ def set_posted_by
+ self.posted_by = User.current if User.current
+ end
+=end
+
+end
diff --git a/engines/support/app/models/ticket_selection.rb b/engines/support/app/models/ticket_selection.rb
new file mode 100644
index 0000000..74d5b78
--- /dev/null
+++ b/engines/support/app/models/ticket_selection.rb
@@ -0,0 +1,71 @@
+class TicketSelection
+
+ #
+ # supported options:
+ #
+ # user_id: id of the user (uuid string)
+ # open_status: open | closed | all
+ # sort_order: updated_at_desc | updated_at_asc | created_at_desc | created_at_asc
+ # admin_status: mine | all
+ # is_admin: true | false
+ #
+ def initialize(options = {})
+ @user_id = options[:user_id].gsub /[^a-z0-9]/, ''
+ @open_status = allow options[:open_status], 'open', 'closed', 'all'
+ @sort_order = allow options[:sort_order], 'updated_at_desc', 'updated_at_asc', 'created_at_desc', 'created_at_asc'
+ @admin_status = allow options[:admin_status], 'mine', 'all'
+ @is_admin = allow options[:is_admin], false, true
+ end
+
+ def tickets
+ Ticket.send(finder_method).startkey(startkey).endkey(endkey).send(order)
+ end
+
+ protected
+
+ def allow(source, *allowed)
+ if allowed.include?(source)
+ source
+ else
+ allowed.first
+ end
+ end
+
+ def finder_method
+ method = 'by_'
+ method += 'includes_post_by_and_' if only_mine?
+ method += 'is_open_and_' if @open_status != 'all'
+ method += @sort_order.sub(/_(de|a)sc$/, '')
+ end
+
+ def startkey
+ startkeys = []
+ startkeys << @user_id if only_mine?
+ startkeys << (@open_status == 'open') if @open_status != 'all'
+ startkeys << 0
+ startkeys = startkeys.join if startkeys.length == 1 # want string not array if just one thing in array
+ startkeys
+ end
+
+ def endkey
+ endtime = Time.now + 2.days # TODO. this obviously isn't ideal
+ if self.startkey.is_a?(Array)
+ endkeys = self.startkey
+ endkeys.pop
+ endkeys << endtime
+ else
+ endtime
+ end
+ end
+
+ def order
+ # we have defined the ascending method to return the view itself:
+ (@sort_order.end_with? 'desc') ? 'descending' : 'ascending'
+ end
+
+
+ def only_mine?
+ !@is_admin || @admin_status == 'mine'
+ end
+
+end