Module: ActivityTypeModelHelper

Included in:
Activity::Adjustment, Activity::Labor, Activity::Material, Activity::Proposal
Defined in:
app/helpers/activity_type_model_helper.rb

Class Method Summary collapse

Class Method Details

.append_features(base) ⇒ Object



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'app/helpers/activity_type_model_helper.rb', line 3

def self.append_features(base)
  super
  
  base.class_eval do
    belongs_to :activity, :class_name => "::Activity"
    belongs_to :client, :class_name => "::Client"
    
    hack_an_association_join(:client) do |association|
      " LEFT OUTER JOIN %s ON %s.%s = %s.%s " % [
        association.klass.table_name, 
        association.aliased_table_name, 
        association.reflection.klass.primary_key,
        'activities', 
        association.klass.to_s.foreign_key
      ]
    end
    
    # Client hacks
    def []=(field,value)
      return activity.nil? ? nil : ( activity[:client_id] = value ) if field.to_sym == :client_id
      
      super field, value
    end
    
    def [](field)
      return activity.nil? ? nil : activity[:client_id] if field.to_sym == :client_id
  
      super field
    end
    
    def client=(value)
      build_activity if activity.nil? and value
      activity.client = value
    end
  
    class << self
      def client_arrange_include_param(args)
        # THis forces the :activity to always occur before :client in an :include
        args.each do |arg|
          if (
            arg.respond_to? :has_key? and
            arg.has_key? :include and
            arg[:include].respond_to? :include? and
            arg[:include].include? :client
          )
            arg[:include] = ([:activity] + arg[:include]).uniq
          end
        end
      end
      
      def find(*args)
        client_arrange_include_param args
        super(*args)
      end
  
      def count(*args)
        client_arrange_include_param args
        super(*args)
      end
    end
    # /Client Hacks
    
    # We use this when printing invoices, probably not the best way to do this, but its fine enough for now
    def as_legacy_ledger_row
      begin
        # We just do this to help when writing your activity types, as a starting point
        if label and comments and label.length > 0 and comments.length > 0
          description = '%s - %s' % [label, comments]
        else
          description = (label and label.length > 0) ? label : comments
        end
      rescue
        description = 'TODO: Lorem ipsum dolor sit amet, consectetuer adipiscing elit. '
      end
      
      [
       1,
       activity.cost,
       activity.cost,
       activity.activity_type.capitalize,
       occurred_on.strftime('%m/%d/%y'),
       description
      ]
    end

    # Generally useful accessors & utils for the activity association
    
    def column_for_attribute(name)
      # My hack to support the execute_callstack_for_multiparameter_attributes() set for occurred_on
      (name.to_sym == :occurred_on) ? OpenStruct.new( :klass => Time ) : super(name)
    end
    
    def is_published
      activity.is_published if activity
    end
    
    def occurred_on
      self.activity.occurred_on if activity
    end
    
    def cost
      self.activity.cost if activity
    end
    
    def tax
      self.activity.tax if activity
    end
    
    def type_quick_namer(*args)
      nil_label = '(None)'
      
      namer_format = args.shift
      
      args.map! do |a|   
        if a.nil?
          nil_label
        elsif a.respond_to? :name
          a.name
        else
          a.to_s
        end
      end
      
      args << ((activity.nil?) ? nil_label : activity.occurred_on.strftime("%m/%d/%Y %I:%M %p"))
      
      namer_format % args
    end
    
    # Activity hacks:
    alias build_activity_without_type_helper build_activity
    
    def build_activity(record = {})
      if /^[^\:]+\:\:(.+)$/.match(self.class.to_s)
        record[:activity_type] = $1.downcase
      end
      
      build_activity_without_type_helper record
    end
    
    # Published handling:
    def is_paid?
      (activity.nil?) ? false : activity.is_paid?
    end
    
    def is_published?
      (activity.nil?) ? false : activity.is_published?
    end
    
    before_destroy :ensure_not_published
      
    def ensure_not_published
      if is_published?
        errors.add_to_base "Can't destroy an activity once its invoice is published"
        return false
      end
    end
    
    def validate_on_update
      errors.add_to_base "Activity can't be adjusted once its invoice is published" if is_published? and changed_attributes.length > 0 
    end
    # /No updates/destroys
    
    # Event handlers:
    alias initialize_without_activity_type_helper initialize
    def initialize(*args)
      initialize_without_activity_type_helper(*args)
      build_activity if new_record? and activity.nil?
    end

    after_destroy { |record| record.activity.destroy }
    
    before_save { |record| record.activity.save if record.activity and record.activity.changed? }
    
    attr :dont_validate_activity_association
    def validate
      super
      
      unless dont_validate_activity_association
        if activity.nil?
          errors.add :activity, 'missing'
        else
          activity.dont_validate_type_associations = true
          activity.valid?
          activity.errors.each { |attr, msg| errors.add attr, msg }
        end
      end
    end
    
  end
end