Class: ODDB::InfoInvoicer

Inherits:
Invoicer show all
Defined in:
src/plugin/info_invoicer.rb

Direct Known Subclasses

FachinfoInvoicer, PatinfoInvoicer

Constant Summary

Constants inherited from Invoicer

RECIPIENTS

Constants inherited from Plugin

ARCHIVE_PATH, RECIPIENTS

Instance Attribute Summary (collapse)

Instance Method Summary (collapse)

Methods inherited from Invoicer

#create_invoice, #ensure_yus_user, #resend_invoice, #rp2fr, #send_invoice

Methods inherited from Plugin

#initialize, #l10n_sessions, #log_info, #recipients, #report, #resolve_link, #update_rss_feeds

Methods included from HttpFile

#http_body, #http_file

Constructor Details

This class inherits a constructor from ODDB::Plugin

Instance Attribute Details

- (Object) invoice_number

Returns the value of attribute invoice_number



10
11
12
# File 'src/plugin/info_invoicer.rb', line 10

def invoice_number
  @invoice_number
end

Instance Method Details

- (Object) active_companies



15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'src/plugin/info_invoicer.rb', line 15

def active_companies
  active_companies = []
  @app.invoices.each_value { |inv|
    inv.items.each_value { |item|
      if(item.type == :annual_fee && (ptr = item.item_pointer) \
        && (seq = pointer_resolved(ptr)) && seq.is_a?(parent_item_class) \
        && (company = seq.company))
        active_companies.push(company.odba_instance)
      end
    }
  }
  active_companies.uniq!
  active_companies
end

- (Object) adjust_annual_fee(company, items)



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'src/plugin/info_invoicer.rb', line 29

def adjust_annual_fee(company, items)
  if(date = company.invoice_date(@infotype))
    diy = (date - (date << 12)).to_f
    short = date << 1
    items.each { |item|
      if(item.type == :annual_fee)
        tim = item.time
        item_date = Date.new(tim.year, tim.month, tim.day)
        exp = (!company.limit_invoice_duration && item_date > short) \
          ? (date >> 12) : date
        exp_time = Time.local(exp.year, exp.month, exp.day)
        days = (exp - item_date).to_f
        factor = days/diy
        item.data ||= {}
        item.data.update({:last_valid_date => exp, :days => days})
        item.quantity = factor
        item.expiry_time = exp_time
      end
    }
  end
end

- (Object) adjust_company_fee(company, items)



50
51
52
53
54
55
56
57
58
59
# File 'src/plugin/info_invoicer.rb', line 50

def adjust_company_fee(company, items)
  price = company.price(@infotype).to_i
  if(price > 0)
    items.each { |item|
      if(item.type == :annual_fee)
        item.price = price
      end
    }
  end
end

- (Object) adjust_overlap_fee(date, items)



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
# File 'src/plugin/info_invoicer.rb', line 60

def adjust_overlap_fee(date, items)
  first_invoice = items.any? { |item| item.type == :activation }
  date_end = (date >> 12)
  exp_time = Time.local(date_end.year, date_end.month, date_end.day)
  diy = (date_end - date).to_f
  items.each { |item|
    days = diy
    date_start = date
    if(!first_invoice && (tim = item.expiry_time))
      valid = Date.new(tim.year, tim.month, tim.day)
      if(valid > date_start)
        date_start = valid
        days = (date_end - valid).to_f
        factor = days/diy
        item.quantity = factor
      end
    end
    item.expiry_time = exp_time
    if(item.type == :annual_fee)
      item.data ||= {}
      item.data.update({
        :days => days,
        :first_valid_date => date_start, 
        :last_valid_date => date_end,
      })
    end
  }
end

- (Object) all_items



96
97
98
99
100
101
102
103
# File 'src/plugin/info_invoicer.rb', line 96

def all_items
  active = active_infos
  ## all items for which the product still exists 
  slate_items.reverse.select { |item| 
    # but only once per sequence.
    (item.type == :processing) || active.delete(unique_name(item))
  }
