shoppe 0.0.16 → 0.0.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +7 -0
  2. data/Rakefile +5 -6
  3. data/app/assets/javascripts/shoppe/application.coffee +19 -0
  4. data/app/assets/stylesheets/shoppe/application.scss +62 -20
  5. data/app/assets/stylesheets/shoppe/{chosen.css → chosen.scss} +18 -24
  6. data/app/assets/stylesheets/shoppe/dialog.scss +17 -2
  7. data/app/controllers/shoppe/orders_controller.rb +9 -7
  8. data/app/controllers/shoppe/payments_controller.rb +33 -0
  9. data/app/controllers/shoppe/settings_controller.rb +4 -0
  10. data/app/controllers/shoppe/tax_rates_controller.rb +1 -1
  11. data/app/controllers/shoppe/users_controller.rb +1 -1
  12. data/app/helpers/shoppe/application_helper.rb +0 -9
  13. data/app/models/shoppe/country.rb +17 -20
  14. data/app/models/shoppe/delivery_service.rb +16 -22
  15. data/app/models/shoppe/delivery_service_price.rb +10 -21
  16. data/app/models/shoppe/order/actions.rb +80 -0
  17. data/app/models/shoppe/order/billing.rb +99 -0
  18. data/app/models/shoppe/order/delivery.rb +196 -0
  19. data/app/models/shoppe/order/states.rb +69 -0
  20. data/app/models/shoppe/order.rb +29 -365
  21. data/app/models/shoppe/order_item.rb +52 -39
  22. data/app/models/shoppe/payment.rb +80 -0
  23. data/app/models/shoppe/product/product_attributes.rb +6 -4
  24. data/app/models/shoppe/product/variants.rb +20 -7
  25. data/app/models/shoppe/product.rb +37 -37
  26. data/app/models/shoppe/product_attribute.rb +13 -20
  27. data/app/models/shoppe/product_category.rb +6 -19
  28. data/app/models/shoppe/setting.rb +9 -0
  29. data/app/models/shoppe/stock_level_adjustment.rb +5 -18
  30. data/app/models/shoppe/tax_rate.rb +18 -21
  31. data/app/models/shoppe/user.rb +8 -15
  32. data/app/views/shoppe/delivery_service_prices/_form.html.haml +9 -3
  33. data/app/views/shoppe/delivery_service_prices/index.html.haml +6 -4
  34. data/app/views/shoppe/delivery_services/_form.html.haml +1 -1
  35. data/app/views/shoppe/orders/edit.html.haml +62 -0
  36. data/app/views/shoppe/orders/index.html.haml +2 -3
  37. data/app/views/shoppe/orders/show.html.haml +100 -63
  38. data/app/views/shoppe/payments/refund.html.haml +14 -0
  39. data/app/views/shoppe/product_categories/_form.html.haml +1 -1
  40. data/app/views/shoppe/products/_form.html.haml +8 -2
  41. data/app/views/shoppe/settings/edit.html.haml +1 -1
  42. data/app/views/shoppe/tax_rates/form.html.haml +5 -4
  43. data/app/views/shoppe/users/_form.html.haml +1 -1
  44. data/app/views/shoppe/variants/form.html.haml +2 -2
  45. data/config/routes.rb +3 -1
  46. data/db/migrate/20130926094549_create_shoppe_initial_schema.rb +1 -1
  47. data/db/migrate/20131024201501_add_address_type_to_shoppe_tax_rates.rb +5 -0
  48. data/db/migrate/20131024204815_create_shoppe_payments.rb +32 -0
  49. data/db/schema.rb +218 -0
  50. data/db/seeds.rb +15 -15
  51. data/lib/shoppe/engine.rb +7 -2
  52. data/lib/shoppe/errors/refund_failed.rb +15 -0
  53. data/lib/shoppe/settings.rb +0 -2
  54. data/lib/shoppe/version.rb +1 -1
  55. data/lib/shoppe/view_helpers.rb +16 -0
  56. data/lib/shoppe.rb +23 -6
  57. data/test/app/db/schema.rb +21 -6
  58. data/test/app/log/development.log +12782 -0
  59. data/test/app/tmp/cache/assets/development/sass/edac894564dae62b78e653a08d1c41f10ade93f9/application.scssc +0 -0
  60. data/test/app/tmp/cache/assets/development/sass/edac894564dae62b78e653a08d1c41f10ade93f9/chosen.scssc +0 -0
  61. data/test/app/tmp/cache/assets/development/sprockets/01d6eb5fc12044a487be4b93584690f2 +0 -0
  62. data/test/app/tmp/cache/assets/development/sprockets/02d3923383f72b56dd7919e301d22d24 +0 -0
  63. data/test/app/tmp/cache/assets/development/sprockets/0a6bca3e510625f255083bd154cc470b +0 -0
  64. data/test/app/tmp/cache/assets/development/sprockets/2f80004fb2e2ce07283a83ac15cf920a +0 -0
  65. data/test/app/tmp/cache/assets/development/sprockets/322295abdd8625fcce4da08f9565cc63 +0 -0
  66. data/test/app/tmp/cache/assets/development/sprockets/4c8cb5cfd87990ebddbaa5b5fd594be5 +0 -0
  67. data/test/app/tmp/cache/assets/development/sprockets/53c0f5159a54836310b1a3f5357bc4c6 +0 -0
  68. data/test/app/tmp/cache/assets/development/sprockets/7938636d16e11b754d4dd046b89863c4 +0 -0
  69. data/test/app/tmp/cache/assets/development/sprockets/7a90d9251a7c5506f33a3c72a224e571 +0 -0
  70. data/test/app/tmp/cache/assets/development/sprockets/9da17bb4868a0b762f8884db45c76ffd +0 -0
  71. data/test/app/tmp/cache/assets/development/sprockets/a692ba7ed6cff183bb840c2622233c87 +0 -0
  72. data/test/app/tmp/cache/assets/development/sprockets/a9befe910d55141b8ba02d8198b8f966 +0 -0
  73. data/test/app/tmp/cache/assets/development/sprockets/accc4dc17ef18d0b510917a005340da5 +0 -0
  74. data/test/app/tmp/cache/assets/development/sprockets/b9ad7ea18b7e55c3626a15d1dae142ed +0 -0
  75. data/test/app/tmp/cache/assets/development/sprockets/c733f1a2fe9d05a3a634ff64a394f64b +0 -0
  76. data/test/app/tmp/cache/assets/development/sprockets/da76586dcb6d9a408b2cf33307790d66 +0 -0
  77. metadata +62 -63
  78. data/README.rdoc +0 -1
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: dcbba75865dfb23d23a64375e7706b6664bc1d19
4
+ data.tar.gz: f5b5ae13ac740c329f9f1b693a42708c632e6530
5
+ SHA512:
6
+ metadata.gz: 8cab21ef5ecd835b5a6afb468c1aa5dbc2a6064ffe536e72e0da60f1bac1ce6c4b1d61b7e60a66e67366a9736bbb47b3afbd74cef97126d2061abeb05ad0786e
7
+ data.tar.gz: ac7abebddd19f138855ed9cc86bda752bf3a2eb9d6156f717abc5dc7f839ab2c48919057e206d4e5f0c51013295d5c1fa7e1b549b5156d52e86f055d39a737a7
data/Rakefile CHANGED
@@ -18,16 +18,15 @@ Rake::TestTask.new(:test) do |t|
18
18
  end
