public
Description: open-source e-commerce built on merb
Clone URL: git://github.com/myabc/merb_mart.git
Click here to lend your support to: merb_mart and make a donation at www.pledgie.com !
Changed license to GPL License.
Updated README to reflect change in design (no longer quick port of 
Substruct).
Renamed OrderUser to Customer.
Removed various content management (CMS) models.
Removed lines of Artistic License 1.0 encumbered, Substruct 
copy-and-pasted code from models and views.
Added ignore rule for NB projects in .gitignore.
Commented out various routing rules.
myabc (author)
Sun Apr 27 12:43:52 -0700 2008
commit  09233d02a8c662968d61f6defc28fef0ae266615
tree    6ab3efa3bcc3f96c34cc161ef4a785afda0e2463
parent  e09b81dd3255346cc794941b10ee05a2af507d5e
...
8
9
10
 
11
12
13
...
8
9
10
11
12
13
14
0
@@ -8,6 +8,7 @@ cache/*
0
 config/database.yml
0
 coverage
0
 gems
0
+nbproject
0
 pkg
0
 pkg/*
0
 tmp
...
1
2
3
4
5
...
1
 
 
2
3
0
@@ -1,4 +1,2 @@
0
 = Change Log
0
-
0
-pre-0.1: Changes from Substruct:
0
     
0
\ No newline at end of file
...
1
2
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
...
61
62
63
64
65
 
 
66
67
68
...
83
84
85
86
87
 
 
 
...
1
2
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
...
61
62
63
 
 
64
65
66
67
68
...
83
84
85
 
86
87
88
89
0
@@ -1,37 +1,37 @@
0
 MerbMart README
0
 ===============
0
 
0
-MerbMart is an *open-source e-commerce engine*, developed on top of the recent
0
-Ruby-language Merb MVC framework. Although MerbMart is designed for e-commerce
0
-sites of all sizes, the speed and scalability of the Merb framework make it
0
-scalable for even large online vendors.
0
-
0
-In addition to Merb framework, MerbMart is also built on the following open-
0
-source foundations:
0
-
0
- * DataMapper (0.9 branch), for object relation mapping (ORM) and persistence.
0
- * RSpec, for behavio(u)r driven development (BDD).
0
- * ActiveMerchant, for Credit Card, payment and shipping processing.
0
+MerbMart is an *open-source e-commerce application*, developed on top of the
0
+recent Ruby-language Merb MVC framework. Although MerbMart is designed for
0
+e-commerce sites of all sizes, the speed and scalability of the Merb framework
0
+make it scalable even for large online vendors.
0
+
0
+In addition to Merb framework, the following technologies and frameworks
0
+provide a foundation for MerbMart:
0
+
0
+ * **DataMapper** (bleeding-edge 0.9), for object relation mapping (ORM) and
0
+ persistence.
0
+ * **RSpec**, for behavio(u)r driven development (BDD).
0
+ * **ActiveMerchant**, for Credit Card, payment and shipping processing.
0
    as well as attachmerb\_fu, merb\_paginate.
0
 
0
 See INSTALL or the project wiki for a full list of dependencies.
0
 
0
-MerbMart is a loose port of the Substruct e-commerce application for Ruby-on-
0
-Rails. The initial 0.1 release of MerbMart will be a feature-equivalent port
0
-of Substruct 0.97. MerbMart borrows many ideas, its database entity-
0
-relationship design and some lines of code from Substruct, and is grateful to i
0
-ts developers for developing such a great application:
0
- http://code.google.com/p/substruct/
0
- http://substruct.subimage.com/
0
+MerbMart is inspired by other, Rails based e-commerce applications, including
0
+[Substruct][substruct] and [Spree][spree]. Although MerbMart started out as a
0
+project to port Substruct to Merb, the initial 0.1 release of MerbMart will
0
+instead be a its own implementation of an e-commerce engine, trying to match
0
+the feature sets other e-commerce applications, but taking advantages of the
0
+unique features of Merb and DataMapper.
0
 
0
-Developer ReadMe
0
-----------------
0
+Developer Notes
0
+---------------
0
 
0
 **WARNING** : MerbMart is at a very early development stages. At this stage,
0
 the application should be considered only for consumption by advanced Ruby and
0
 Merb developers. If you're looking for something for production consumption,
0
 or not yet ready to jump from Ruby on Rails, then we would strongly advise
0
-trying Substruct.
0
+trying [Substruct][substruct] or [Spree][spree].
0
 
0
 **REQUEST** : Your development support is very much appreciated. Please
0
 contact us below if you're interested in lending a hand with the development
0
@@ -61,8 +61,8 @@ MerbMart.
0
 Licensing and Copyright
0
 -----------------------
0
 
0
-MerbMart is released under the **Artistic License**. Copyright information,
0
-as well as a copy of the Artistic License may be found in the LICENSE file.
0
+This code is licensed under the **GNU Public License (GPL) v2**. Please see
0
+LICENSE for licensing and copyright information.
0
 
0
 Support
0
 -------
0
@@ -83,4 +83,6 @@ list:
0
  * **MerbMart homepage**: _coming soon_
0
  * Contact the developers directly:
0
     - <alex@alexcolesportfolio.com> | myabc on #datamapper, #merb IRC
0
-
0
\ No newline at end of file
0
+
0
+[substruct]:http://code.google.com/p/substruct/ "Substruct e-commerce project"
0
+[spree]:http://spreehq.org/ "Spree Online Commerce for Ruby on Rails"
...
1
2
3
4
5
6
7
8
9
10
11
12
...
 
 
1
2
 
 
 
 
 
3
4
5
0
@@ -1,11 +1,4 @@
0
-# Represents any type of user upload that's not an image.
0
-#
0
 class Asset < UserUpload
0
 
0
-# has_attachment :storage => :file_system,
0
-# :max_size => MAX_SIZE,
0
-# :path_prefix => 'public/system/'
0
-
0
-# validates_as_attachment
0
 
0
 end
0
\ No newline at end of file
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
...
 
 
1
2
3
4
5
 
 
 
 
 
 
 
 
 
6
7
0
@@ -1,17 +1,6 @@
0
-# Represents an image
0
-#
0
 class Image < UserUpload
0
 
0
   one_to_many :product_images
0
   one_to_many :products, :through => :product_images
0
 
0
-# has_attachment :content_type => :image,
0
-# :storage => :file_system,
0
-# :max_size => MAX_SIZE,
0
-# :thumbnails => { :thumb => '50x50>', :small => '200x200' },
0
-# :processor => 'MiniMagick',
0
-# :path_prefix => 'public/system/'
0
-#
0
-# validates_as_attachment
0
-
0
 end
0
\ No newline at end of file
...
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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
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
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
...
29
30
31
 
 
 
32
33
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
36
37
0
@@ -29,612 +29,8 @@ class Order
0
   property :shipping_cost, Float, :default => 0.0
0
   property :tax, Float, :default => 0.0, :nullable => false
0
 
0
- #property t.string :auth_transaction_id"
0
- #property t.integer :shipping_address_id", :default => 0, :null => false
0
- #property t.integer :billing_address_id", :default => 0, :null => false
0
   
0
   validates_presence_of :order_number
0
- # FIXME: fix validates_uniqueness_of
0
- #validates_uniqueness_of :order_number
0
-
0
- # CALLBACKS =================================================================
0
-
0
- # FIXME: callbacks
0
- #before_save :set_product_cost
0
- #before_save :set_promo_code
0
-
0
- # Sets product cost based on line items total before a save.
0
- def set_product_cost
0
- self.product_cost = self.line_items_total
0
- end
0
-
0
- # Modifies the order based on any promotion codes passed in.
0
- #
0
- # This can add discounts to the order or add items.
0
- #
0
- # Returns silently and just doesn't add the promo if something
0
- # is wrong.
0
- #
0
- def set_promo_code
0
- # Find promotion based on code entered
0
- promo = Promotion.first(:code => self.promotion_code)
0
-
0
- # No promo code? Not active? No deal...
0
- return if !promo || !promo.is_active?
0
-
0
- # Make sure it's valid to add
0
- if promo.minimum_cart_value
0
- return if promo.minimum_cart_value > self.total
0
- end
0
- logger.info "PROMO MIN CART VALUE PASSED"
0
-
0
- # Don't allow more than one promotion?
0
- # This destroys any line items created previously.
0
- self.promotion_line_item.destroy if self.promotion_line_item
0
-
0
- # Assign proper promotion ID
0
- self.promotion_id = promo.id
0
-
0
- # Add any line items necessary from promotion.
0
- oli = OrderLineItem.new
0
- logger.info "CREATED OLI"
0
- # Set name & item...
0
- oli.name = promo.description
0
- oli.item_id = promo.item_id
0
-
0
- # Figure out how to apply the promotion
0
- case promo.discount_type
0
- # Dollars
0
- when 0 then
0
- oli.quantity = 1
0
- oli.unit_price = -promo.discount_amount
0
- #
0
- # Percent
0
- when 1 then
0
- oli.quantity = 1
0
- oli.unit_price = -(self.total * (promo.discount_amount/100))
0
- #
0
- # Buy N get 1 free
0
- when 2 then
0
- item = self.order_line_items.detect { |i| i.item_id == promo.item_id }
0
- if item && item.quantity >= promo.discount_amount.to_i
0
- oli.quantity = item.quantity / promo.discount_amount.to_i
0
- logger.info "ITEM QUANTITY #{oli.quantity}"
0
- else
0
- return
0
- end
0
- end
0
-
0
- self.order_line_items << oli
0
- end
0
-
0
- # CLASS METHODS =============================================================
0
-
0
- # Searches an order
0
- # Uses order number, first name, last name
0
- def self.search(search_term, count=false, limit_sql=nil)
0
- if (count == true) then
0
- sql = "SELECT COUNT(*) "
0
- else
0
- sql = "SELECT DISTINCT orders.* "
0
- end
0
- sql << "FROM orders "
0
- sql << "JOIN order_addresses ON orders.order_user_id = order_addresses.order_user_id "
0
- sql << "WHERE orders.order_number = ? "
0
- sql << "OR order_addresses.first_name LIKE ? "
0
- sql << "OR order_addresses.last_name LIKE ? "
0
- sql << "OR CONCAT(order_addresses.first_name, ' ', order_addresses.last_name) LIKE ? "
0
- sql << "ORDER BY orders.created_on DESC "
0
- sql << "LIMIT #{limit_sql}" if limit_sql
0
- arg_arr = [sql, search_term, "%#{search_term}%", "%#{search_term}%", "%#{search_term}%"]
0
- if (count == true) then
0
- count_by_sql(arg_arr)
0
- else
0
- find_by_sql(arg_arr)
0
- end
0
- end
0
-
0
- # Finds orders by country
0
- #
0
- def self.find_by_country(country_id, count=false, limit_sql=nil)
0
- if (count == true) then
0
- sql = "SELECT COUNT(*) "
0
- else
0
- sql = "SELECT DISTINCT orders.* "
0
- end
0
- sql << "FROM orders "
0
- sql << "INNER JOIN order_users ON order_users.id = orders.order_user_id "
0
- sql << "INNER JOIN order_addresses ON ( "
0
- sql << " order_addresses.country_id = ? AND order_addresses.order_user_id = order_users.id "
0
- sql << ")"
0
- arg_arr = [sql, country_id]
0
- if (count == true) then
0
- count_by_sql(arg_arr)
0
- else
0
- find_by_sql(arg_arr)
0
- end
0
- end
0
-
0
- # Generates a unique order number.
0
- # This number isn't ID because we want to mask that from the customers.
0
- def self.generate_order_number
0
- record = Object.new
0
- while record
0
- random = rand(999999999)
0
- record = first(:conditions => ['order_number = ?', random])
0
- end
0
- return random
0
- end
0
-
0
- # Returns array of sales totals (hash) for a given year.
0
- # Hash contains
0
- # * :number_of_sales
0
- # * :sales_total
0
- # * :tax
0
- # * :shipping
0
- def self.get_totals_for_year(year)
0
- months = Array.new
0
- 0.upto(12) { |i|
0
- sql = "SELECT COUNT(*) AS number_of_sales, SUM(product_cost) AS sales_total, "
0
- sql << "SUM(tax) AS tax, SUM(shipping_cost) AS shipping "
0
- sql << "FROM orders "
0
- sql << "WHERE YEAR(created_on) = ? "
0
- if i != 0 then
0
- sql << "AND MONTH(created_on) = ? "
0
- end
0
- sql << "AND (order_status_code_id = 5 OR order_status_code_id = 6 OR order_status_code_id = 7) "
0
- sql << "LIMIT 0,1"
0
- if i != 0 then
0
- months[i] = self.find_by_sql([sql, year, i])[0]
0
- else
0
- months[i] = self.find_by_sql([sql, year])[0]
0
- end
0
- }
0
- return months
0
- end
0
-
0
- # Gets a CSV string that represents an order list.
0
- def self.get_csv_for_orders(order_list)
0
- require 'fastercsv'
0
- csv_string = FasterCSV.generate do |csv|
0
- # Do header generation 1st
0
- csv << [
0
- "OrderNumber", "Company", "ShippingType", "Date",
0
- "BillLastName", "BillFirstName", "BillAddress", "BillCity",
0
- "BillState", "BillZip", "BillCountry", "BillTelephone",
0
- "ShipLastName", "ShipFirstName", "ShipAddress", "ShipCity",
0
- "ShipState", "ShipZip", "ShipCountry", "ShipTelephone",
0
- "Item1",
0
- "Quantity1", "Item2", "Quantity2", "Item3", "Quantity3", "Item4",
0
- "Quantity4", "Item5", "Quantity5", "Item6", "Quantity6", "Item7",
0
- "Quantity7", "Item8", "Quantity8", "Item9", "Quantity9", "Item10",
0
- "Quantity10", "Item11", "Quantity11", "Item12", "Quantity12", "Item13",
0
- "Quantity13", "Item14", "Quantity14", "Item15", "Quantity15", "Item16",
0
- "Quantity16"
0
- ]
0
- for order in order_list
0
- bill = order.billing_address
0
- ship = order.shipping_address
0
- pretty_date = order.created_on.strftime("%m/%d/%y")
0
- if !order.order_shipping_type.nil?
0
- ship_code = order.order_shipping_type.code
0
- else
0
- ship_code = ''
0
- end
0
- order_arr = [
0
- order.order_number, '', ship_code, pretty_date,
0
- bill.last_name, bill.first_name, bill.address, bill.city,
0
- bill.state, bill.zip, bill.country.name, bill.telephone,
0
- ship.last_name, ship.first_name, ship.address, ship.city,
0
- ship.state, ship.zip, ship.country.name, ship.telephone
0
- ]
0
- item_arr = []
0
- # Generate spaces for items up to 16 deep
0
- 0.upto(15) do |i|
0
- item = order.order_line_items[i]
0
- if !item.nil? && !item.product.nil? then
0
- item_arr << item.product.code
0
- item_arr << item.quantity
0
- else
0
- item_arr << ''
0
- item_arr << ''
0
- end
0
- end
0
- # Add csv string by joining arrays
0
- csv << order_arr.concat(item_arr)
0
- end
0
- end
0
- return csv_string
0
- end
0
-
0
- # Returns an XML string for each order in the order list.
0
- # This format is for sending orders to Tony's Fine Foods
0
- def self.get_xml_for_orders(order_list)
0
- xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
0
- xml << "<orders>\n"
0
- for order in order_list
0
- if order.order_shipping_type
0
- shipping_type = order.order_shipping_type.code
0
- else
0
- shipping_type = ''
0
- end
0
- #pretty_date = order.created_on.strftime("%m/%d/%y")
0
- pretty_date = order.created_on
0
- xml << " <order>\n"
0
- xml << " <date>#{pretty_date}</date>\n"
0
- xml << " <shippingCode>#{shipping_type}</shippingCode>\n"
0
- xml << " <invoiceNumber>#{order.order_number}</invoiceNumber>\n"
0
- xml << " <emailAddress>#{order.order_user.email_address}</emailAddress>\n"
0
- # Shipping address
0
- address = order.shipping_address
0
- xml << " <shippingAddress>\n"
0
- xml << " <firstName>#{address.first_name}</firstName>\n"
0
- xml << " <lastName>#{address.last_name}</lastName>\n"
0
- xml << " <address1>#{address.address}</address1>\n"
0
- xml << " <address2></address2>\n"
0
- xml << " <city>#{address.city}</city>\n"
0
- xml << " <state>#{address.state}</state>\n"
0
- xml << " <zip>#{address.zip}</zip>\n"
0
- xml << " <countryCode>#{address.country.fedex_code}</countryCode>\n"
0
- xml << " <telephone>#{address.telephone}</telephone>\n"
0
- xml << " </shippingAddress>\n"
0
- # Items
0
- xml << " <items>\n"
0
- for item in order.order_line_items
0
- xml << " <item>\n"
0
- xml << " <name>#{item.product.name}</name>\n"
0
- xml << " <id>#{item.product.code}</id>\n"
0
- xml << " <quantity>#{item.quantity}</quantity>\n"
0
- xml << " </item>\n"
0
- end
0
- xml << " </items>\n"
0
- # End
0
- xml << " </order>\n"
0
- end
0
- # End orders
0
- xml << "</orders>\n"
0
- return xml
0
- end
0
-
0
-
0
- # INSTANCE METHODS ==========================================================
0
-
0
- # Shortcut to find order_line_item for a promotion that has been applied.
0
- def promotion_line_item
0
- if self.promotion
0
- return self.order_line_items.find_by_name(self.promotion.description)
0
- else
0
- return nil
0
- end
0
- end
0
-
0
- # Order status name
0
- def status
0
- code = OrderStatusCode.first(:id => self.order_status_code_id)
0
- code.name
0
- end
0
-
0
- # Shortcut to items
0
- def items
0
- self.order_line_items
0
- end
0
-
0
- # Total for the order, including shipping and tax.
0
- #
0
- def total
0
- logger.info "CALCULATING SHIPPING TOTAL"
0
- logger.info "LINE ITEMS TOTAL: #{self.line_items_total}"
0
- logger.info "SHIPPING COST: #{self.shipping_cost}"
0
- logger.info "TAX COST: #{self.tax_cost}"
0
- self.line_items_total + self.shipping_cost + self.tax_cost
0
- end
0
-
0
- # The tax of items if applied.
0
- #
0
- def tax_cost
0
- (self.line_items_total) * (self.tax/100)
0
- end
0
-
0
- def name
0
- return "#{billing_address.first_name} #{billing_address.last_name}"
0
- end
0
-
0
- def account
0
- self.order_account
0
- end
0
-
0
- # Sets line items from the product output table on the edit page.
0
- #
0
- # Deletes any line items with a quantity of 0.
0
- # Adds line items with a quantity > 0.
0
- #
0
- # This is called from update in our controllers.
0
- # What's passed looks something like this...
0
- # @products = {'1' => {'quantity' => 2}, '2' => {'quantity' => 0}, etc}
0
- def line_items=(products)
0
- # Clear out all line items
0
- self.order_line_items.clear
0
- # Go through all products
0
- products.each do |id, product|
0
- quantity = product['quantity']
0
- if quantity.blank? then
0
- quantity = 0
0
- else
0
- quantity = Integer(quantity)
0
- end
0
-
0
- if (quantity > 0) then
0
- new_item = self.order_line_items.build
0
- logger.info("\n\nBUILDING NEW LINE ITEM\n")
0
- logger.info(new_item.inspect+"\n")
0
- new_item.quantity = quantity
0
- new_item.item_id = id
0
- new_item.unit_price = Item[:id].price
0
- new_item.save
0
- end
0
- end
0
- end
0
-
0
- # Do we have a valid transaction id
0
- def contains_valid_transaction_id?()
0
- return (!self.auth_transaction_id.blank? && self.auth_transaction_id != 0)
0
- end
0
-
0
- # Determines if an order has a line item based on product id
0
- def has_line_item?(id)
0
- self.order_line_items.each do |item|
0
- return true if item.id == id
0
- end
0
- return false
0
- end
0
-
0
- # Gets quantity of a product if exists in current line items.
0
- def get_line_item_quantity(id)
0
- self.order_line_items.each do |item|
0
- return item.quantity if item.id == id
0
- end
0
- return 0
0
- end
0
-
0
- # Gets a subtotal for line items based on product id
0
- def get_line_item_total(id)
0
- self.order_line_items.each do |item|
0
- return item.total if item.id == id
0
- end
0
- return 0
0
- end
0
-
0
- # Grabs the total amount of all line items associated with this order
0
- def line_items_total
0
- total = 0
0
- for item in self.order_line_items
0
- total += item.total
0
- end
0
- return total
0
- end
0
-
0
- # Adds a new order note from the edit page.
0
- #
0
- # We display notes as read-only, so we only have to use a text field
0
- # instead of multiple records.
0
- def new_notes=(note)
0
- if !note.blank? then
0
- time = Time.now.strftime("%m-%d-%y %I:%M %p")
0
- new_note = "<p>#{note}<br/>"
0
- new_note << "<span class=\"info\">"
0
- new_note << "[#{time}]"
0
- new_note << "</span></p>"
0
- if self.notes.blank? then
0
- self.notes = new_note
0
- else
0
- self.notes << new_note
0
- end
0
- end
0
- end
0
-
0
- # Calculates the weight of an order
0
- def weight
0
- weight = 0
0
- self.order_line_items.each do |item|
0
- weight += item.quantity * item.product.weight rescue 0
0
- end
0
- return weight
0
- end
0
-
0
- # Gets a flat shipping price for an order.
0
- # This is if we're not using live rate calculation usually
0
- #
0
- # A lot of people will want this overridden in their app
0
- def get_flat_shipping_price
0
- return Preference.find_by_name('store_handling_fee').value.to_f
0
- end
0
-
0
- # Gets all LIVE shipping prices for an order.
0
- #
0
- # Returns an array of OrderShippingTypes
0
- def get_shipping_prices
0
- prices = []
0
- # If they're in the USA
0
- address = self.shipping_address
0
-
0
- # TODO - set this country_id as a preference in the admin UI
0
- #
0
- if address.country_id == 1 then
0
- shipping_types = OrderShippingType.get_domestic
0
- else
0
- shipping_types = OrderShippingType.get_foreign
0
- end
0
-
0
- for type in shipping_types
0
- type.calculate_price(self.weight)
0
- prices << type
0
- end
0
-
0
- return prices
0
-
0
- end
0
-
0
- # Runs an order transaction.
0
- # Farms out the work to an Authorize.net or PayPal method
0
- # (or one of your devising).
0
- #
0
- # Should return TRUE if the process is successful.
0
- # Should return AN ERROR MESSAGE if not...
0
- #
0
- def run_transaction
0
- cc_processor = Order.get_cc_processor
0
- if cc_processor == Preference::CC_PROCESSORS[0]
0
- run_transaction_authorize
0
- elsif cc_processor == Preference::CC_PROCESSORS[1]
0
- run_transaction_paypal_ipn
0
- else
0
- throw "The currently set preference for cc_processor is not recognized. You might want to add it to the code..."
0
- end
0
- end
0
  
0
- # Check to see which cc processor is used
0
- def self.get_cc_processor
0
- Preference.find_by_name('cc_processor').value
0
- end
0
-
0
- # Get the login info for the cc processor (if any)
0
- def self.get_cc_login
0
- Preference.find_by_name('cc_login').value
0
- end
0
-
0
- # Runs an order through Authorize.net
0
- #
0
- # Returns true
0
- #
0
- def run_transaction_authorize
0
- ba = self.billing_address
0
-
0
- # For debugging with a test account...
0
- # ActiveMerchant::Billing::Base.mode = :test
0
-