end

- (Object) annual_items



88
89
90
91
92
93
94
95
# File 'src/plugin/info_invoicer.rb', line 88

def annual_items
  active = active_infos
  ## all items for which the product still exists 
  slate_items.select { |item| 
    # but only once per sequence.
    item.type == :annual_fee && active.delete(unique_name(item))
  }
end

- (Object) filter_paid(items, date = @@today)



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
# File 'src/plugin/info_invoicer.rb', line 104

def filter_paid(items, date=@@today)
  ## Prinzipielles Vorgehen
  # Für jedes item in items:
  # Gibt es ein Invoice, welches nicht expired? ist 
  # und welches ein Item beinhaltet, das den typ 
  # :annual_fee hat und den selben unique_name wie item

  items = items.sort_by { |item| item.time }

  ## Vorgeschlagener Algorithmus
  # 1. alle invoices von app
  # 2. davon alle items, die nicht expired? und den 
  #    typ :annual_fee haben
  # 3. davon den unique_name
  # 4. -> neue Collection pointers
  fee_names = []
  prc_names = []
  @app.invoices.each_value { |invoice|
    invoice.items.each_value { |item|
      if(name = unique_name(item))
        if(item.type == :annual_fee && !item.expired?(date))
          fee_names.push(name)
        elsif(item.type == :processing && !item.expired?(date))
          prc_names.push(name)
        end
      end
    }
  }
  fee_names.uniq!
  prc_names.uniq!
  
  # 5. Duplikate löschen
  result = []
  items.each { |item| 
    ## as patinfos/fachinfos can be assigned to other sequences, check at
    #  least all sequences in the current registration for non-expired
    #  invoices
    names = neighborhood_unique_names(item)
    if(name = unique_name(item))
      if(item.type == :annual_fee && (fee_names & names).empty?)
        fee_names.push(name)
        result.push(item)
      elsif(item.type == :processing && (prc_names & names).empty?)
        prc_names.push(name)
        result.push(item)
      end
    end
  }
  result
end

- (Object) group_by_company(items)



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
# File 'src/plugin/info_invoicer.rb', line 154

def group_by_company(items)
  active_comps = active_companies
  companies = {}
  items.each { |item| 
    ptr = item.item_pointer
    if(seq = pointer_resolved(ptr))
      ## correct the item's stored name (it may have changed in Packungen.xls)
      (item.data ||= {})[:name] = seq.name if seq.respond_to?(:name)
      (companies[seq.company.odba_instance] ||= []).push(item)
    end
  }
  price = activation_fee
  companies.each { |company, items|
    time = items.collect { |item| item.time }.min
    unless(active_comps.include?(company))
      item = AbstractInvoiceItem.new
      item.price = price
      item.text = "Aufschaltgeb\374hr"
      item.time = time
      item.type = :activation
      item.unit = 'Einmalig'
      item.vat_rate = VAT_RATE
      items.unshift(item)
    end
  }
  companies
end

- (Object) html_items(day)



181
182
183
# File 'src/plugin/info_invoicer.rb', line 181

def html_items(day)
  [] # does not apply for fachinfos
end

- (Object) neighborhood_unique_names(item)



184
185
186
# File 'src/plugin/info_invoicer.rb', line 184

def neighborhood_unique_names(item)
  [] # does not apply for fachinfos
end

- (Object) parent_item_class



187
188
189
# File 'src/plugin/info_invoicer.rb', line 187

def parent_item_class
  Object
end

- (Object) pointer_resolved(pointer)



190
191
192
193
# File 'src/plugin/info_invoicer.rb', line 190

def pointer_resolved(pointer)
  pointer.resolve(@app)
rescue StandardError
end

- (Object) recent_items(day)

also takes a range of Dates



194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'src/plugin/info_invoicer.rb', line 194