19
19
 
20
20
  namespace :shoppe do
21
-
22
- desc "Generate RDoc documentation into doc/"
23
- task :generate_docs do
24
- system("rm -Rf doc")
25
- system("bundle exec sdoc app/models lib README.rdoc")
21
+ desc 'Publish the release notes'
22
+ task :changelog do
23
+ system "scp CHANGELOG.md rubyapps@tryshoppe.com:/opt/rubyapps/shoppe-website/shared/CHANGELOG.md"
26
24
  end
27
25
 
28
26
  desc "Publish RDoc documentation from doc to api.tryshoppe.com"
29
- task :publish_docs do
27
+ task :docs do
30
28
  if File.exist?("doc")
29
+ system "yard"
31
30
  system "ssh root@tryshoppe.com rm -Rf /var/www/shoppe-api"
32
31
  system "scp -r doc root@tryshoppe.com:/var/www/shoppe-api"
33
32
  else
@@ -42,12 +42,23 @@ $ ->
42
42
  # Chosen
43
43
  $('select.chosen').chosen()
44
44
  $('select.chosen-with-deselect').chosen({allow_single_deselect: true})
45
+ $('select.chosen-basic').chosen({disable_search_threshold:100})
45
46
 
46
47
  # Printables
47
48
  $('a[rel=print]').on 'click', ->
48
49
  window.open($(this).attr('href'), 'despatchnote', 'width=700,height=800')
49
50
  false
50
51
 
52
+ # Order editting
53
+ toggleDeliveryFieldsetForOrder = ->
54
+ fieldset = $('form.edit_order fieldset.delivery')
55
+ if $('form.edit_order input#order_separate_delivery_address').prop('checked') then fieldset.show() else fieldset.hide()
56
+ $('form.edit_order input#order_separate_delivery_address').on 'change', toggleDeliveryFieldsetForOrder
57
+ toggleDeliveryFieldsetForOrder()
58
+
59
+ # Close dialog
60
+ $('body').on 'click', 'a[rel=closeDialog]', Nifty.Dialog.closeTopDialog
61
+
51
62
  # Open AJAX dialogs
52
63
  $('a[rel=dialog]').on 'click', ->
53
64
  element = $(this)
@@ -59,6 +70,14 @@ $ ->
59
70
  options.url = element.attr('href')
60
71
  Nifty.Dialog.open(options)
61
72
  false
73
+
74
+ # Format money values to 2 decimal places
75
+ formatMoneyField = ->
76
+ value = $(this).val()
77
+ if value.length
78
+ $(this).val(parseFloat(value).toFixed(2))
79
+ $('div.moneyInput input').each formatMoneyField
80
+ $('div.moneyInput input').on('blur', formatMoneyField)
62
81
 
63
82
  #
64
83
  # Stock Level Adjustment dialog beavior