def recent_items(day) # also takes a range of Dates
  fd = nil
  ld = nil
  if(day.is_a?(Range))
    fd = day.first
    ld = day.last.next
  else
    fd = day
    ld = day.next
  end
  ft = Time.local(fd.year, fd.month, fd.mday)
  lt = Time.local(ld.year, ld.month, ld.mday)
  range = ft...lt
  recents = all_items.select { |item|
    range.include?(item.time)
  }
  ## remove duplicate processing items
  active = active_infos
  recents.reject { |item| 
    item.type == :processing && !active.delete(unique_name(item))
  }
end

- (Object) run(day = @@today)



11
12
13
14
# File 'src/plugin/info_invoicer.rb', line 11

def run(day = @@today)
  send_daily_invoices(day - 1)
  send_annual_invoices(day)
end

- (Object) send_annual_invoices(day = @@today, company_name = nil, invoice_date = day)



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# File 'src/plugin/info_invoicer.rb', line 216

def send_annual_invoices(day = @@today, company_name=nil, invoice_date=day)
  items = annual_items
  ## augment with active html-patinfos
  items += html_items(day)
  time = Time.local(day.year + 1, day.month, day.day) + 1
  payable_items = filter_paid(items, time)
  groups = group_by_company(payable_items)
  groups.each { |company, items|
    ## if autoinvoice is disabled, but a preferred invoice_date is set, 
    ## invoice-start and -end-dates should be adjusted to that date.
    if(company.invoice_disabled?(@infotype))
      if(date = company.invoice_date(@infotype))
        if(date == day)
          date = company.invoice_dates[@infotype] = date + 1
          company.odba_store
        end
        time = Time.local(date.year, date.month, date.day)
        items.each { |item|
          if(item.respond_to?(:odba_store))
            item.expiry_time = time
            item.odba_store
          end
        }
      end
    elsif( = company.contact_email)
      if(!company.invoice_date(@infotype))
        time = items.collect { |item| item.time }.min
        date = Date.new(time.year, time.month, time.day)
        company.invoice_dates[@infotype] = date
        company.odba_store
      elsif(company_name == company.name)
        company.invoice_dates[@infotype] = day
        company.odba_store
      end
      if(company_name == company.name \
        || (company_name.nil? && day == company.invoice_date(@infotype)))
        ## work with duplicates
        items = items.collect { |item| item.dup }
        ## adjust the annual fee according to company settings
        adjust_company_fee(company, items)
        ## adjust the fee according to date
        adjust_overlap_fee(day, items)
        ensure_yus_user(company)
        ## first send the invoice 
        if ydim_id = send_invoice(invoice_date, , items, day)
          ## then store it in the database
          create_invoice(, items, ydim_id)
        end
      elsif((day >> 12) == company.invoice_date(@infotype))
        ## if the date has been set to one year from now,
        ## this invoice has already been sent manually.
        ## store the items anyway to prevent sending a 2-year
        ## invoice on the following day..
        create_invoice(, items, nil)
      end
    end
  }
end

- (Object) send_daily_invoices(day, company_name = nil, invoice_date = day)



274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
# File 'src/plugin/info_invoicer.rb', line 274

def send_daily_invoices(day, company_name=nil, invoice_date=day)
  items = recent_items(day)
  payable_items = filter_paid(items, day)
  groups = group_by_company(payable_items)
  groups.each { |company, items|
    if(!company.invoice_disabled?(@infotype) \
       && ( = company.contact_email) \
       && (company_name.nil? || company_name == company.name))
      ## work with duplicates
      items = items.collect { |item| item.dup }
      ## adjust the annual fee according to company settings
      adjust_company_fee(company, items)
      ## adjust the annual fee according to date
      adjust_annual_fee(company, items)
      ensure_yus_user(company)
      ## first send the invoice 
      if ydim_id = send_invoice(invoice_date, , items, day)
        ## then store it in the database
        create_invoice(, items, ydim_id)
      end
    end
  }
  nil
end

- (Object) slate_items



298
299
300
301
302
# File 'src/plugin/info_invoicer.rb', line 298

def slate_items
  @app.slate(@infotype).items.values.sort_by { |item|
    item.time
  }
end