@@ -129,17 +129,25 @@ header.main {
129
129
  &.received { color:#909091; background-image:image-url('shoppe/statuses/received.svg'); }
130
130
  }
131
131
 
132
+ //
133
+ // fieldset
134
+ //
135
+ fieldset {
136
+ border:1px solid #dce2eb;
137
+ background:#fff;
138
+ padding-top:15px;
139
+ padding-bottom:25px;
140
+ margin-bottom:15px;
141
+ legend {color:#5B6270; margin:0 25px; font-weight:300; font-size:1.5em;}
142
+ &.padded { padding:15px 25px 25px 25px;}
143
+ &.padded legend { margin:0;}
144
+ }
145
+
132
146
  //
133
147
  // forms
134
148
  //
135
149
  form {
136
150
  fieldset {
137
- border:1px solid #dce2eb;
138
- background:#fff;
139
- padding-top:15px;
140
- padding-bottom:25px;
141
- margin-bottom:15px;
142
- legend {color:#5B6270; margin:0 25px; font-weight:300; font-size:1.5em;}
143
151
 
144
152
  .splitContainer { margin:0 25px; margin-bottom:15px; height:50px;}
145
153
  .splitContainer:last-child { margin-bottom:0;}
@@ -162,6 +170,8 @@ header.main {
162
170
  padding-top:4px;
163
171
  input,label { margin-right:10px;}
164
172
  }
173
+ dd.space { margin-bottom:5px;}
174
+ dd.space:last-child { margin-bottom:0;}
165
175
  &.half {
166
176
  width:49%;
167
177
  margin:0;
@@ -272,6 +282,7 @@ header.main {
272
282
  dl {
273
283
  dt { float:left; width:30%; text-align:right; color:#888;white-space:nowrap}
274
284
  dd { font-weight:bold; margin-left:35%; margin-bottom:6px; white-space:nowrap}
285
+ dd a { color:inherit;}
275
286
  dt.padding { padding-top:6px;}
276
287
  }
277
288
 
@@ -289,7 +300,7 @@ header.main {
289
300
  margin:45px 0;
290
301
  overflow:hidden;
291
302
  ul {
292
- li { width:25%;float:left; text-align:center; background:image-url('shoppe/statuses/shipped.svg') no-repeat center 0; background-size:36px; padding-top:42px;z-index:10;}
303
+ li { width:33%;float:left; text-align:center; background:image-url('shoppe/statuses/shipped.svg') no-repeat center 0; background-size:36px; padding-top:42px;z-index:10;}
293
304
  h4 { color:#E32479;}
294
305
  li p { margin-top:5px; font-size:0.9em; color:#999;}
295
306
  li a { color:inherit;}
@@ -304,29 +315,50 @@ header.main {
304
315
  }
305
316
  }
306
317
 
307
- .notes {
308
- background:#fff;
309
- border:1px solid #CED2D8;
310
- p { padding:15px;}
311
- p textarea { border:0; padding:0; width:100%; resize:none; height:100px; font-family:$font; font-size:1.1em}
312
- h4 { background:#F7F9FC; padding:10px 15px; font-weight:500;}
313
- h4 input { float:right; margin-top:-3px;}
314
- }
315
-
316
318
  .order_items {
317
- margin:25px 0;
318
319
  table.data {
319
320
  .money { text-align:right; width:8%}
320
321
  .product { width:42%;}
321
322
  .sku { width:18%;}
322
323
  .qty {text-align:center; width:5%;}
323
- tfoot td { background:#5B6270; color:#fff; border:1px solid #5B6270; font-weight:bold; font-size:1.1em;}
324
324
  }
325
325
  }
326
326
  }
327
327
 
328
328
  //
329
- // orer search
329
+ // payments
330
+ //
331
+ fieldset.orderPayments {
332
+ h4 { font-weight:bold; text-transform:uppercase; color:#5B6270;}
333
+ .table {
334
+ margin-bottom:20px;
335
+ table td.refund { width:10%; text-align:center;}
336
+ table td.confirmed { width:5%; text-align:center;}
337
+ }
338
+ form {
339
+ overflow:hidden;
340
+ background:#F7F9FC;
341
+ border:1px solid #DCE2EB;
342
+ padding:15px;
343
+ dl {
344
+ width:23%;float:left;
345
+ dt { margin-bottom:4px; font-size:0.9em;color:#A9AEB5; font-weight:500;}
346
+ &.text { width:27%;margin-right:2%;}
347
+ &.amount { width:25%;}
348
+ &.submit { width:15%; text-align:right; margin-top:15px;}
349
+ }
350
+ }
351
+ p.notice {
352
+ background:#fffff3;
353
+ padding:10px;
354
+ color:#F67C00;
355
+ border:1px solid #F6B721;
356
+ margin-bottom:15px;
357
+ }
358
+ }
359
+
360
+ //
361
+ // order search
330
362
  //
331
363
  div.orderSearch {
332
364
  overflow:hidden;
@@ -366,13 +398,22 @@ footer {
366
398
  }
367
399
  }
368
400
 
369
- span.boolean span.true { color:#38BA4F}
401
+ span.boolean span.true { color:#96BF48}
370
402
  span.boolean span.false { color:#c04a4a}
371
403
 
372
404
  .float-right { float:right;}
373
405
 
374
406
  div.field_with_errors { display:inline;}
375
407
 
408
+ //
409
+ // money input box
410
+ //
411
+ div.moneyInput {
412
+ overflow:hidden;
413
+ div.currency {float:left; background:#f3f6ec; color:#74884a; padding:5px; width:20px; text-align:center;border:1px solid #c5ceb1; font-size:1.1em; border-right:0;}
414
+ input { width:100px; font-size:1.1em;}
415
+ }
416
+
376
417
  //
377
418
  // standard text input box
378
419
  //
@@ -425,6 +466,7 @@ div.table {
425
466
  td.desc input[type=text] { width:95%;}
426
467
  td.adjustment input[type=text] { width:50px; margin-right:5px;}
427
468
  }
469
+ tfoot td { background:#5B6270; color:#fff; border:1px solid #5B6270; font-weight:bold; font-size:1.1em;}
428
470
  }
429
471
  }
430
472
 
@@ -74,7 +74,7 @@
74
74
  display: block;
75
75
  width: 12px;
76
76
  height: 12px;
77
- background: url('chosen-sprite.png') -42px 1px no-repeat;
77
+ background: image-url('shoppe/chosen-sprite.png') -42px 1px no-repeat;
78
78
  font-size: 1px;
79
79
  }
80
80
  .chosen-container-single .chosen-single abbr:hover {
@@ -95,7 +95,7 @@
95
95
  display: block;
96
96
  width: 100%;
97
97
  height: 100%;
98
- background: url('chosen-sprite.png') no-repeat 0px 2px;
98
+ background: image-url('shoppe/chosen-sprite.png') no-repeat 0px 2px;
99
99
  }
100
100
  .chosen-container-single .chosen-search {
101
101
  position: relative;
@@ -114,12 +114,12 @@
114
114
  height: auto;
115
115
  outline: 0;
116
116
  border: 1px solid #ccc;
117
- background: white url('chosen-sprite.png') no-repeat 100% -20px;
118
- background: url('chosen-sprite.png') no-repeat 100% -20px, -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
119
- background: url('chosen-sprite.png') no-repeat 100% -20px, -webkit-linear-gradient(#eeeeee 1%, #ffffff 15%);
120
- background: url('chosen-sprite.png') no-repeat 100% -20px, -moz-linear-gradient(#eeeeee 1%, #ffffff 15%);
121
- background: url('chosen-sprite.png') no-repeat 100% -20px, -o-linear-gradient(#eeeeee 1%, #ffffff 15%);
122
- background: url('chosen-sprite.png') no-repeat 100% -20px, linear-gradient(#eeeeee 1%, #ffffff 15%);
117
+ background: white image-url('shoppe/chosen-sprite.png') no-repeat 100% -20px;
118
+ background: image-url('shoppe/chosen-sprite.png') no-repeat 100% -20px, -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
119
+ background: image-url('shoppe/chosen-sprite.png') no-repeat 100% -20px, -webkit-linear-gradient(#eeeeee 1%, #ffffff 15%);
120
+ background: image-url('shoppe/chosen-sprite.png') no-repeat 100% -20px, -moz-linear-gradient(#eeeeee 1%, #ffffff 15%);
121
+ background: image-url('shoppe/chosen-sprite.png') no-repeat 100% -20px, -o-linear-gradient(#eeeeee 1%, #ffffff 15%);
122
+ background: image-url('shoppe/chosen-sprite.png') no-repeat 100% -20px, linear-gradient(#eeeeee 1%, #ffffff 15%);
123
123
  font-size: 1em;
124
124
  font-family: sans-serif;
125
125
  line-height: normal;
@@ -197,17 +197,12 @@
197
197
  -moz-box-sizing: border-box;
198
198
  box-sizing: border-box;
199
199
  margin: 0;
200
- padding: 0;
200
+ padding: 5px;
201
201
  width: 100%;
202
202
  height: auto !important;
203
203
  height: 1%;
204
204
  border: 1px solid #ccc;
205
205
  background-color: #fff;
206
- background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
207
- background-image: -webkit-linear-gradient(#eeeeee 1%, #ffffff 15%);
208
- background-image: -moz-linear-gradient(#eeeeee 1%, #ffffff 15%);
209
- background-image: -o-linear-gradient(#eeeeee 1%, #ffffff 15%);
210
- background-image: linear-gradient(#eeeeee 1%, #ffffff 15%);
211
206
  cursor: text;
212
207
  }
213
208
  .chosen-container-multi .chosen-choices li {
@@ -261,7 +256,7 @@
261
256
  display: block;
262
257
  width: 12px;
263
258
  height: 12px;
264
- background: url('chosen-sprite.png') -42px 1px no-repeat;
259
+ background: image-url('shoppe/chosen-sprite.png') -42px 1px no-repeat;
265
260
  font-size: 1px;
266
261
  }
267
262
  .chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover {
@@ -298,7 +293,7 @@
298
293
  /* @group Active */
299
294
  .chosen-container-active .chosen-single {
300
295
  border: 1px solid #9AC835;
301
- box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
296
+ //box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
302
297
  }
303
298
  .chosen-container-active.chosen-with-drop .chosen-single {
304
299
  border: 1px solid #ccc;
@@ -322,7 +317,6 @@
322
317
  }
323
318
  .chosen-container-active .chosen-choices {
324
319
  border: 1px solid #9AC835;
325
- box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
326
320
  }
327
321
  .chosen-container-active .chosen-choices li.search-field input[type="text"] {
328
322
  color: #111 !important;
@@ -397,12 +391,12 @@
397
391
  }
398
392
  .chosen-rtl .chosen-search input[type="text"] {
399
393
  padding: 4px 5px 4px 20px;
400
- background: white url('chosen-sprite.png') no-repeat -30px -20px;
401
- background: url('chosen-sprite.png') no-repeat -30px -20px, -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
402
- background: url('chosen-sprite.png') no-repeat -30px -20px, -webkit-linear-gradient(#eeeeee 1%, #ffffff 15%);
403
- background: url('chosen-sprite.png') no-repeat -30px -20px, -moz-linear-gradient(#eeeeee 1%, #ffffff 15%);
404
- background: url('chosen-sprite.png') no-repeat -30px -20px, -o-linear-gradient(#eeeeee 1%, #ffffff 15%);
405
- background: url('chosen-sprite.png') no-repeat -30px -20px, linear-gradient(#eeeeee 1%, #ffffff 15%);
394
+ background: white image-url('shoppe/chosen-sprite.png') no-repeat -30px -20px;
395
+ background: image-url('shoppe/chosen-sprite.png') no-repeat -30px -20px, -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
396
+ background: image-url('shoppe/chosen-sprite.png') no-repeat -30px -20px, -webkit-linear-gradient(#eeeeee 1%, #ffffff 15%);
397
+ background: image-url('shoppe/chosen-sprite.png') no-repeat -30px -20px, -moz-linear-gradient(#eeeeee 1%, #ffffff 15%);
398
+ background: image-url('shoppe/chosen-sprite.png') no-repeat -30px -20px, -o-linear-gradient(#eeeeee 1%, #ffffff 15%);
399
+ background: image-url('shoppe/chosen-sprite.png') no-repeat -30px -20px, linear-gradient(#eeeeee 1%, #ffffff 15%);
406
400
  direction: rtl;
407
401
  }
408
402
  .chosen-rtl.chosen-container-single .chosen-single div b {
@@ -422,7 +416,7 @@
422
416
  .chosen-container-multi .chosen-choices .search-choice .search-choice-close,
423
417
  .chosen-container .chosen-results-scroll-down span,
424
418
  .chosen-container .chosen-results-scroll-up span {
425
- background-image: url('chosen-sprite@2x.png') !important;
419
+ background-image: image-url('shoppe/chosen-sprite@2x.png') !important;
426
420
  background-size: 52px 37px !important;
427
421
  background-repeat: no-repeat !important;
428
422
  }
@@ -1,10 +1,25 @@
1
1
  div.niftyDialog {
2
2
  h2 {
3
3
  background:#fff;
4
- border-bottom:1px solid #efefef;
5
- font-size:1.2em;
4
+ border:0;
5
+ padding:0;
6
+ font-size:1.3em;
7
+ border-bottom:1px solid #000;
8
+ padding-bottom:4px;
9
+ margin-bottom:10px;
6
10
  color:#111;
7
11
  }
8
12
  padding:15px;
9
13
  nav.pagination { margin:0; margin-top:15px;}
14
+ p.intro { line-height:1.5; color:#666; margin:6px 0;}
15
+
16
+ form.refundForm {
17
+ overflow:hidden;
18
+ margin:10px;
19
+ p.intro { margin-bottom:25px;}
20
+ .moneyInput { float:left; }
21
+ .moneyInput .currency { font-size:1.4em;}
22
+ .moneyInput input { font-size:1.4em}
23
+ p.submit { float:right;}
24
+ }
10
25
  }
@@ -8,10 +8,17 @@ module Shoppe
8
8
  @query = Shoppe::Order.ordered.received.includes(:order_items => :ordered_item).page(params[:page]).search(params[:q])
9
9
  @orders = @query.result
10
10
  end
11
+
12
+ def show
13
+ @payments = @order.payments.to_a
14
+ end
11
15
 
12
16
  def update
13
- @order.update_attributes!(params[:order].permit(:notes))
14
- redirect_to @order, :notice => "Order has been saved successfully"
17
+ if @order.update_attributes(params[:order].permit(:notes, :first_name, :last_name, :company, :billing_address1, :billing_address2, :billing_address3, :billing_address4, :billing_postcode, :billing_country_id, :separate_delivery_address,:delivery_name, :delivery_address1, :delivery_address2, :delivery_address3, :delivery_address4, :delivery_postcode, :delivery_country_id, :email_address, :phone_number))
18
+ redirect_to @order, :notice => "Order has been saved successfully"
19
+ else
20
+ render :action => "edit"
21
+ end
15
22
  end
16
23
 
17
24
  def search
@@ -34,11 +41,6 @@ module Shoppe
34
41
  redirect_to @order, :notice => "Order has been shipped successfully"
35
42
  end
36
43
 
37
- def pay
38
- @order.pay!(params[:payment_reference], params[:payment_method].blank? ? 'Unknown' : params[:payment_method])
39
- redirect_to @order, :notice => "Order has been marked as paid successfully"
40
- end
41
-
42
44
  def despatch_note
43
45
  render :layout => 'shoppe/printable'
44
46
  end
@@ -0,0 +1,33 @@
1
+ module Shoppe
2
+ class PaymentsController < ApplicationController
3
+
4
+ before_filter { @order = Shoppe::Order.find(params[:order_id]) }
5
+ before_filter { params[:id] && @payment = @order.payments.find(params[:id]) }
6
+
7
+ def create
8
+ payment = @order.payments.build(params[:payment].permit(:amount, :method, :reference))
9
+ if payment.save
10
+ redirect_to @order, :notice => "Payment has been added successfully"
11
+ else
12
+ redirect_to @order, :alert => payment.errors.full_messages.to_sentence
13
+ end
14
+ end
15
+
16
+ def destroy
17
+ @payment.destroy
18
+ redirect_to @order, :notice => "Payment has been removed successfully"
19
+ end
20
+
21
+ def refund
22
+ if request.post?
23
+ @payment.refund!(params[:amount])
24
+ redirect_to @order, :notice => "Refund has been processed successfully."
25
+ else
26
+ render :layout => false
27
+ end
28
+ rescue Shoppe::Errors::RefundFailed => e
29
+ redirect_to @order, :alert => e.message
30
+ end
31
+
32
+ end
33
+ end
@@ -4,6 +4,10 @@ module Shoppe
4
4
  before_filter { @active_nav = :settings }
5
5
 
6
6
  def update
7
+ if Shoppe.settings.demo_mode?
8
+ raise Shoppe::Error, "You cannot make changes to settings in demo mode. Sorry about that."
9
+ end
10
+
7
11
  Shoppe::Setting.update_from_hash(params[:settings].permit!)
8
12
  redirect_to :settings, :notice => "Settings have been updated successfully."
9
13
  end
@@ -42,7 +42,7 @@ module Shoppe
42
42
  private
43
43
 
44
44
  def safe_params
45
- params[:tax_rate].permit(:name, :rate, :country_ids => [])
45
+ params[:tax_rate].permit(:name, :rate, :address_type, :country_ids => [])
46
46
  end
47
47
 
48
48
  end
@@ -5,7 +5,7 @@ module Shoppe
5
5
  before_filter { params[:id] && @user = Shoppe::User.find(params[:id]) }
6
6
  before_filter(:only => [:create, :update, :destroy]) do
7
7
  if Shoppe.settings.demo_mode?
8
- raise Shoppe::Error, "You cannot make changes to user in demo mode. Sorry about that."
8
+ raise Shoppe::Error, "You cannot make changes to users in demo mode. Sorry about that."
9
9
  end
10
10
  end
11
11
 
@@ -1,15 +1,6 @@
1
1
  module Shoppe
2
2
  module ApplicationHelper
3
3
 
4
- def number_to_currency(number, options = {})
5
- options[:unit] ||= Shoppe.settings.currency_unit
6
- super
7
- end
8
-
9
- def number_to_weight(kg)
10
- "#{kg}#{t('shoppe.helpers.number_to_weight.kg', :default => 'kg')}"
11
- end
12
-
13
4
  def status_tag(status)
14
5
  content_tag :span, status, :class => "status-tag #{status}"
15
6
  end
@@ -1,30 +1,27 @@
1
- # == Schema Information
2
- #
3
- # Table name: shoppe_countries
4
- #
5
- # id :integer not null, primary key
6
- # name :string(255)
7
- # code2 :string(255)
8
- # code3 :string(255)
9
- # continent :string(255)
10
- # tld :string(255)
11
- # currency :string(255)
12
- # eu_member :boolean default(FALSE)
13
- #
14
-
15
1
  module Shoppe
2
+
3
+ # The Shoppe::Country model stores countries which can be used for delivery & billing
4
+ # addresses for orders.
5
+ #
6
+ # You can use the Shoppe::CountryImporter to import a pre-defined list of countries
7
+ # into your database. This automatically happens when you run the 'shoppe:setup'
8
+ # rake task.
9
+
16
10
  class Country < ActiveRecord::Base
17
-
18
- # Set the table name
11
+
19
12
  self.table_name = 'shoppe_countries'
20
-
21
- # Relationships
13
+
14
+ # All orders which have this country set as their billing country
22
15
  has_many :billed_orders, :dependent => :restrict_with_exception, :class_name => 'Shoppe::Order', :foreign_key => 'billing_country_id'
23
- has_many :delivered_orders, :dependent => :restrict_with_exception, :class_name => 'Shoppe::Order', :foreign_key => 'delivery_country_id'
24
16
 
17
+ # All orders which have this country set as their delivery country
18
+ has_many :delivered_orders, :dependent => :restrict_with_exception, :class_name => 'Shoppe::Order', :foreign_key => 'delivery_country_id'
25
19
 
26
- # Scopes
20
+ # All countries ordered by their name asending
27
21
  scope :ordered, -> { order('shoppe_countries.name asc') }
28
22
 
23
+ # Validations
24
+ validates :name, :presence => true
25
+
29
26
  end
30
27
  end
@@ -1,38 +1,32 @@
1
- # == Schema Information
2
- #
3
- # Table name: shoppe_delivery_services
4
- #
5
- # id :integer not null, primary key
6
- # name :string(255)
7
- # code :string(255)
8
- # default :boolean default(FALSE)
9
- # active :boolean default(TRUE)
10
- # created_at :datetime
11
- # updated_at :datetime
12
- # courier :string(255)
13
- # tracking_url :string(255)
14
- #
15
-
16
1
  module Shoppe
17
2
  class DeliveryService < ActiveRecord::Base
18
3
 
19
- # Set the table name
20
4
  self.table_name = 'shoppe_delivery_services'
21
-
5
+
22
6
  # Validations
23
7
  validates :name, :presence => true
24
8
  validates :courier, :presence => true
25
9
 
26
- # Relationships
10
+ # Orders which are assigned to this delivery service
27
11
  has_many :orders, :dependent => :restrict_with_exception, :class_name => 'Shoppe::Order'
12
+
13
+ # Prices for the different levels of service within this delivery service
28
14
  has_many :delivery_service_prices, :dependent => :destroy, :class_name => 'Shoppe::DeliveryServicePrice'
29
15
 
30
- # Scopes
16
+ # All active delivery services
31
17
  scope :active, -> { where(:active => true)}
32
18
 
33
- # Return the tracking URL for the given consignment number
34
- def tracking_url_for(consignment_number)
35
- tracking_url.gsub("{{consignment_number}}", consignment_number)
19
+ # Returns a tracking URL for the passed order
20
+ #
21
+ # @param order [Shoppe::Order]
22
+ # @return [String] the full URL for the order.
23
+ def tracking_url_for(order)
24
+ return nil if self.tracking_url.blank?
25
+ tracking_url = self.tracking_url.dup
26
+ tracking_url.gsub!("{{consignment_number}}", CGI.escape(order.consignment_number.to_s))
27
+ tracking_url.gsub!("{{delivery_postcode}}", CGI.escape(order.delivery_postcode.to_s))
28
+ tracking_url.gsub!("{{billing_postcode}}", CGI.escape(order.billing_postcode.to_s))
29
+ tracking_url
36
30
  end
37
31
 
38
32
  end
@@ -1,41 +1,30 @@
1
- # == Schema Information
2
- #
3
- # Table name: shoppe_delivery_service_prices
4
- #
5
- # id :integer not null, primary key
6
- # delivery_service_id :integer
7
- # code :string(255)
8
- # price :decimal(8, 2)
9
- # cost_price :decimal(8, 2)
10
- # tax_rate_id :integer
11
- # min_weight :decimal(8, 2)
12
- # max_weight :decimal(8, 2)
13
- # created_at :datetime
14
- # updated_at :datetime
15
- # country_ids :text
16
- #
17
-
18
1
  module Shoppe
19
2
  class DeliveryServicePrice < ActiveRecord::Base
20
3
 
21
4
  # Set the table name
22
5
  self.table_name = 'shoppe_delivery_service_prices'
23
6
 
24
- # Tax rates are associated with countries
25
7
  include Shoppe::AssociatedCountries
26
8
 
27
- # Relationships
9
+ # The delivery service which this price belongs to
28
10
  belongs_to :delivery_service, :class_name => 'Shoppe::DeliveryService'
11
+
12
+ # The tax rate which should be applied
29
13
  belongs_to :tax_rate, :class_name => "Shoppe::TaxRate"
30
-
14
+
31
15
  # Validations
16
+ validates :code, :presence => true
32
17
  validates :price, :numericality => true
33
18
  validates :cost_price, :numericality => true, :allow_blank => true
34
19
  validates :min_weight, :numericality => true
35
20
  validates :max_weight, :numericality => true
36
21
 
37
- # Scopes
22
+ # All prices ordered by their price ascending
38
23
  scope :ordered, -> { order('price asc')}
24
+
25
+ # All prices which are suitable for the weight passed.
26
+ #
27
+ # @param weight [BigDecimal] the weight of the order
39
28
  scope :for_weight, -> weight { where("min_weight <= ? AND max_weight >= ?", weight, weight) }
40
29
 
41
30
  end